一. 写在前面
本文Log4Net介绍了基础的方式,大数据量生产环境不能使用,中等日志量请日志单库。 希望爱技术的你不要错过exceptionless和ELK
第四节开始简单配置大牛们推荐的了ExceptionLess, 一款开源分布式日志系统。
日志系统对于任何项目都是必不可少的,无论对于测试阶段的debug,性能测试,执行时间,操作记录还是线上的问题排查,访问记录等,日志系统都扮演着重要的角色。本篇分享的目的是能帮助需要的人快速搭建自己的LogSystem.,仅供参考。 先上个图呗,自认为页面还算清爽吧:
我的LogSystem使用Log4net入库的方式,网上特别多的分享,但是能完整运行下来的真是很少,所以现在需要和以后用得上的小伙伴抓紧收藏咯。
二. Log4Net自定义内容入库
Log4Net存日志的方式,给人的感觉实在是不实用,IT行业不都求一个自动化吗?废话不说了,先上Log4net入库系统的代码。
LogSystem数据库结构,我的建议是一个项目一个表。
在Log组件中,你需要这样几个类。下面分别给出代码:
LogContent.cs,这里定义了Log实体,在实体化实体的时候,通过给构造函数传参创建好这个对象。注释很详细了
1 using System;
2
3 namespace LogComponent
4 {
5 public class LogContent
6 {
7
8 public LogContent(string logLevel, string logMsg, string logModule, string description, string userName)
9 {
10 LogLevel = logLevel;
11 UserName = userName;
12 Description = description;
13 LogMsg = logMsg;
14 LogModule = logModule;
15 }
16
17 /// <summary>
18 /// 日志级别
19 /// </summary>
20 public string LogLevel { get; set; }
21
22 /// <summary>
23 /// 日志消息
24 /// </summary>
25 public string LogMsg { get; set; }
26
27 /// <summary>
28 /// 系统登陆用户
29 /// </summary>
30 public string UserName { get; set; }
31
32 /// <summary>
33 /// 日志描述信息
34 /// </summary>
35 public string Description { get; set; }
36
37 /// <summary>
38 /// 记录时间
39 /// </summary>
40 public DateTime LogDate { get; set; }
41
42 /// <summary>
43 /// 模块名称
44 /// </summary>
45 public string LogModule { get; set; }
46 }
47 }
LogHelper.cs,定义了日志级别,和写入方法
1 [assembly: log4net.Config.XmlConfigurator(Watch = true,ConfigFile = "log4net.config")]
2 namespace LogComponent
3 {
4 public class LogHelper
5 {
6 static log4net.ILog log = log4net.LogManager.GetLogger("myLogger");
7
8 /// <summary>
9 /// 异常日志
10 /// </summary>
11 /// <param name="logMsg">日志信息</param>
12 /// <param name="logModule">代码模块</param>
13 /// <param name="description">其他描述</param>
14 /// <param name="userName">用户名</param>
15 public static void LogError(string logMsg, string logModule, string description = "", string userName = "")
16 {
17 log.Error(new LogContent("Error", SubLogString(logMsg), logModule, SubLogString(description), userName));
18 }
19
20 public static void LogInfo(string logMsg, string logModule, string description = "", string userName = "")
21 {
22 log.Info(new LogContent("Info", SubLogString(logMsg), logModule, SubLogString(description), userName));
23 }
24
25 public static void LogWarn(string logMsg, string logModule, string description = "", string userName = "")
26 {
27 log.Warn(new LogContent("Warn", SubLogString(logMsg), logModule, SubLogString(description), userName));
28 }
29
30 public static void LogDebug(string logMsg, string logModule, string description = "", string userName = "")
31 {
32 log.Debug(new LogContent("Debug", SubLogString(logMsg), logModule, SubLogString(description), userName));
33 }
34
35 private static string SubLogString(string str)
36 {
37 if (str.Length > 1500)
38 {
39 return str.Substring(0, 1500);
40 }
41 return str;
42 }
43 }
44 }
MessagePartternConverter.cs
1 using log4net.Core;
2 using log4net.Layout.Pattern;
3 using System.IO;
4 using System.Reflection;
5 namespace LogComponent
6 {
7 class MessagePatternConverter : PatternLayoutConverter
8 {
9 protected override void Convert(TextWriter writer, LoggingEvent loggingEvent)
10 {
11 if (Option != null)
12 {
13 // Write the value for the specified key
14 WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));
15 }
16 else
17 {
18 // Write all the key value pairs
19 WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());
20 }
21 }
22 /// <summary>
23 /// 通过反射获取传入的日志对象的某个属性的值
24 /// </summary>
25 /// <param name="property"></param>
26 /// <returns></returns>
27 private object LookupProperty(string property, log4net.Core.LoggingEvent loggingEvent)
28 {
29 object propertyValue = string.Empty;
30 PropertyInfo propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
31 if (propertyInfo != null)
32 propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);
33 return propertyValue;
34 }
35 }
36 }
MyLayout.cs
1 using log4net.Layout;
2 namespace LogComponent
3 {
4 class MyLayout : PatternLayout
5 {
6 public MyLayout()
7 {
8 this.AddConverter("property", typeof(MessagePatternConverter));
9 }
10 }
11 }
其实看到这里,最重要的并不是代码了,核心部分Log4net都帮我们写好了,关键在于你的配置,下面是log4net.config的内容。拿到你的web项目里是一样用的。但是不要忘了在你的项目中引用nuget:log4net哟。
log4net.config如下:在其中主要配置了log入库的参数和sql语句,当然还有sql连接。注释已经很详细了
1 <?xml version="1.0" encoding="utf-8" ?>
2 <configuration>
3 <configSections>
4 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
5 </configSections>
6 <log4net>
7 <root >
8 <level value="Debug"/>
9 <appender-ref ref="ADONetAppender"/>
10 </root>
11 <logger name="myLogger">
12 <level value="Debug"/>
13 <appender-ref ref="ADONetAppender"/>
14 </logger>
15 <appender name="ADONetAppender" type="log4net.Appender.ADONetAppender,log4net">
16 <!--BufferSize为缓冲区大小,只有日志记录超value条才会一块写入到数据库-->
17 <bufferSize value="1"/>
18 <!--或写为<param name="BufferSize" value="1" />-->
19 <!--引用-->
20 <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
21 <!--连接数据库字符串-->
22 <connectionString value="Data Source=115.29.54.31;Initial Catalog=LogSystem;uid=sa;pwd=sa.;MultipleActiveResultSets=True"/>
23 <!--插入到表Log-->
24 <commandText value="INSERT INTO HdPubLog ([LogDate],[LogMsg],[UserName],[Description],[LogLevel],[LogModule]) VALUES (@log_date,@LogMsg,@UserName,@Description,@LogLevel,@LogModule)"/>
25 <parameter>
26 <parameterName value="@log_date"/>
27 <dbType value="DateTime"/>
28 <layout type="log4net.Layout.RawTimeStampLayout"/>
29 <!--获取log4net中提供的日志时间RawTimeStampLayout为默认的时间输出格式-->
30 </parameter>
31 <parameter>
32 <parameterName value="@LogMsg"/>
33 <dbType value="String"/>
34 <size value="1510"/>
35 <layout type="LogComponent.MyLayout, LogComponent">
36 <param name="ConversionPattern" value="%property{LogMsg}"/>
37 </layout>
38 </parameter>
39 <parameter>
40 <parameterName value="@UserName"/>
41 <dbType value="String"/>
42 <size value="50"/>
43 <layout type="LogComponent.MyLayout, LogComponent">
44 <param name="ConversionPattern" value="%property{UserName}"/>
45 </layout>
46 </parameter>
47 <parameter>
48