隐藏

c#实现服务器性能监控并发送邮件保存日志

发布:2021/11/6 13:35:21作者:管理员 来源:本站 浏览次数:700

客户端代码


复制代码 代码如下:


using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.ServiceProcess;

using System.Text;

using System.Threading;

using System.Management;

using System.Configuration;

using System.Net;

using System.IO;


namespace MON.WS

{

   public partial class Service : ServiceBase

   {

       //post 11.9

       //卸载服务

       //installutil /u F:\XLFX-2\XLFX\MON.WS\bin\debug\MON.WS.EXE

       //安装服务

       //installutil F:\XLFX-2\XLFX\MON.WS\bin\debug\MON.WS.EXE

       object threadObj;

       Thread jobThread;

       Dictionary<string, PerformanceCounter> dicCounter;

       Dictionary<string, ManagementObject> dicDisk;


       public Service()

       {

           InitializeComponent();

       }

       /// <summary>

       /// 服务启动

       /// </summary>

       /// <param name="args"></param>

       protected override void OnStart(string[] args)

       {

           threadObj = new object();

           dicCounter = new Dictionary<string, PerformanceCounter>();

           dicDisk = new Dictionary<string, ManagementObject>();

           jobThread = new Thread(new ThreadStart(Job));

           jobThread.IsBackground = true;

           jobThread.Start();

       }

       /// <summary>

       /// 服务停止

       /// </summary>

       protected override void OnStop()

       {

           if (jobThread.IsAlive)

           {

               jobThread.Abort();

               jobThread.Join();

           }

           foreach (var obj in dicCounter.Values)

           {

               obj.Dispose();

           }

           foreach (var obj in dicDisk.Values)

           {

               obj.Dispose();

           }

           dicDisk.Clear();

           dicCounter.Clear();

       }


       /// <summary>

       /// 监控线程

       /// </summary>

       void Job()

       {

           while (true)

           {

               lock (threadObj)

               {

                   //监控开始

                   try

                   {

                       var obj = new MONServiceClient.MONService();

                       var hn = Dns.GetHostName();

                       var ips = GetIpv4Address(hn);                      

                       if (ips.Count < 1)

                       {

                           obj.Dispose();

                           Thread.Sleep(60000);//如果服务器出错,那么就每分钟去检查一次

                           WriteLog("一个IPV4的地址也没有得到");

                           continue;

                       }

                       DataSet ds = GetConfigDS(hn,ips,obj);

                       if (ds == null)

                       {

                           obj.Dispose();

                           Thread.Sleep(60000);

                           WriteLog("请检查WEBService和全局变量设置");

                           continue;

                       }

                       int sleepTime;

                       try

                       {

                           sleepTime = Convert.ToInt32(ds.Tables[0].Rows[0]["LOG_CIRC"]) * 1000;//毫秒

                       }

                       catch

                       {

                           sleepTime = 60000;

                       }

                       if (sleepTime < 1)

                       {

                           sleepTime = 60000;

                       }

                       Thread.Sleep(sleepTime);

                       if (ds.Tables[1].Rows[0]["S_ISWATCH"].ToString() == "0")

                       {

                           //监控开关->关闭

                           obj.Dispose();

                           continue;

                       }

                       var arr = getWatchValue(ds).ToArray();

                       obj.UpdateServerStatus(arr);

                       obj.Dispose();

                   }

                   catch (Exception ex)

                   {

                       WriteLog(ex.Message);

                   }

                   //监控结束

               }

           }

       }

       /// <summary>

       /// 获取配置信息

       /// </summary>

       /// <param name="ips"></param>

       /// <returns></returns>

       DataSet GetConfigDS(string hn,List<IPAddress> ips,MONServiceClient.MONService obj)

       {

           DataSet ds;

           try

           {

               if (ips.Count > 1)

               {

                   ds = obj.GetMachineConfig(hn, ips[0].ToString(), ips[1].ToString());

               }

               else

               {

                   ds = obj.GetMachineConfig(hn, ips[0].ToString(), "");

               }

           }

           catch

           {

               ds = null;

           }

           return ds;

       }

       /// <summary>

       /// 获取性能数组

       /// </summary>

       /// <param name="ds"></param>

       /// <returns></returns>

       List<string> getWatchValue(DataSet ds)

       {

           var result = new List<string>();

           result.Add(ds.Tables[1].Rows[0]["LIST_ID"].ToString());

           result.Add(GetValue(ds.Tables[1].Rows[0]["S_CPU"].ToString()).ToString("F2"));

           result.Add(GetDiskValue(ds.Tables[1].Rows[0]["S_DISK_APP"].ToString()).ToString("F2"));

           result.Add(GetDiskValue(System.Environment.SystemDirectory.Substring(0, 2)).ToString("F2"));

           result.Add(GetValue(ds.Tables[1].Rows[0]["S_MEMORY"].ToString()).ToString("F2"));

           result.Add(GetValue(ds.Tables[1].Rows[0]["S_FLOW_IN"].ToString()).ToString("F2"));

           result.Add(GetValue(ds.Tables[1].Rows[0]["S_FLOW_OUT"].ToString()).ToString("F2"));

           result.Add(GetValue(ds.Tables[1].Rows[0]["S_WEB_PORT"].ToString()).ToString("F2"));

           result.Add(GetValue(ds.Tables[1].Rows[0]["S_SQL_CONNECT"].ToString()).ToString("F2"));

           result.Add(ds.Tables[1].Rows[0]["CAMP_ID"].ToString());

           result.Add(ds.Tables[1].Rows[0]["CICODE"].ToString());

           result.Add(ds.Tables[1].Rows[0]["S_KIND"].ToString());

           return result;

       }

       /// <summary>

       /// 获取IPV4的地址

       /// </summary>

       /// <param name="hn"></param>

       /// <returns></returns>

       List<IPAddress> GetIpv4Address(string hn)

       {

           var result = new List<IPAddress>();

           var ips = Dns.GetHostAddresses(hn);

           foreach (var ip in ips)

           {

               if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)

               {

                   result.Add(ip);

               }

           }

           return result;

       }

       /// <summary>

       /// 获取性能计数器的值

       /// </summary>

       /// <param name="configStr"></param>

       /// <returns></returns>

       double GetValue(string configStr)

       {

           try

           {

               if (!dicCounter.ContainsKey(configStr))

               {

                   var arr = configStr.Split('#');

                   var pc = new PerformanceCounter();

                   pc.CategoryName = arr[0];

                   pc.CounterName = arr[1];

                   pc.InstanceName = arr[2];

                   dicCounter.Add(configStr, pc);

               }

               return dicCounter[configStr].NextValue();

           }

           catch (Exception ex)

           {

               WriteLog(string.Format("计数器取值错误:{0}{1}{2}", configStr, Environment.NewLine, ex.Message));

               return -1;

           }

       }

       /// <summary>

       /// 获取磁盘信息的值

       /// </summary>

       /// <param name="key"></param>

       /// <returns></returns>

       double GetDiskValue(string key)

       {

           try

           {

               if (!dicDisk.ContainsKey(key))

               {

                   ManagementObject DiskInfo = new ManagementObject(string.Format("win32_logicaldisk.deviceid=\"{0}\"", key));

                   dicDisk.Add(key, DiskInfo);

               }

               dicDisk[key].Get();

               var s = Convert.ToDouble(dicDisk[key]["Size"]);

               var l = Convert.ToDouble(dicDisk[key]["FreeSpace"]);

               var d = (s - l) / s * 100;

               return d;

           }

           catch (Exception ex)

           {

               WriteLog(string.Format("获取磁盘信息值错误:{0}{1}{2}", key, Environment.NewLine, ex.Message));

               return -1;

           }

       }

       /// <summary>

       /// 写本地日志

       /// </summary>

       /// <param name="text"></param>

       void WriteLog(string text)

       {

           try

           {

               var logDic = ConfigurationManager.AppSettings["LogDic"];

               int logDays;

               try

               {

                   logDays = Convert.ToInt32(ConfigurationManager.AppSettings["LogDays"]);

               }

               catch

               {

                   logDays = 7;

               }

               if (logDays < 1)

               {

                   logDays = 7;

               }

               var fs = LogFileMon(logDic, logDays);

               StreamWriter writer = new StreamWriter(fs);

               writer.WriteLine(DateTime.Now.ToString());

               writer.WriteLine(text);

               writer.WriteLine("-----------------------------------------------------------");

               writer.Flush();

               writer.Close();

               fs.Close();

           }

           catch

           {

               //写日志出错就没办法了

           }

       }

       /// <summary>

       /// 维护日志文件

       /// </summary>

       /// <param name="logDic"></param>

       /// <param name="days"></param>

       FileStream LogFileMon(string logDic, int dayCount)

       {

           DirectoryInfo di = new DirectoryInfo(logDic);

           //如果日志文件夹不存在则创建日志文件夹;

           if (!di.Exists)

           {

               di.Create();

           }

           //当前应保存的日志数据

           List<string> days = new List<string>();

           for (var i = 0; i < dayCount; i++)

           {

               var d = DateTime.Now.AddDays(0 - i).ToString("yyyy-MM-dd");

               days.Add(string.Format("{0}.log", d));

           }

           //删除没用的历史数据

           foreach (var f in di.GetFiles())

           {

               if (!days.Contains(f.Name))

               {

                   f.Delete();

               }

           }

           //返回当前日志文件的数据流

           var fileName = Path.Combine(logDic, days[0]);

           var fs = File.Open(fileName, FileMode.Append,FileAccess.Write);

           return fs;

       }

   }

}


服务端代码


复制代码 代码如下:


Imports System.Web.Services

Imports System.Web.Services.Protocols

Imports System.ComponentModel

Imports System.Threading

Imports System.Collections.Generic

Imports System.Text


' 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。

' <System.Web.Script.Services.ScriptService()> _

<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _

<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _

<ToolboxItem(False)> _

Public Class MONService

   Inherits System.Web.Services.WebService


   <WebMethod()> _

   Public Function GetMachineConfig(ByVal HostName As String, ByVal IP1 As String, ByVal IP2 As String) As DataSet

       Dim sqlda As New data_source.WebTao.Public.SqlServerData

       Try

           Dim sSQL As String = "select *  from mon_server_list " & _

               " where S_HOSTNAME ='" & HostName & "' and IP1 = '" & IP1 & "'  and IP2 = '" & IP2 & "'"

           Dim dt As DataTable = sqlda.GetMytable(sSQL)

           If dt.Rows.Count < 1 Then

               sqlda.runSql("insert into mon_server_list (S_HOSTNAME,IP1,IP2,S_ISWATCH,CICODE,S_NAME,CAMP_ID,S_KIND,STATUS) values ('" & HostName & "','" & IP1 & "','" & IP2 & "',0,'待确定','待确定',-1,0,0)")

               dt = sqlda.GetMytable(sSQL)

               sqlda.runSql("INSERT INTO [MON_INFO] ([LIST_ID],[S_CPU],[S_DISK_APP],[S_DISK_SYS],[S_MEMORY],[S_FLOW_IN],[S_FLOW_OUT],[S_WEB_PORT],[S_SQL_CONNECT],[IN_TIME]) VALUES (" & dt.Rows(0)("LIST_ID").ToString() & ",-1,-1,-1,-1,-1,-1,-1,-1,'" & Now.ToString() & "') ")

           End If

           Dim result As DataSet = sqlda.GetMyDataSet("select * from MON_PARAMETER")

           result.Tables.Add(dt)

           Return result

       Catch ex As Exception

           Return Nothing

       End Try

   End Function

   <WebMethod()> _

   Public Function UpdateServerStatus(ByVal ParamArray ValueArr() As String)

       Dim sqlda As New data_source.WebTao.Public.SqlServerData

       Try

           Dim sSQL As String = "UPDATE [MON_INFO] " & _

                 " SET " & _

                 " [S_CPU] = " & ValueArr(1) & _

                 " ,[S_DISK_APP] = " & ValueArr(2) & _

                 " ,[S_DISK_SYS] = " & ValueArr(3) & _

                 " ,[S_MEMORY] = " & ValueArr(4) & _

                 " ,[S_FLOW_IN] = " & ValueArr(5) & _

                 " ,[S_FLOW_OUT] = " & ValueArr(6) & _

                 " ,[S_WEB_PORT] = " & ValueArr(7) & _

                 " ,[S_SQL_CONNECT] = " & ValueArr(8) & _

                 " ,[IN_TIME] = '" & Now.ToString() & "'" & _

                 " WHERE LIST_ID = " & ValueArr(0)

           sqlda.runSql(sSQL)

           '没有策略

           If ValueArr(9).Trim() = "-1" Or String.IsNullOrEmpty(ValueArr(9).Trim()) Then

               Return 0

           End If

           '找到策略

           sSQL = "select * from MON_CAMPAIGN_LIST where CAMP_ID = " & ValueArr(9)

           Dim dt As DataTable = sqlda.GetMytable(sSQL)

           Dim Dic As New Dictionary(Of String, String)

           Dic.Add("S_PRIORITY", dt.Rows(0)("S_PRIORITY").ToString())

           Dic.Add("S_ACTION", dt.Rows(0)("S_ACTION").ToString())


           '验证策略

           sSQL = "select count(*) from MON_INFO where 1=1 and " & dt.Rows(0)("S_NAME").ToString & " and LIST_ID = " & ValueArr(0)

           Dim FLAG = CType(sqlda.myExecuteScalar(sSQL), Integer)

           '没有超标

           If FLAG < 1 Then

               Return 0

           End If


           '是否到了下一个轮训间隔

           sSQL = "select TOP 1 * from [MON_MAIL]   WHERE list_id = " & ValueArr(0) & "  ORDER BY S_SENDTIME DESC "

           dt = sqlda.GetMytable(sSQL)

           Dim ts As TimeSpan = TimeSpan.MaxValue

           If dt.Rows.Count > 0 Then

               Dim thatTime As DateTime = CType(dt.Rows(0)("S_SENDTIME"), DateTime)

               ts = DateTime.Now.Subtract(thatTime)

           End If

           sSQL = "select * from MON_PARAMETER"

           dt = sqlda.GetMytable(sSQL)

           Dim circ As Integer = CType(dt.Rows(0)("MAIL_CIRC"), Integer)

           If ts.TotalSeconds < circ Then

               Return 0

           End If


           '异步发信

           Dic.Add("S_TITLE", dt.Rows(0)("S_TITLE").ToString())

           Dic.Add("MAIL_SMTP_SERVER", dt.Rows(0)("MAIL_SMTP_SERVER").ToString())

           Dic.Add("MAIL_ACCOUNT", dt.Rows(0)("MAIL_ACCOUNT").ToString())

           Dic.Add("MAIL_PASSWORD", dt.Rows(0)("MAIL_PASSWORD").ToString())

           Dic.Add("MAIL_FROM", dt.Rows(0)("MAIL_FROM").ToString())

           Dic.Add("MAIL_ADDRESS", dt.Rows(0)("MAIL_ADDRESS").ToString())

           Dim sout As Double

           Dim sin As Double

           Try

               sin = Convert.ToDouble(ValueArr(5)) / 1024.0

               sout = Convert.ToDouble(ValueArr(6)) / 1024.0

           Catch ex As Exception

               sin = -1

               sout = -1

           End Try

           Dim sb As New StringBuilder()

           sb.AppendFormat("CPU使用率:{0}%<br />", ValueArr(1))

           sb.AppendFormat("内存使用率:{0}%<br />", ValueArr(4))

           sb.AppendFormat("系统磁盘使用率:{0}%<br />", ValueArr(3))

           sb.AppendFormat("文件磁盘使用率:{0}%<br />", ValueArr(2))

           sb.AppendFormat("网络下行流量IN:{0}KB/S<br />", sin.ToString())

           sb.AppendFormat("网络上行流量OUT:{0}KB/S<br />", sout.ToString())

           sb.AppendFormat("网站连接数:{0}<br />", ValueArr(7))

           sb.AppendFormat("数据库连接数:{0}<br />", ValueArr(8))

           Dim subject As String = String.Format("人力运营管理系统监控告警:{0}{1}", ValueArr(10), IIf(ValueArr(11) = "0", "WEB服务器", "数据库服务器"))

           Dim body As String = String.Format("{0}<br />{1}<br />{2}<br />{3}<br />{4}", DateTime.Now.ToString(), Dic("S_PRIORITY"), Dic("S_TITLE"), sb.ToString(), Dic("S_ACTION"))

           'TODO:oracle不支持~select @@identity

           sSQL = "INSERT INTO [MON_MAIL] ([LIST_ID] ,[S_SOURCE] ,[S_CONTENT] ,[S_ACTION] ,[S_PRIORITY] ,[S_ADDRESS] ,[STATUS] ,[S_SENDTIME]) VALUES " & _

           "(" & ValueArr(0) & ",'" & Dic("S_TITLE") & "','" & sb.ToString() & "','" & Dic("S_ACTION") & "','" & Dic("S_PRIORITY") & "','" & dt.Rows(0)("MAIL_ADDRESS").ToString() & "',0,'" & DateTime.Now.ToString() & "');select @@identity"

           Dim index As Integer = CType(sqlda.myExecuteScalar(sSQL), Integer)


           Dic.Add("SUBJECT", subject)

           Dic.Add("BODY", body)

           Dic.Add("INDEX", index)

           Dic.Add("CONSTR", sqlda.GetMyConnStr())


           ThreadPool.QueueUserWorkItem(AddressOf SendMail, Dic)

       Catch ex As Exception


       End Try

   End Function

   Function SendMail(ByVal setting As Object) As Integer

       Try

           Dim Dic As Dictionary(Of String, String) = CType(setting, Dictionary(Of String, String))

           Dim iSmtpSetting As New PublicFunction.SmtpSetting

           iSmtpSetting.SmtpServer = Dic("MAIL_SMTP_SERVER")

           iSmtpSetting.SystemEmailAccount = Dic("MAIL_ACCOUNT")

           iSmtpSetting.SystemEmailAccountPassword = Dic("MAIL_PASSWORD")

           iSmtpSetting.SmtpAuthenticationType = 1

           Dim result As Boolean = PublicFunction.Mail.SendMail(iSmtpSetting, Dic("MAIL_FROM"), Dic("MAIL_ADDRESS"), Dic("SUBJECT"), Dic("BODY"), True, System.Web.Mail.MailPriority.High, System.Text.Encoding.UTF8, New String() {})

           Dim val As Integer = IIf(result, 1, 2)

           Dim sqlda As New data_source.WebTao.Public.SqlServerData(Dic("CONSTR"))

           sqlda.runSql("update MON_MAIL set STATUS = " & val & " where MAIL_ID = " & Dic("INDEX"))

       Catch ex As Exception


       End Try

   End Function

End Class