首页 > 编程 > .NET > 正文

.net 日志系统解析

2020-01-17 22:30:09
字体:
来源:转载
供稿:网友

一.   写在前面

日志系统对于任何项目都是必不可少的,无论对于测试阶段的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); } }

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持武林网!

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表