欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2024-02-16 23:09:46
客户端代码 复制代码 代码如下:using system;using system.collections.generic;using system.componentm...

客户端代码

复制代码 代码如下:

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