实现对程序池资源监控:CPU占用率、GC监控及邮件预警,帮助做性能分析,错误报警
页面展示如下:
1. 展示当前各个程序池的CPU占用率
2. 展示监控的程序池的cpu占用率图表
3. 程序池配置list
4. 程序池监控配置详情页:
5. 超出阈值预警邮件
数据库表如下:
核心代码如下:
获取进程
每个程序池就是一个映像名称为w3wp的进程,如图
所以需要根据映像名称跟用户名得到Process
2. 进程的CPU占用率
根据Process的ID与PerformanceCounter("Process", "ID Process", instance)得到instance,
在生成 PerformanceCounter(
"Process"
,
"% Processor Time"
, instance1) 就能获取cpu的占用率。
详情参考:上篇博文中写出了如何监控Process的CPU占用率以及GC (http://4453154.blog.51cto.com/4443154/1701525)
3. 进程的GC
根据Process的ID与PerformanceCounter(".NET CLR Memory"
,
"Process ID",
instance)得到instance,
在生成 PerformanceCounter
(
".NET CLR Memory"
,
"% Time in GC",
instance1) 就能获取进程的gc。
详情参考:上篇博文中写出了如何监控Process的CPU占用率以及GC (http://4453154.blog.51cto.com/4443154/1701525)
4. 由于每台服务器上有很多程序池,每个程序池CPU监控器创建的时候都有个舍弃第一个无效样本,等待最小时间片(测试出来大多机器是200ms,保险起见取1000ms),这样个耗时操作,所以采用多线程来批量创建程序池的监控。
核心代码如下:
AppPoolMonitorUtil.cs
using NLog; using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; namespace xxxx.xxx.QA.Platform.Core.ServerUtils { public class AppPoolMonitorUtil { private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); private static Hashtable monitorHT = new Hashtable(); //创建一个Hashtable实例 #region 初始化 /// <summary> /// 初始化程序池监控 /// </summary> /// <param name="configs"></param> public static void InitAppPoolMonitor(List<string> poolNames) { Logger.Info("初始化程序池监控信息-start"); int counter = ProcessorCountMonitor.getValue(); //Logger.Info("counter:" + counter); List<AppPoolMonitorInfo> poolMonitors = new List<AppPoolMonitorInfo>(); ArrayList listThread = new ArrayList(); DateTime d2 = DateTime.Now; // 获取所有程序池名称 DateTime d3 = DateTime.Now; Process[] ps = Process.GetProcessesByName("w3wp"); DateTime d4 = DateTime.Now; Logger.Info("需监控pool如下:"); foreach (string name in poolNames) { Logger.Info(name); } foreach (Process p in ps) { string name = MachineMonitor.GetProcessUserName(p.Id); //Logger.Info("Process Name:"+name); if (poolNames.IndexOf(name) >= 0 && !monitorHT.ContainsKey(name)) { Logger.Info("Name:" + name+"未生成监控,新建线程生成监控"); Thread parameterThread = new Thread(delegate() { GetSingleAppPoolMonitor(name, p, counter, ref monitorHT); }); parameterThread.Name = name; parameterThread.Start(); //Logger.Info("Thread " + name+" start"); listThread.Add(parameterThread); } } foreach (Thread thread in listThread) { thread.Join(); } Logger.Info("实例化的监控信息如下:"); int n = monitorHT.Count; foreach (DictionaryEntry de in monitorHT) //ht为一个Hashtable实例 { Logger.Info("key:" + de.Key);//de.Key对应于keyvalue键值对key Logger.Info("Value:" + de.Value);//de.Key对应于keyvalue键值对value } Logger.Info("初始化程序池监控信息-Finish"); } public static void GetSingleAppPoolMonitor(string name, Process p, int counter, ref Hashtable ht) { try { //Logger.Info("in GetAppPoolInfo()"); AppPoolMonitor info = new AppPoolMonitor(); info.name = name; info.count = counter; info.process = p; //Logger.Info("p.ProcessName:" + p.ProcessName); //Logger.Info("p.ProcessName:" + p.Id); // 获取CPU占用率 PerformanceCounter string instance1 = GetInstanceName("Process", "ID Process", p); if (instance1 != null) { PerformanceCounter cpucounter = new PerformanceCounter("Process", "% Processor Time", instance1); if (cpucounter != null) { cpucounter.NextValue(); System.Threading.Thread.Sleep(200); //等200ms(是测出能换取下个样本的最小时间间隔),让后系统获取下一个样本 info.cpuCounter = cpucounter; //Logger.Info("Name:" + name + "生成CPU监控成功" + instance1); } else { //Logger.Info("Name:" + name + "生成CPU监控失败" + instance1); } } else { //Logger.Info("Name:" + name + "获取cpu监控实例失败" + instance1); } // 获取GC占用率 PerformanceCounter string instance2 = GetInstanceName(".NET CLR Memory", "Process ID", p); if (instance2 != null) { PerformanceCounter gccounter = new PerformanceCounter(".NET CLR Memory", "% Time in GC", instance2); if (gccounter != null) { gccounter.NextValue(); info.gcCounter = gccounter; //Logger.Info("Name:" + name + "生成GC监控成功" + instance2); } else { //Logger.Info("Name:" + name + "生成GC监控失败" + instance2); } } else { //Logger.Info("Name:" + name + "获取GC监控实例失败" + instance2); } lock (ht) { // Access thread-sensitive resources. if (info != null) { ht.Add(name,info); //Logger.Info("Add name:" + name + " into hashtable"); } } } catch (Exception ex) { Logger.Info("Exception:" + ex.ToString()); } } public static string GetInstanceName(string categoryName, string counterName, Process p) { try { PerformanceCounterCategory processcounter = new PerformanceCounterCategory(categoryName); string[] instances = processcounter.GetInstanceNames(); foreach (string instance in instances) { PerformanceCounter counter = new PerformanceCounter(categoryName, counterName, instance); //Logger.Info("对比in mothod GetInstanceName," + counter.NextValue() + ":" + p.Id); if (counter.NextValue() == p.Id) { return instance; } } } catch (Exception ex) { } return null; } #endregion public static float GetAppPoolMonitorCpu(string poolName) { Logger.Info("In Method GetAppPoolMonitorCpu(string poolName) and poolName is " + poolName); PerformanceCounter cpuCounter = ((AppPoolMonitor)monitorHT[poolName]).cpuCounter ; if (cpuCounter != null) { return cpuCounter.NextValue() / ((AppPoolMonitor)monitorHT[poolName]).count; } return 0; } public static float GetAppPoolMonitorMemory(string poolName) { Process process = ((AppPoolMonitor)monitorHT[poolName]).process; return process.WorkingSet64 / (1024 * 1024); } public static float GetAppPoolMonitorGC(string poolName) { PerformanceCounter gcCounter = ((AppPoolMonitor)monitorHT[poolName]).gcCounter; if (gcCounter != null) { return gcCounter.NextValue() ; } return 0; } } public class AppPoolMonitor { public string name { get; set; } //程序池名 public int count { get; set; } //核数 public PerformanceCounter cpuCounter { get; set; }//cpu占用率:( cpuCounter.NextValue()/count).ToString("F"); public PerformanceCounter gcCounter { get; set; } public Process process { get; set; }//内存:(process.WorkingSet64 / (1024 * 1024)).ToString("F"); } }
创建Task
MonitorTask.cs
using FluentScheduler; using NLog; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Web; namespace xxx.xxx.QA.Platform.EnvAgent.Services.Tasks { public class MonitorTask : 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 程序池监控 IEnumerable<EnvAppPoolMonitorConfig> currentAppPoolMonitorConfigs = EnvAppPoolMonitorConfigBiz.GetCurrentAppPoolMonitorConfig(); // 每分钟插入下数据库 Hashtable poolMonitor = new Hashtable(); foreach (EnvAppPoolMonitorConfig config in currentAppPoolMonitorConfigs) { //Logger.Info("监控信息:" + config.PoolName+"("+config.TurnOn+")"); if (!poolMonitor.ContainsKey(config.PoolName)) { //Logger.Info("插入hashtable"); poolMonitor.Add(config.PoolName, config.TurnOn); } else { //Logger.Info("已存在"); if (config.TurnOn == 1 && (int)poolMonitor[config.PoolName] == 0) { // Logger.Info("TurnON设成1"); poolMonitor[config.PoolName] = 1; } } } //Logger.Info("监控程序池的hashtable如下:"); List<string> poolNames = new List<string>(); foreach (DictionaryEntry de in poolMonitor) //ht为一个Hashtable实例 { //Logger.Info("key:" + de.Key);//de.Key对应于keyvalue键值对key // Logger.Info("Value:" + de.Value);//de.Key对应于keyvalue键值对value if ((int)de.Value == 1) { poolNames.Add(de.Key.ToString()); //Logger.Info("进入监控池"); } } AppPoolMonitorUtil.InitAppPoolMonitor(poolNames); foreach (DictionaryEntry de in poolMonitor) //ht为一个Hashtable实例 { if ((int)de.Value == 1) { string poolName = de.Key.ToString(); // CPU占用率 int apppoolcpu = (int)AppPoolMonitorUtil.GetAppPoolMonitorCpu(poolName); // 内存占用MB int apppoolMemory = (int)AppPoolMonitorUtil.GetAppPoolMonitorMemory(poolName); // GC int apppoolgc = (int)AppPoolMonitorUtil.GetAppPoolMonitorGC(poolName); // 存入数据库 DateTime dt = DateTime.Now.ToLocalTime(); Logger.Info("Add Pool Monitor info (" + envMachine.Id + ", " + poolName + ", " + apppoolcpu + ", " + apppoolMemory + ", " + apppoolgc + ", " + dt + ")"); EnvAppPoolMonitor newInfo2 = EnvAppPoolMonitorBiz.AddEnvAppPoolMonitorInfo(envMachine.Id, poolName, apppoolcpu, apppoolMemory, apppoolgc, dt); //Logger.Info("存程序池监控信息Result: success, return EnvAppPoolMonitor id is " + newInfo2.Id); } } #endregion #region 程序池监控邮件 // 每十五分钟监控下发邮件 DateTime dn2 = DateTime.Now.ToLocalTime(); if (EmailSendTime.GetTimeSpanSecond2(dn2) > 15) { foreach (EnvAppPoolMonitorConfig config in currentAppPoolMonitorConfigs) { if (config.TurnOn == 1 && config.EmailOn == 1) { string reciever = config.Reciever; string body = ""; bool flag = false; body += "<h3>"+config.DomainName+" : "+config.NodeName+"</h3>"; // 未设置情况默认为该账户 if (reciever == null || reciever.Equals("")) { reciever = "xxx@xxxx.com"; } // 检查CPU占用率 int apppoolcpu = (int)AppPoolMonitorUtil.GetAppPoolMonitorCpu(config.PoolName); if (config.Cpu != null && apppoolcpu > config.Cpu || apppoolcpu > 95) { body += "<h3>CPU占用率超标</h3>CPU占用率: " + apppoolcpu + "(阈值:" + config.Cpu + ")<br/><br/>"; flag = true; } // 检查内存占用MB int apppoolMemory = (int)AppPoolMonitorUtil.GetAppPoolMonitorMemory(config.PoolName); if (config.Memory != null && apppoolMemory > config.Memory) { body += "<h3>内存占用超标</h3>内存: " + apppoolMemory + "MB(阈值:" + config.Memory + ")<br/><br/>"; flag = true; } // 检查GC int apppoolgc = (int)AppPoolMonitorUtil.GetAppPoolMonitorGC(config.PoolName); if (config.GC != null && apppoolgc > config.GC || apppoolgc > 95) { body += "<h3>GC占用超标</h3>GC: " + apppoolgc + "(阈值:" + config.GC + ")<br/><br/>"; flag = true; } // 发送邮件
注册Task
Logger.Info("每1分钟执行下机器监控"); Schedule<MonitorTask>().ToRunNow().AndEvery(1).Minutes();
页面代码:
显示页
getAppPoolMonitorInfo: function () { var container = $("#machinemonitor"); container.empty(); var machine = pagefind.currentMachine(); container.append('<div id="container1"></div><div id="container2" style="min-width: 310px; height: 400px; margin: 0 auto"></div>'); var container1 = $("#container1"); var container2 = $("#container2"); if (machine == null) { $.note(null, '请先选择环境&机器', 'error'); return; } chcoreui.attachLoader(container1, pageid.loader, 410, 100); var url = 'http://' + machine.IP + ':8167/MachineMonitor/GetAppPoolMonitorInfo'; var pack = new Object(); pack.Token = $.readCookie('accessToken'); var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { if (results.StateCode == 0) { var bodyContent = ''; $.each(results.Data, function (idx, item) { bodyContent += '<tr><td style="text-align:left;">' + item.PoolName + '</td><td><div class="progressbar_3"><div class="text">' + item.CpuUsage + '%</div><div class="bar" style="width:' + item.CpuUsage + '%;"></div></div></div></td><td>' + item.MemoryUsage + 'MB</td><td><button class="warning" id="AppPoolRestBtn" style="width:160px" id="' + item.PoolName + '" onclick="informationpage.AppPoolReset(id)">重启程序池</button></td></tr>'; }); container1.html('<table class="table bordered striped hovered dataTable" cellspacing="0" id="machineMonitortable" style="text-align:center"><thead><tr><th>程序池名称</th><th>占用CPU百分比</th><th>专用内存</th><th>Action</th></tr></thead><tbody>' + bodyContent + '</tbody></table>'); $('#machineMonitortable').dataTable({ "paging": false, "searching": true, "ordering": true, "info": false, "striped": false, //"scrollY": "450px", "scrollCollapse": true }); } }, error: function (xhr, status, error) { $.note('Error', '获取机器监控信息失败,请联系管理员(qyli).', 'error'); } }); //chcoreui.attachLoader(container2, pageid.loader, 410, 100); var url2 = '/AppPoolMonitor/GetMonitorInfos?ip=' + machine.IP; var pack = new Object(); pack.Token = $.readCookie('accessToken'); var submitData = JSON.stringify(pack); $.ajax({ type: "POST", url: url2, data: submitData, dataType: "json", contentType: "application/json", crossDomain: true, success: function (results) { if (results.StateCode == 0) { $.apppoolmonitorchart(container2, results.Data); } else { $.note('获取数据库中程序池监控信息失败.' + results.Message, 'error'); } }, error: function (xhr, status, error) { $.note('Error', '获取数据库中机器监控信息失败', error); } }); }
2. 图表
(function ($){ $.apppoolmonitorchart = function (container, monitorinfo) { $.each(monitorinfo, function (index, value) { var time = new Array(); var i = 0; $.each(value.timeList, function (index, value) { time[i] = $.convertToDateStr(value); i++; }); container.append('<br/><div id="newContain'+index+'" style="min-width: 310px; height: 400px; margin: 0 auto"></div>') $("#newContain"+index+"").highcharts({ title: { text: '程序池CPU资源监控', x: -20 //center }, subtitle: { text: value.poolName+'的CPU占用率', x: -20 }, xAxis: { categories: time }, yAxis: { title: { text: '百分比(%)' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { valueSuffix: '%' }, legend: { layout: 'vertical', align: 'right', verticalAlign: 'middle', borderWidth: 0 }, series: [{ name: 'CPU', data: value.dataList }] }); }); } })(jQuery);
3. 配置
monitorapppoolconfigpage = { render: function () { var container = $(pageid.mainContent); container.empty(); chcoreui.attachLoader(container, pageid.loader, 410, 100); var url = '/AppPoolMonitor/AppPoolMonitorConfig'; $.getJSON(url, function (results) { if (results.StateCode == 0) { // 成功 var bodyContent = ''; $.each(results.Data, function (idx, item) { bodyContent += '<tr><td style="text-align:center;"><button class="link invokebtn"><i class="icon-play"></i></button></td><td>' + item.Name + '</td><td>' + item.DomainName + '</td><td>' + item.NodeName + '</td><td>' + item.MachineName + '</td><td style="text-align:center;">' + item.Ip + '</td><td style="text-align:center;"><input class="turnonckbox" id="' + item.Id + '" type="checkbox"'; if (item.TurnOn == 1) { bodyContent += " checked " } bodyContent += ' data-size="mini" data-on-color="success"></td><td><button class="link apppoolmonitorconfigbtn" id="' + item.Id + '" ><span class="mif-loop2"></span>配置</button></td></tr>'; }); container.empty(); container.html('<div style="margin-left:30px;"><button class="refreshbtn primary" style="width:100px" ><i class="icon-cycle on-left"></i>刷新</button> <button class="addapppoolmonitorbtn success" style="width:100px" ><i class="icon-plus on-left"></i>新建</button></div><table class="table bordered striped hovered dataTable" cellspacing="0" id="apppooltable"><thead><tr><th><button class="invokeallbtn warning"><i class="icon-play on-left"></i>唤醒</button></th><th>监控器名</th><th>站点名</th><th>字站点名</th><th>机器名</th><th>ip</th><th>开启</th><th>Action</th></tr></thead><tbody>' + bodyContent + '</tbody></table>'); $('#apppooltable').dataTable({ "paging": false, "searching": true, "ordering": true, // "scrollY": "450px", "scrollCollapse": true, "dom": '<"tool1bar">fr1tip' }); $(".turnonckbox").change(function () { var id = this.id; if ($('#' + id + '').is(':checked')) { monitorapppoolconfigpage.postTurnOn(id); } else { monitorapppoolconfigpage.postTurnOff(id); } }); $(".refreshbtn").click(function () { monitorapppoolconfigpage.render(); }); $(".addapppoolmonitorbtn").click(function () { monitorapppoolconfigpage.getConfigSetingDialog(0); }); $(".invokebtn").click(function () { monitorapppoolconfigpage.startInvoke($(this)); }); $(".invokeallbtn").click(function () { if (!$(this).hasClass('disabled')) { var syncbtns = $('.invokebtn'); $(this).addClass('disabled'); $.each(syncbtns, function (idx, item) { item.click(); }); } }); $(".apppoolmonitorconfigbtn").click(function () { var id = this.id; monitorapppoolconfigpage.getConfigSetingDialog(id); }); } }); }, getConfigSetingDialog: function (id) { $.setting("settingDiv", "程序池监控配置框:" + name, "620px", "470px"); chcoreui.attachLoader($("#settingDiv"), pageid.loader, 410, 100); $("#settingDiv").empty(); $("#AppPoolMonitorSettingTemplate").tmpl().appendTo("#settingDiv"); var domainSelect = $("#domain"); var templateSelect = $("#template"); var nodeSelect = $("#node"); // 绑定数据 if (id != 0) { $.getJSON('/AppPoolMonitor/GetMonitorSetting?id=' + id, null, function (data) { if (data) { domainSelect.append("<option value=" + data.Data.SubId + " select disabled=true>" + data.Data.SubName + "</option>"); templateSelect.append("<option value=" + data.Data.DomainId + " select disabled=true>" + data.Data.DomainName + "</option>"); nodeSelect.append("<option value=" + data.Data.NodeId + " select disabled=true>" + 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); } $("#monitorName").val(data.Data.Name); $("#cpu").val(data.Data.Cpu); $("#Memory").val(data.Data.Memory); $("#GC").val(data.Data.GC); $("#recievers").val(data.Data.Reciever); } }); } else { // 绑定环境 domainSelect.empty(); $.getJSON('/env/GetAllEnvSubs', null, function (data) { if (data.StateCode == 0) { var content = "<option select>请选择环境</option>"; $.each(data.Data, function (idx, item) { content += "<option value=" + item.EnvSubId + ">" + item.EnvSubName + "</option>" }); domainSelect.append(content); } }); // 绑定站点 templateSelect.empty(); $.getJSON('/DomainTemplate/GetAllEnvDomainTemplates', null, function (data) { if (data.StateCode == 0) { var content = "<option select>请选择站点</option>"; $.each(data.Data, function (idx, item) { content += "<option value=" + item.Id + ">" + item.DomainName + "</option>" }); templateSelect.append(content); } }); //绑定onchange事件 templateSelect.change(function () { // 绑定子站点 monitorapppoolconfigpage.bingDomainNode(templateSelect.val(), 0); }); } $('#comitSettingBtn').click(function () { monitorapppoolconfigpage.commitMonitorConfig(); $.Dialog.close(); }); $('#cancelCommitBtn').click(function () { monitorapppoolconfigpage.getConfigSetingDialog(id); }); $('#closeCommitBtn').click(function () { $.Dialog.close(); }); }, 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.Cpu = $("#cpu").val(); config.Memory = $("#Memory").val(); config.GC = $("#GC").val(); config.SubId = $("#domain").val(); config.SubName = $("#domain").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"; } config.Reciever = $("#recievers").val(); if (config.NodeName == "全部") { $("#node option").each(function () { //遍历全部option var txt = $(this).text(); //获取option的内容 if (txt != "全部" && txt != "请选择子站点") //如果不是“全部”和"请选择子站点" { config.NodeName = txt; monitorapppoolconfigpage.postMonitorConfig(config); } }); } else { monitorapppoolconfigpage.postMonitorConfig(config); } }, postMonitorConfig: function (postData) { var url = '/AppPoolMonitor/CommitMonitorConfig'; var pack = new Object(); pack.Token = $.readCookie('accessToken'); pack.config = config; 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 + "监控配置成功!"); monitorapppoolconfigpage.render(); } else { $.note(null, "修改" + name + "监控配置失败!" + results.Message, 'error'); } }, error: function (xhr, status, error) { $.note(null, "发送修改" + name + "监控配置请求失败!", 'error'); } }); }, postTurnOn: function (id) { token = $.readCookie('accessToken'); $.post("/AppPoolMonitor/TurnOnMonitor", { "id": id, "alis": token }, function (data) { if (data.StateCode == 0) { $.note(null, '开启监控成功.'); } else { $.note(null, '开启监控失败.',"error"); } }); }, postTurnOff: function (id) { token = $.readCookie('accessToken'); $.post("/AppPoolMonitor/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)); }); } }); } }