需求:自動化組提出需要,要對IIS上的站點進行監控,異常停止後報警
需求分析:這站點的運行正常需要多方面的監控,如站點,程序池,資源,所以針對這需求做了三方面的監控。
站點狀態的監控
站點對應的程序池的監控
URL的監控,監控url能返回200的狀態碼
數據庫設計:
頁面展示:
配置list頁
配置Detail頁
預警郵件:
核心代碼:
配置頁面代碼
index.cshtml
@model IEnumerable<Ctrip.Hotel.QA.Platform.Data.Dao.EnvRunStatusMonitorConfig> @{ ViewBag.Title = "Run Monitor"; } @Styles.Render("~/Content/themes/metro/css") @Styles.Render("~/Content/themes/custom/chcore.css") @Styles.Render("~/Content/themes/fakeloader/fakeloader.css") @Scripts.Render("~/scripts/metro/jquery.dataTables.min.js") @Scripts.Render("~/Scripts/custom/chcoreui.js") @Scripts.Render("~/scripts/pages/runmonitor.js") <div class="grid" style="margin-top:50px;"> <div class="row cells12"> <div class="cell colspan10 offset1" id="divState"> </div> </div> <div class="row cells12"> <div class="cell colspan10 offset1" id="divContainer"> <div style="margin-left:0px;"> <button class="refreshbtn button primary" style="width:100px" onclick="eidtRunStatusMonitorConfigPage.refresh();"> <span class="mif-loop2"></span> 刷新 </button> <button class="addapppoolmonitorbtn button success" style="width:100px" onclick="eidtRunStatusMonitorConfigPage.showEditDialog('editConfigDialog', 0)"> <span class="mif-plus"></span> 新建 </button> </div> <table id="runMonitorTable" class="dataTable striped border bordered hovered" data-role="datatable" data-searching="true"> <thead> <tr> <th><button class="invokeallbtn button warning" style="width:50px;">喚醒</button></th> <th>監控器名</th> <th>站點名</th> <th>字站點名</th> <th>機器名</th> <th style="text-align:center">ip</th> <th style="text-align:center">啓動</th> <th style="text-align:center">Action</th> </tr> </thead> <tfoot> <tr> <th><button class="invokeallbtn button warning">喚醒</button></th> <th>監控器名</th> <th>站點名</th> <th>字站點名</th> <th>機器名</th> <th style="text-align:center">ip</th> <th style="text-align:center">開啓</th> <th style="text-align:center">Action</th> </tr> </tfoot> <tbody> @foreach (var item in Model) { <tr> <td style="text-align:center;"><span class="fg-cyan mif-play invokebtn"></span></td> <td> @Html.DisplayFor(modelItem => item.Name) </td> <td> @Html.DisplayFor(modelItem => item.DomainName) </td> <td> @Html.DisplayFor(modelItem => item.NodeName) </td> <td> @Html.DisplayFor(modelItem => item.MachineName) </td> <td> @Html.DisplayFor(modelItem => item.Ip) </td> <td> <label class="switch"> @if (item.TurnOn == 1) { <input type="checkbox" id="turnOn" checked onchange="eidtRunStatusMonitorConfigPage.postTurnOff(@Html.DisplayFor(modelItem => item.Id))" /> } else { <input type="checkbox" id="turnOn" onchange="eidtRunStatusMonitorConfigPage.postTurnOn(@Html.DisplayFor(modelItem => item.Id))" /> } <span class="check"></span> </label> </td> <td> <span class="mif-pencil fg-green" onclick="eidtRunStatusMonitorConfigPage.showEditDialog('editConfigDialog', @Html.DisplayFor(modelItem => item.Id))"></span> <span class="mif-cancel fg-red" onclick="eidtRunStatusMonitorConfigPage.deleteConfig(@Html.DisplayFor(modelItem => item.Id))"></span> </td> </tr> } </tbody> </table> </div> </div> </div> <div data-role="dialog" id="editConfigDialog" class="padding20" data-close-button="true" data-overlay="true" data-overlay-color="op-dark" > <h3>運行狀態監控配置:</h3><hr/> <div class="metro"> <div style="width:620px"> <div class="grid"> <div class="row"> <div id="subDiv" class="input-control full-size" data-role="select" data-placeholder="請選擇環境" data-allow-clear="true"> <select class="full-size" id="sub"></select> </div> <div id="templateDiv" class="input-control full-size" data-role="select" data-placeholder="請選擇站點" data-allow-clear="true"> <select class="full-size" id="template"></select> </div> <div id="nodeDiv" class="input-control full-size" data-role="select" data-placeholder="請選擇應用" data-allow-clear="true"> <select class="full-size" id="node"></select> </div> </div> <div class="row" id="ipAndPoolInfoDiv" style="display:none"> <div class="span2"> <div style="float:left;display:inline;font-weight:bold;margin-left:10px"> IP: </div> <div id="ip" style="float:left;display:inline;"> 10.2.3.410 </div> </div> <div class="span6"> <div style="float:left;display:inline;font-weight:bold;"> 程序池: </div> <div id="apppool" style="float:left;display:inline;"> hotel-vendor-interfaceadapter </div> </div> </div> <div class="row"> <div class="span8"> <label class="switch" style="float:left;display:inline;margin-left:10px;"> <input type="checkbox" checked id="turnOn"> <span class="check"></span> 開啓監控 </label> <label class="switch" style="float:left;display:inline;margin-left:50px;"> <input type="checkbox" checked id="emailOn"> <span class="check"></span> 收郵件 </label> </div> </div> <div class="row"> <div class="span8"> <div style="float:left;display:inline;margin-top:10px;margin-left:10px;font-weight:bold;"> Monitor Name: </div> <div style="float:left;display:inline;margin-left:10px;width:490px"> <!-- Input with clear helper --> <div class="input-control text" data-role="input"> <input type="text" id="monitorName"> <button class="button helper-button clear"><span class="mif-cross"></span></button> </div> </div> </div> </div> <div class="row"> <div class="span8"> <label class="switch" style="float:left;display:inline;margin-left:10px;"> <input type="checkbox" id="siteOn"> <span class="check"></span> 監控站點 </label> <label class="switch" style="float:left;display:inline;margin-left:50px;"> <input type="checkbox" id="poolOn"> <span class="check"></span> 監控程序池 </label> <label class="switch" style="float:left;display:inline;margin-left:50px;"> <input type="checkbox" checked id="urlOn"> <span class="check"></span> 監控Url返回200 </label> </div> </div> <div class="row" id="urlDiv"> <div class="span8"> <div style="float:left;display:inline;margin-top:10px;margin-left:10px;font-weight:bold;"> url: </div> <!-- Input with clear helper --> <div class="input-control text" data-role="input" style="float:left;display:inline;margin-left:10px;width:566px"> <input type="text" id="url"> <button class="button helper-button clear"><span class="mif-cross"></span></button> </div> </div> </div> <div class="row"> <div class="span8"> <div style="float:left;display:inline;margin-left:10px;font-weight:bold;"> 收件人: </div> <div class="input-control textarea " data-role="input-control" style="float:left;display:inline;width:100%"> <textarea id="recievers"></textarea> </div> </div> </div> </div> <div style="display:inline-block; text-align:right;width:100%"> <button id="comitSettingBtn" class="primary"><i class="icon-checkmark on-left"></i>確認</button> <button id="cancelCommitBtn" class="danger"><i class=" icon-cancel-2 on-left"></i>取消</button> <button id="closeCommitBtn" class="warning"><i class=" icon-cancel-2 on-left"></i>關閉</button> </div> </div> </div> </div>
js代碼:
////// 頁面初始化加載 ////// $(document).ready(function () { }); function showDialog(dialogId) { var dialog = $("#" + dialogId).data('dialog'); if (!dialog.element.data('opened')) { dialog.open(); } else { dialog.close(); } } function closeDialog(dialogId) { var dialog = $("#" + dialogId).data('dialog'); if (!dialog.element.data('closed')) { dialog.close(); } else { dialog.open(); } } var RunStatusMonitorConfigListPage = { refresh: function () { window.location.href = window.location.href; } } var eidtRunStatusMonitorConfigPage = { showEditDialog: function (dialogId, configId) { eidtRunStatusMonitorConfigPage.bingConfigDialogInfo(configId); $('#comitSettingBtn').click(function () { eidtRunStatusMonitorConfigPage.commitMonitorConfig(); }); $('#cancelCommitBtn').click(function () { eidtRunStatusMonitorConfigPage.showEditDialog(dialogId, configId); }); $('#closeCommitBtn').click(function () { closeDialog(dialogId); }); showDialog(dialogId); }, bingConfigDialogInfo: function (id) { var subSelect = $("#sub"); var templateSelect = $("#template"); var nodeSelect = $("#node"); // 綁定數據 if (id != 0) { $.getJSON('/RunMonitor/GetMonitorSetting?id=' + id, null, function (data) { if (data) { subSelect.empty(); subSelect.append("<option></option><option value=" + data.Data.SubId + " select>" + data.Data.SubName + "</option>"); templateSelect.empty(); templateSelect.append("<option></option><option value=" + data.Data.DomainId + " select>" + data.Data.DomainName + "</option>"); nodeSelect.empty(); nodeSelect.append("<option></option><option value=" + data.Data.NodeId + " select >" + data.Data.NodeName + "</option>"); $("#ipAndPoolInfoDiv").removeAttr("style"); $("#ip").html(data.Data.Ip); $("#apppool").html(data.Data.PoolName); if (data.Data.TurnOn == 1) { $("#turnOn").attr("checked", true); } else { $("#turnOn").attr("checked", false); } if (data.Data.EmailOn == 1) { $("#emailOn").attr("checked", true); } else { $("#emailOn").attr("checked", false); } if (data.Data.CheckSiteOn == 1) { $("#siteOn").attr("checked", true); } else { $("#siteOn").attr("checked", false); } if (data.Data.CheckPoolOn == 1) { $("#poolOn").attr("checked", true); } else { $("#poolOn").attr("checked", false); } if (data.Data.CheckUrlOn == 1) { $("#urlOn").attr("checked", true); } else { $("#urlOn").attr("checked", false); } $("#monitorName").val(data.Data.Name); $("#url").val(data.Data.Url); $("#recievers").val(data.Data.Reciever); } }); } else { // 綁定環境 subSelect.empty(); $.getJSON('/env/GetAllEnvSubs', null, function (data) { if (data.StateCode == 0) { var content = "<option></option>"; $.each(data.Data, function (idx, item) { content += "<option value=" + item.EnvSubId + ">" + item.EnvSubName + "</option>" }); subSelect.append(content); } }); // 綁定站點 templateSelect.empty(); $.getJSON('/DomainTemplate/GetAllEnvDomainTemplates', null, function (data) { if (data.StateCode == 0) { var content = "<option></option>"; $.each(data.Data, function (idx, item) { content += "<option value=" + item.Id + ">" + item.DomainName + "</option>" }); templateSelect.append(content); } }); //綁定onchange事件 templateSelect.change(function () { // 綁定子站點 eidtRunStatusMonitorConfigPage.bingDomainNode(templateSelect.val(), 0); }); } }, bingDomainNode: function (templateid, nodeid) { var nodeSelect = $("#node"); nodeSelect.empty(); $.getJSON('/DomainTemplate/GetDomainNodeTemplate?id=' + templateid, null, function (data) { if (data.StateCode == 0) { var content = "<option select>請選擇子站點</option><option>全部</option>"; $.each(data.Data, function (idx, item) { content += "<option value=" + item.Id + ">" + item.NodeName + "</option>" }); nodeSelect.append(content); if (nodeid != 0) { $("#node option[@value='" + nodeid + "']").attr("selected", "true") } else { $("#monitorName").text = $("#domain").val() + "-" + $("#template").val(); } } }); }, commitMonitorConfig: function () { var config = new Object(); config.Name = $("#monitorName").val(); config.SubId = $("#sub").val(); config.SubName = $("#sub").find("option:selected").text(); config.DomainId = $("#template").val(); config.DomainName = $("#template").find("option:selected").text(); config.NodeId = $("#node").val(); config.NodeName = $("#node").find("option:selected").text(); if ($("#turnOn").is(':checked')) { config.TurnOn = "1"; } else { config.TurnOn = "0"; } if ($("#emailOn").is(':checked')) { config.EmailOn = "1"; } else { config.EmailOn = "0"; } if ($("#siteOn").is(':checked')) { config.CheckSiteOn = "1"; } else { config.CheckSiteOn = "0"; } if ($("#poolOn").is(':checked')) { config.CheckPoolOn = "1"; } else { config.CheckPoolOn = "0"; } if ($("#urlOn").is(':checked')) { config.CheckUrlOn = "1"; } else { config.CheckUrlOn = "0"; } config.Url = $("#url").val(); config.Reciever = $("#recievers").val(); if (config.NodeName == "全部") { $("#node option").each(function () { //遍歷全部option var txt = $(this).text(); //獲取option的內容 if (txt != "全部") //如果不是“全部”和"請選擇子站點" { config.NodeName = txt; eidtRunStatusMonitorConfigPage.postMonitorConfig(config); } }); } else { eidtRunStatusMonitorConfigPage.postMonitorConfig(config); } }, postMonitorConfig: function (postData) { var url = '/RunMonitor/CommitMonitorConfig'; var pack = new Object(); pack.Token = $.readCookie('accessToken'); pack.config = postData; var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { if (results.Data == "0") { $.note(null, "修改" + name + "運行狀態監控配置成功!"); RunStatusMonitorConfigListPage.refresh(); } else { $.note(null, "修改" + name + "運行狀態監控配置失敗!" + results.Message, 'error'); } }, error: function (xhr, status, error) { $.note(null, "發送修改" + name + "運行狀態監控配置請求失敗!", 'error'); } }); }, postTurnOn: function (id) { token = $.readCookie('accessToken'); $.post("/RunMonitor/TurnOnMonitor", { "id": id, "alis": token }, function (data) { if (data.StateCode == 0) { $.note(null, '開啓監控成功.'); } else { $.note(null, '開啓監控失敗.', "error"); } }); }, postTurnOff: function (id) { token = $.readCookie('accessToken'); $.post("/RunMonitor/TurnOffMonitor", { "id": id, "alis": token }, function (data) { if (data.StateCode == 0) { $.note(null, '關閉監控成功.'); } else { $.note(null, '關閉監控失敗.', "error"); } }); }, startInvoke: function (sender) { var parentObj = sender.parent(); parentObj.empty(); parentObj.append('<img src="../img/loading.jpg" style="width:30px;" id="iloader" />'); var ip = parentObj.next().next().next().next().next().text(); var url = 'http://' + ip + ':8167/Monitor/Ping'; $.ajax({ type: "POST", url: url, data: null, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { parentObj.empty(); var reg = /\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}/; if (reg.test(results)) { $.note(null, '喚醒' + ip + '監控成功!'); parentObj.append('<button class="link invokesuccessbtn" style="margin-left:30px;"><i class="icon-checkmark fg-green" style="margin-left:45px;"></i></button>'); $('.invokesuccessbtn').click(function () { monitorconfigpage.startInvoke($(this)); }); } else { $.note('Error', '喚醒' + ip + '失敗!', 'error'); parentObj.append('<button class="link invokefailbtn" style="margin-left:30px;"><i class="icon-cancel-2 fg-red"></i></button>'); $('.invokefailbtn').click(function () { monitorconfigpage.startInvoke($(this)); }); } }, error: function (xhr, status, error) { $.note('Error', '喚醒' + ip + '失敗!' + error, 'error'); parentObj.empty(); parentObj.append('<button class="link invokefailbtn" style="margin-left:30px;"><i class="icon-cancel-2 fg-red"></i></button>'); $('.invokefailbtn').click(function () { monitorconfigpage.startInvoke($(this)); }); } }); }, deleteConfig:function(id) { var r = confirm("確定刪除該配置信息?") if (r == true) { var config = new Object(); config.id = id; } else { $.note(null, "你已取消刪除配置信息id:" + id); } }, postDeleteConfig:function(postData) { var url = '/RunMonitor/DeleteMonitorConfig'; var pack = new Object(); pack.Token = $.readCookie('accessToken'); pack.config = postData; var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { if (results.Data == "0") { $.note(null, "刪除運行狀態監控配置成功!"); RunStatusMonitorConfigListPage.refresh(); } else { $.note(null, "刪除運行狀態監控配置失敗!" + results.Message, 'error'); } }, error: function (xhr, status, error) { $.note(null, "發送刪除運行狀態監控配置請求失敗!", 'error'); } }); } }
Controller代碼:
using RestSharp; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using ControllerBase = xxx.xxx.QA.Platform.Common.ControllerBase; namespace xxx.xxx.QA.Platform.Environment.Controllers.Coverage { public class RunMonitorController : ControllerBase { // // GET: /RunMonitor/ public ActionResult Index() { IList <EnvRunStatusMonitorConfig> configList = EnvRunStatusMonitorConfigBiz.GetRunStatusMonitorConfig(); return View(configList); } public JsonResult GetMonitorSetting(int id) { var resp = new APIResponse<EnvRunStatusMonitorConfig>() { StateCode = StateCode.Success, Message = "" }; try { EnvRunStatusMonitorConfig config = EnvRunStatusMonitorConfigBiz.GetRunStatusMonitorConfig(id); resp.Data = config; } catch (Exception ex) { resp.StateCode = StateCode.Fail; resp.Message += ex.ToString(); } return Json(resp, JsonRequestBehavior.AllowGet); } public JsonResult TurnOnMonitor(int id, string alis) { var resp = new APIResponse<string>() { StateCode = StateCode.Success, Message = "" }; var accessToken = LoginSecurity.DecodeAccessToken(alis); if (VerifyToken(ref accessToken, ref resp, "EnvIISResetOperator")) { try { EnvRunStatusMonitorConfig config = EnvRunStatusMonitorConfigBiz.GetRunStatusMonitorConfig(id); EnvRunStatusMonitorConfigBiz.TurnOnEnvRunStatusMonitorConfig(config); string desc = string.Format("{0} turn on run monitor {1} ", accessToken.Alias, config.DomainId + "-" + config.Id); int machineid = config.Id; EnvOperationLogBiz.LogTurnOnRunMonitor(machineid, accessToken.Alias, desc); } catch (Exception ex) { resp.StateCode = StateCode.Fail; resp.Message += ex.ToString(); } } return Json(resp, JsonRequestBehavior.DenyGet); } public JsonResult TurnOffMonitor(int id, string alis) { var resp = new APIResponse<string>() { StateCode = StateCode.Success, Message = "" }; var accessToken = LoginSecurity.DecodeAccessToken(alis); if (VerifyToken(ref accessToken, ref resp, "EnvIISResetOperator")) { try { EnvRunStatusMonitorConfig config = EnvRunStatusMonitorConfigBiz.GetRunStatusMonitorConfig(id); EnvRunStatusMonitorConfigBiz.TurnOffEnvRunStatusMonitorConfig(config); string desc = string.Format("{0} turn off run monitor {1} ", accessToken.Alias, config.DomainId + "-" + config.Id); int machineid = config.Id; EnvOperationLogBiz.LogTurnOffRunMonitor(machineid, accessToken.Alias, desc); } catch (Exception ex) { resp.StateCode = StateCode.Fail; resp.Message += ex.ToString(); } } return Json(resp, JsonRequestBehavior.DenyGet); } public JsonResult CommitMonitorConfig(RunStatusMonitorConfigPack pack) { var resp = new APIResponse<string>() { StateCode = StateCode.Success, Message = "" }; var accessToken = LoginSecurity.DecodeAccessToken(pack.Token); if (VerifyToken(ref accessToken, ref resp, "EnvIISResetOperator")) { try { EnvRunStatusMonitorConfig config = pack.config; config.DomainName = DomainUtil.GetDomainName(config.SubName, config.DomainName); // 根據環境跟站點獲取機器 IEnumerable<EnvDomainConfig> domainConfigs = EnvDomainConfigBiz.GetAllDomainsByEnvAndDomainName(config.SubName, config.DomainName); if (domainConfigs != null && domainConfigs.Count() >= 1) { EnvDomainConfig domainConfig = domainConfigs.First(); EnvMachine machine = EnvMachineBiz.FindByMachineName(domainConfig.MachineName); config.MachineName = domainConfig.MachineName; config.MachineId = machine.Id; config.Ip = machine.IP; // 查詢機器上是否存在該子站點 var client = new RestClient("http://" + machine.IP + ":8167"); string nodename = config.NodeName; string path = nodename.IndexOf("/") < 0 ? "/" + nodename : nodename; var request = new RestRequest("/IIS/GetAppPoolNameBySite?siteName=" + config.DomainName + "&path=" + path, Method.GET); var response = client.Execute(request); if (!response.Content.ToString().Equals("") && response.Content.ToString().IndexOf("無效的應用程序路徑") < 0) { config.PoolName = response.Content.ToString().Replace("\"", ""); EnvRunStatusMonitorConfigBiz.CommitRunStatusMonitorConfig(config); resp.Data = "0"; } // 存在子站點,查詢程序池,提交 else { // 程序池不存在,返回102,提示請檢查站點是否最近有更新 resp.Data = "102"; resp.Message = "站點:" + config.DomainName + "子站點" + config.NodeName + "的程序池不存在, 請檢查站點是否最近有更新"; } } else { // 機器不存在,返回101,提示請檢查該站點是否部署 resp.Data = "101"; resp.Message = "環境:" + config.SubName + "站點" + config.DomainName + "的機器不存在, 請檢查站點是否部署"; } // EnvAppPoolMonitorConfigBiz.CommitAppPoolMonitorConfigInfo(pack.config); } catch (Exception ex) { resp.StateCode = StateCode.Fail; resp.Message += ex.ToString(); resp.Data = "1"; } } return Json(resp, JsonRequestBehavior.AllowGet); } public JsonResult DeleteMonitorConfig(RunStatusMonitorConfigPack pack) { var resp = new APIResponse<string>() { StateCode = StateCode.Success, Message = "" }; var accessToken = LoginSecurity.DecodeAccessToken(pack.Token); if (VerifyToken(ref accessToken, ref resp, "EnvIISResetOperator")) { try { EnvRunStatusMonitorConfigBiz.DeleteEnvAppPoolMonitorConfig(pack.config.Id); resp.Data = "0"; } catch (Exception ex) { resp.StateCode = StateCode.Fail; resp.Message += ex.ToString(); resp.Data = "1"; } } return Json(resp, JsonRequestBehavior.AllowGet); } } public class RunStatusMonitorConfigPack : PostPackBase { public EnvRunStatusMonitorConfig config { get; set; } } }
2. 服務器端監控代碼
監控站點程序池的狀態,是放在該服務器上的EnvAgency裏面
using FluentScheduler; using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace xxx.xxx.QA.Platform.EnvAgent.Services.Tasks { public class RunStatusMonitorTask : ITask { private static readonly object Locker = new object(); private static bool _isRunning; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public void Execute() { if (_isRunning) { return; } ChangeState(true); try { Logger.Info("Monitor start"); EnvMachine envMachine = EnvMachineBiz.GetCurrentMachine(); #region 監控站點 IList<EnvRunStatusMonitorConfig> configList = EnvRunStatusMonitorConfigBiz.GetRunStatusSiteMonitorConfigByMachineId(envMachine.Id); foreach (EnvRunStatusMonitorConfig config in configList) { DateTime dt = DateTime.Now.ToLocalTime(); bool siteStared = RunStatusMonitorUtil.IsSiteStarted(config.DomainName); EnvRunStatusMonitorLogBiz.AddEnvRunSiteStatusMonitorLog(envMachine.Id, siteStared, dt); if (!siteStared) { string reciever = config.Reciever; string body = ""; body += "<h3>機器</h3>" + config.Ip + ")<br/><br/>"; body += "<h3>站點</h3>" + config.DomainName + ")<br/><br/>"; // 未設置情況默認爲該賬戶 if (reciever == null || reciever.Equals("")) { reciever = "[email protected]"; } Mail.SendMailWithHtml2(reciever, "站點未啓動預警:" + envMachine.Name+"-"+config.DomainName, body, "[email protected]"); Logger.Info("Send 站點未開啓預警 mail:" + body); } } #endregion #region 監控程序池 IList<EnvRunStatusMonitorConfig> configList2 = EnvRunStatusMonitorConfigBiz.GetRunStatusAppPoolMonitorConfigByMachineId(envMachine.Id); foreach (EnvRunStatusMonitorConfig config in configList2) { DateTime dt = DateTime.Now.ToLocalTime(); bool poolStared = RunStatusMonitorUtil.IsAppPoolStarted(config.PoolName); EnvRunStatusMonitorLogBiz.AddEnvRunSiteStatusMonitorLog(envMachine.Id, poolStared, dt); if (!poolStared) { string reciever = config.Reciever; string body = ""; body += "<h3>機器</h3>" + config.Ip + ")<br/><br/>"; body += "<h3>程序池</h3>" + config.PoolName + ")<br/><br/>"; // 未設置情況默認爲該賬戶 if (reciever == null || reciever.Equals("")) { reciever = "[email protected]"; } Mail.SendMailWithHtml2(reciever, "程序池未啓動預警:" + envMachine.Name + "-" + config.PoolName, body, "[email protected]"); Logger.Info("Send 程序池未開啓預警 mail:" + body); } } #endregion //監控URL放在主站點做比較合適 } catch (Exception ex) { Logger.Error("MonitorTask異常信息:" + ex.ToString()); } finally { ChangeState(false); } } private void ChangeState(bool running) { lock (Locker) { _isRunning = running; } } } }
監控URL狀態是放在環境系統平臺裏面
using FluentScheduler; using NLog; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace xxx.xxx.QA.Platform.Environment.Services.Task { public class RunStatusMonitorTask : ITask { private static readonly object Locker = new object(); private static bool _isRunning; private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); public void Execute() { if (_isRunning) { return; } ChangeState(true); try { Logger.Info("Monitor start"); EnvMachine envMachine = EnvMachineBiz.GetCurrentMachine(); #region 監控URL IList<EnvRunStatusMonitorConfig> configList = EnvRunStatusMonitorConfigBiz.GetRunStatusUrlMonitorConfig(); foreach (EnvRunStatusMonitorConfig config in configList) { DateTime dt = DateTime.Now.ToLocalTime(); bool urlStared = RunStatusMonitorUtil.IsUrlReturnOK(config.Url); EnvRunStatusMonitorLogBiz.AddEnvRunSiteStatusMonitorLog(config.Id, urlStared, dt); if (!urlStared) { string reciever = config.Reciever; string body = ""; body += "<h3>Name</h3>" + config.Name + "<br/><br/>"; body += "<h3>URL</h3>" + config.Url + "<br/><br/>"; body += "<h3>環境</h3>" + config.SubName + "<br/><br/>"; body += "<h3>站點</h3>" + config.DomainName+ "<br/><br/>"; body += "<h3>子站點</h3>" + config.NodeName + "<br/><br/>"; body += "<h3>IP</h3>" + config.Ip + "<br/><br/>"; // 未設置情況默認爲該賬戶 if (reciever == null || reciever.Equals("")) { reciever = "[email protected]"; } Mail.SendMailWithHtml2(reciever, "URL未返回成功預警:" + config.Url, body, "[email protected]"); Logger.Info("Send 站點未開啓預警 mail:" + body); } } #endregion } catch (Exception ex) { Logger.Error("MonitorTask異常信息:" + ex.ToString()); } finally { ChangeState(false); } } private void ChangeState(bool running) { lock (Locker) { _isRunning = running; } } } }
監控核心代碼:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; namespace Ctrip.Hotel.QA.Platform.Core.Monitor { public class RunStatusMonitorUtil { public static bool IsSiteStarted(string siteName) { return IISUtil.GetSiteState(siteName).Equals("Started"); } public static bool IsAppPoolStarted(string poolName) { return IISUtil.getAppPoolSatus(poolName).Equals("Started"); } public static bool IsUrlReturnOK(string url) { string status = GetResponseStatueCode(url); return status.Equals("OK"); } public static string GetResponseStatueCode(string url) { HttpWebRequest webrequest = (HttpWebRequest)HttpWebRequest.Create(url); try { HttpWebResponse webreponse = (HttpWebResponse)webrequest.GetResponse(); return webreponse.StatusCode.ToString(); } catch (Exception ex) { return ""; } } } } /// <summary> /// 獲取站點狀態 /// </summary> /// <param name="siteName"></param> /// <returns></returns> public static string GetSiteState(string siteName) { ServerManager manager = new ServerManager(); Site site = manager.Sites[siteName]; return site.State.ToString(); } /// <summary> /// 獲取程序池狀態 /// </summary> /// <param name="poolName"></param> /// <returns></returns> public static ObjectState getAppPoolSatus(string poolName) { ServerManager manager = new ServerManager(); return manager.ApplicationPools[poolName].State; }
如此一來,功能在匆匆忙忙中實現了,但是想想如此現實,有些多餘,
光Url的正常返回就能確定站點跟程序池的正常運行,配置url的話,就不需要配很多參數,如環境,站點,應用等,
或者配置站點,程序池,url做成三個頁面
配置站點:需要選擇環境,站點名,需要檢查該環境上配置該站點的機器,並把機器也保存在數據庫中
配置程序池:需要選擇環境,站點,子站點,需要檢查該環境上配置該站點的機器,並把機器也保存在數據庫中,並且還需要去機子上查找該子站點對應的程序池名,把程序池也保存在數據庫裏
配置URL:這個就簡單了,只需要配置url就能了,直接在List也增刪改查就行了
再加個結果的圖標分析頁就更好了