c#实现服务器性能监控并发送邮件保存日志
程序员文章站
2024-02-24 22:55:28
客户端代码
复制代码 代码如下: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