需求:自动化组提出需要,要对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 = "chenjz@Ctrip.com";
}
Mail.SendMailWithHtml2(reciever, "站点未启动预警:" + envMachine.Name+"-"+config.DomainName, body, "chenjz@Ctrip.com");
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 = "chenjz@Ctrip.com";
}
Mail.SendMailWithHtml2(reciever, "程序池未启动预警:" + envMachine.Name + "-" + config.PoolName, body, "xxx@xxx.com");
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 = "xxx@xxx.com";
}
Mail.SendMailWithHtml2(reciever, "URL未返回成功预警:" + config.Url, body, "chenjz@Ctrip.com");
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也增删改查就行了
再加个结果的图标分析页就更好了
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有