C#實現對站點、程序池狀態的監控,以及URL能正常返回的監控,狀態異常,郵件預警

需求:自動化組提出需要,要對IIS上的站點進行監控,異常停止後報警


需求分析:這站點的運行正常需要多方面的監控,如站點,程序池,資源,所以針對這需求做了三方面的監控。

  1. 站點狀態的監控

  2. 站點對應的程序池的監控

  3. URL的監控,監控url能返回200的狀態碼


數據庫設計:

wKioL1YeHYPj1P_mAAHKAcf9ix0756.jpg


wKiom1YeHWOQEqVIAAC7lpySFrM750.jpg


頁面展示:

配置list頁

wKioL1YeHZyDqHgYAAJ5ToYxFio410.jpg

配置Detail頁

wKiom1YeHXyhSMb2AAHbM4aJ-0E560.jpg

預警郵件:

wKioL1YeHZyQ9u8xAAFXFCmaev4319.jpg


核心代碼:

  1. 配置頁面代碼

    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>&nbsp;
                <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>
                                &nbsp; 開啓監控
                            </label>
                            <label class="switch" style="float:left;display:inline;margin-left:50px;">
                                <input type="checkbox" checked id="emailOn">
                                <span class="check"></span>
                                &nbsp;收郵件
                            </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>
                                &nbsp;監控站點
                            </label>           
                            <label class="switch" style="float:left;display:inline;margin-left:50px;">
                                <input type="checkbox" id="poolOn">
                                <span class="check"></span>
                                &nbsp;監控程序池
                            </label>           
                            <label class="switch" style="float:left;display:inline;margin-left:50px;">
                                <input type="checkbox" checked id="urlOn">
                                <span class="check"></span>
                                &nbsp;監控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>&nbsp;
                    <button id="cancelCommitBtn" class="danger"><i class=" icon-cancel-2 on-left"></i>取消</button>&nbsp;
                    <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做成三個頁面

  1. 配置站點:需要選擇環境,站點名,需要檢查該環境上配置該站點的機器,並把機器也保存在數據庫中

  2. 配置程序池:需要選擇環境,站點,子站點,需要檢查該環境上配置該站點的機器,並把機器也保存在數據庫中,並且還需要去機子上查找該子站點對應的程序池名,把程序池也保存在數據庫裏

  3. 配置URL:這個就簡單了,只需要配置url就能了,直接在List也增刪改查就行了


再加個結果的圖標分析頁就更好了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章