.net 日志系统解析
一. 写在前面
日志系统对于任何项目都是必不可少的,无论对于测试阶段的debug,性能测试,执行时间,操作记录还是线上的问题排查,访问记录等,日志系统都扮演着重要的角色。本篇分享的目的是能帮助需要的人快速搭建自己的logsystem.,仅供参考。 先上个图呗,自认为页面还算清爽吧:
我的logsystem使用log4net入库的方式,网上特别多的分享,但是能完整运行下来的真是很少,所以现在需要和以后用得上的小伙伴抓紧收藏咯。
二. log4net自定义内容入库
log4net存日志的方式,给人的感觉实在是不实用,it行业不都求一个自动化吗?废话不说了,先上log4net入库系统的代码。
logsystem数据库结构,我的建议是一个项目一个表。
在log组件中,你需要这样几个类。下面分别给出代码:
logcontent.cs,这里定义了log实体,在实体化实体的时候,通过给构造函数传参创建好这个对象。注释很详细了
using system; namespace logcomponent { public class logcontent { public logcontent(string loglevel, string logmsg, string logmodule, string description, string username) { loglevel = loglevel; username = username; description = description; logmsg = logmsg; logmodule = logmodule; } /// <summary> /// 日志级别 /// </summary> public string loglevel { get; set; } /// <summary> /// 日志消息 /// </summary> public string logmsg { get; set; } /// <summary> /// 系统登陆用户 /// </summary> public string username { get; set; } /// <summary> /// 日志描述信息 /// </summary> public string description { get; set; } /// <summary> /// 记录时间 /// </summary> public datetime logdate { get; set; } /// <summary> /// 模块名称 /// </summary> public string logmodule { get; set; } } }
loghelper.cs,定义了日志级别,和写入方法
[assembly: log4net.config.xmlconfigurator(watch = true,configfile = "log4net.config")] namespace logcomponent { public class loghelper { static log4net.ilog log = log4net.logmanager.getlogger("mylogger"); /// <summary> /// 异常日志 /// </summary> /// <param name="logmsg">日志信息</param> /// <param name="logmodule">代码模块</param> /// <param name="description">其他描述</param> /// <param name="username">用户名</param> public static void logerror(string logmsg, string logmodule, string description = "", string username = "") { log.error(new logcontent("error", sublogstring(logmsg), logmodule, sublogstring(description), username)); } public static void loginfo(string logmsg, string logmodule, string description = "", string username = "") { log.info(new logcontent("info", sublogstring(logmsg), logmodule, sublogstring(description), username)); } public static void logwarn(string logmsg, string logmodule, string description = "", string username = "") { log.warn(new logcontent("warn", sublogstring(logmsg), logmodule, sublogstring(description), username)); } public static void logdebug(string logmsg, string logmodule, string description = "", string username = "") { log.debug(new logcontent("debug", sublogstring(logmsg), logmodule, sublogstring(description), username)); } private static string sublogstring(string str) { if (str.length > 1500) { return str.substring(0, 1500); } return str; } } }
messagepartternconverter.cs
using log4net.core; using log4net.layout.pattern; using system.io; using system.reflection; namespace logcomponent { class messagepatternconverter : patternlayoutconverter { protected override void convert(textwriter writer, loggingevent loggingevent) { if (option != null) { // write the value for the specified key writeobject(writer, loggingevent.repository, lookupproperty(option, loggingevent)); } else { // write all the key value pairs writedictionary(writer, loggingevent.repository, loggingevent.getproperties()); } } /// <summary> /// 通过反射获取传入的日志对象的某个属性的值 /// </summary> /// <param name="property"></param> /// <returns></returns> private object lookupproperty(string property, log4net.core.loggingevent loggingevent) { object propertyvalue = string.empty; propertyinfo propertyinfo = loggingevent.messageobject.gettype().getproperty(property); if (propertyinfo != null) propertyvalue = propertyinfo.getvalue(loggingevent.messageobject, null); return propertyvalue; } } }
mylayout.cs
using log4net.layout; namespace logcomponent { class mylayout : patternlayout { public mylayout() { this.addconverter("property", typeof(messagepatternconverter)); } } }
其实看到这里,最重要的并不是代码了,核心部分log4net都帮我们写好了,关键在于你的配置,下面是log4net.config的内容。拿到你的web项目里是一样用的。但是不要忘了在你的项目中引用nuget:log4net哟。
log4net.config如下:在其中主要配置了log入库的参数和sql语句,当然还有sql连接。注释已经很详细了
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configsections> <section name="log4net" type="log4net.config.log4netconfigurationsectionhandler, log4net"/> </configsections> <log4net> <root > <level value="debug"/> <appender-ref ref="adonetappender"/> </root> <logger name="mylogger"> <level value="debug"/> <appender-ref ref="adonetappender"/> </logger> <appender name="adonetappender" type="log4net.appender.adonetappender,log4net"> <!--buffersize为缓冲区大小,只有日志记录超value条才会一块写入到数据库--> <buffersize value="1"/> <!--或写为<param name="buffersize" value="1" />--> <!--引用--> <connectiontype value="system.data.sqlclient.sqlconnection, system.data, version=1.0.3300.0, culture=neutral, publickeytoken=b77a5c561934e089"/> <!--连接数据库字符串--> <connectionstring value="data source=115.29.54.31;initial catalog=logsystem;uid=sa;pwd=sa.;multipleactiveresultsets=true"/> <!--插入到表log--> <commandtext value="insert into hdpublog ([logdate],[logmsg],[username],[description],[loglevel],[logmodule]) values (@log_date,@logmsg,@username,@description,@loglevel,@logmodule)"/> <parameter> <parametername value="@log_date"/> <dbtype value="datetime"/> <layout type="log4net.layout.rawtimestamplayout"/> <!--获取log4net中提供的日志时间rawtimestamplayout为默认的时间输出格式--> </parameter> <parameter> <parametername value="@logmsg"/> <dbtype value="string"/> <size value="1510"/> <layout type="logcomponent.mylayout, logcomponent"> <param name="conversionpattern" value="%property{logmsg}"/> </layout> </parameter> <parameter> <parametername value="@username"/> <dbtype value="string"/> <size value="50"/> <layout type="logcomponent.mylayout, logcomponent"> <param name="conversionpattern" value="%property{username}"/> </layout> </parameter> <parameter> <parametername value="@description"/> <dbtype value="string"/> <size value="1510"/> <layout type="logcomponent.mylayout, logcomponent"> <param name="conversionpattern" value="%property{description}"/> </layout> </parameter> <parameter> <parametername value="@loglevel"/> <dbtype value="string"/> <size value="50"/> <layout type="logcomponent.mylayout, logcomponent"> <param name="conversionpattern" value="%property{loglevel}"/> </layout> </parameter> <parameter> <parametername value="@logmodule"/> <dbtype value="string"/> <size value="50"/> <layout type="logcomponent.mylayout, logcomponent"> <param name="conversionpattern" value="%property{logmodule}"/> </layout> </parameter> </appender> </log4net> </configuration>
这样一来,你的配置就完成了,你可以直接测试插入的情况:
三. 把log信息可视化
我的ui使用的是datatables.js,弹出框是layer,日期组件好像是laydate,下拉框是修改样式后的select2。ui代码是我自己的一个框架里的,内容太多就不贴出来了,你只需要和以前一样,把数据从库里查出来,绑定给任意你喜欢的数据表格上。由于单页面的日志系统没有什么复杂操作,就用个sqlhelper查一下就算了,代码和条件拼接如下
public class xxxdal { private sqlhelper _sqlhelper = new sqlhelper(); /// <summary> /// 获取xxx的日志 /// </summary> /// <param name="model"></param> /// <returns></returns> public list<logmodel> getxxxlog(sm_logmodel model) { stringbuilder sql = new stringbuilder(); list<sqlparameter> sqlparameters = new list<sqlparameter>(); stringbuilder sqlwhere = new stringbuilder(); if (!string.isnullorwhitespace(model.logstarttime)) { sqlparameters.add(new sqlparameter("@logstarttime", model.logstarttime)); sqlwhere.append(@" and h.logdate > @logstarttime"); } if (!string.isnullorwhitespace(model.logendtime)) { sqlparameters.add(new sqlparameter("@logendtime", model.logendtime)); sqlwhere.append(@" and h.logdate < @logendtime"); } if (!string.isnullorwhitespace(model.loglevel)) { sqlparameters.add(new sqlparameter("@loglevel", model.loglevel)); sqlwhere.append(@" and h.loglevel = @loglevel"); } if (!string.isnullorwhitespace(model.logmodule)) { sqlparameters.add(new sqlparameter("@logmodule", model.logmodule)); sqlwhere.append(@" and h.logmodule = @logmodule"); } sql.appendformat(@" with t as ( select row_number() over ( order by id desc ) as indexnum , [id] , convert(varchar, [logdate], 21) as [logdate] , [username] , substring([description], 0, 150) as [description] , substring([logmsg], 0, 200) as [logmsg] , [loglevel] , [logmodule] from [logsystem].[dbo].[xxxlog] h where 1 = 1 {0} ) select * from t where indexnum > @startindex and indexnum < @endindex", sqlwhere); sqlparameters.add(new sqlparameter("@startindex", model.start)); sqlparameters.add(new sqlparameter("@endindex", model.start + model.length)); datatable dt = _sqlhelper.executedatatable(sql.tostring(), sqlparameters.toarray()); return datatabletools<logmodel>.datatabletolist(dt); } public int getxxxlogtotalcount(sm_logmodel model) { stringbuilder sql = new stringbuilder(); list<sqlparameter> sqlparameters = new list<sqlparameter>(); sql.append(@" select count(*) from [hdpublog] h where 1=1 "); if (!string.isnullorwhitespace(model.logstarttime)) { sqlparameters.add(new sqlparameter("@logstarttime", model.logstarttime)); sql.append(@" and h.logdate > @logstarttime"); } if (!string.isnullorwhitespace(model.logendtime)) { sqlparameters.add(new sqlparameter("@logendtime", model.logendtime)); sql.append(@" and h.logdate < @logendtime"); } if (!string.isnullorwhitespace(model.loglevel)) { sqlparameters.add(new sqlparameter("@loglevel", model.loglevel)); sql.append(@" and h.loglevel = @loglevel"); } if (!string.isnullorwhitespace(model.logmodule)) { sqlparameters.add(new sqlparameter("@logmodule", model.logmodule)); sql.append(@" and h.logmodule = @logmodule"); } return _sqlhelper.executescalar<int>(sql.tostring(), sqlparameters.toarray()); } [httppost] public logmodel getxxxxsignellog(int id) { string sql = @" select [id] , convert(varchar(30), [logdate], 21) as [logdate] , [username] , [description] , [logmsg] , [loglevel] , [logmodule] , [id] indexnum from [logsystem].[dbo].[xxxxlog] h where h.id = @id"; var row = _sqlhelper.executedatarow(sql, new sqlparameter("@id", id)); return datatabletools<logmodel>.datarowtomodel(row); } }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持!