A Unified Logging System

Keywords: ASP.NET SQL Database Attribute xml

The copyright of this article belongs to the Blog Garden and the author Wu Shuang himself. The original address of the reprint and the reptile must be indicated. www.cnblogs.com/tdws .
This system is a self-use system. Only when so many gods in the comment area recommend other technologies can they know how low they are. Only through communication can we make progress. We must study when we go back.

I. Write in front

This paper introduces the basic way, large data volume production environment can not be used, medium log volume please log single library. Hope you love technology and don't miss exceptionless and ELK. Of course, you can also use nosql + search technology.

Logging system is indispensable for any project. It plays an important role in debug, performance test, execution time, operation record, online problem checking, access record and so on. The purpose of this article is to help people in need to quickly build their own Log System. For reference only. First of all, I think the page is refreshing.

My Log System uses Log4net to store, and there is a lot of sharing on the internet, but few of them can run completely, so now we need to collect them with our little friends who can be used in the future.

 

2. Log4Net Custom Content Storage

Log4Net logs, the way people feel is not practical, the IT industry does not require an automation? Don't talk nonsense. Go to the code of Log4net storage system first.

LogSystem database structure, my recommendation is a project, a table.

In the Log component, you need these classes. The following code is given separately:

LogContent.cs, which defines the Log entity, creates the object by passing parameters to the constructor when it materializes the entity. The notes are very detailed.

 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         /// log level
19         /// </summary>
20         public string LogLevel { get; set; }
21 
22         /// <summary>
23         /// Log message
24         /// </summary>
25         public string LogMsg { get; set; }
26 
27         /// <summary>
28         /// System login users
29         /// </summary>
30         public string UserName { get; set; }
31 
32         /// <summary>
33         /// Log Description Information
34         /// </summary>
35         public string Description { get; set; }
36 
37         /// <summary>
38         /// Recording time
39         /// </summary>
40         public DateTime LogDate { get; set; }
41 
42         /// <summary>
43         /// Module name
44         /// </summary>
45         public string LogModule { get; set; }
46     }
47 }

LogHelper.cs, which defines log level and write method

 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         /// Abnormal log
10         /// </summary>
11         /// <param name="logMsg">log information</param>
12         /// <param name="logModule">Code module</param>
13         /// <param name="description">Other description</param>
14         /// <param name="userName">User name</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         /// Getting the value of an attribute of the incoming log object by reflection
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 }

Actually, the most important thing is not the code. The core part of Log4net is written for us. The key is your configuration. Here is the content of log4net.config. It's just as useful to get your web project. But don't forget to refer to nuget: log4net in your project.

log4net.config is as follows: in which the main configuration log into the library parameters and sql statements, of course, there are sql connections. The annotations are very detailed.

 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 For buffer size, only log super value Only one bar is written to the database.-->
17       <bufferSize value="1"/>
18       <!--Or written as<param name="BufferSize" value="1" />-->
19       <!--Quote-->
20       <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
21       <!--Connect database string-->
22       <connectionString value="Data Source=115.29.54.31;Initial Catalog=LogSystem;uid=sa;pwd=sa.;MultipleActiveResultSets=True"/>
23       <!--Insert to table 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         <!--Obtain log4net The log time provided in RawTimeStampLayout Output format for default time-->
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         <parameterName value="@Description"/>
49         <dbType value="String"/>
50         <size value="1510"/>
51         <layout type="LogComponent.MyLayout, LogComponent">
52           <param name="ConversionPattern" value="%property{Description}"/>
53         </layout>
54       </parameter>
55       <parameter>
56         <parameterName value="@LogLevel"/>
57         <dbType value="String"/>
58         <size value="50"/>
59         <layout type="LogComponent.MyLayout, LogComponent">
60           <param name="ConversionPattern" value="%property{LogLevel}"/>
61         </layout>
62       </parameter>
63       <parameter>
64         <parameterName value="@LogModule"/>
65         <dbType value="String"/>
66         <size value="50"/>
67         <layout type="LogComponent.MyLayout, LogComponent">
68           <param name="ConversionPattern" value="%property{LogModule}"/>
69         </layout>
70       </parameter>
71     </appender>
72   </log4net>
73 </configuration>

In this way, your configuration is complete and you can test the insertion directly:

3. Visualizing Log Information

My UI uses Datatables.js, the pop-up box is layer, the date component is like layDate, and the drop-down box is select2 after modifying the style. UI code is a framework of my own, too much content will not be posted out, you just need to look up the data from the library, as before, bound to any data table you like. Since the single page log system has no complicated operation, just check it with sqlHelper. The code and conditions are mosaic as follows

  1 public class xxxDal
  2     {
  3         private SqlHelper _sqlHelper = new SqlHelper();
  4 
  5         /// <summary>
  6         /// Obtain xxx Log
  7         /// </summary>
  8         /// <param name="model"></param>
  9         /// <returns></returns>
 10         public List<LogModel> GetxxxLog(SM_LogModel model)
 11         {
 12             StringBuilder sql = new StringBuilder();
 13             List<SqlParameter> sqlParameters = new List<SqlParameter>();
 14             StringBuilder sqlWhere = new StringBuilder();
 15             if (!string.IsNullOrWhiteSpace(model.LogStartTime))
 16             {
 17                 sqlParameters.Add(new SqlParameter("@LogStartTime", model.LogStartTime));
 18                 sqlWhere.Append(@" AND h.LogDate > @LogStartTime");
 19             }
 20             if (!string.IsNullOrWhiteSpace(model.LogEndTime))
 21             {
 22                 sqlParameters.Add(new SqlParameter("@LogEndTime", model.LogEndTime));
 23                 sqlWhere.Append(@"  AND h.LogDate < @LogEndTime");
 24             }
 25             if (!string.IsNullOrWhiteSpace(model.LogLevel))
 26             {
 27                 sqlParameters.Add(new SqlParameter("@LogLevel", model.LogLevel));
 28                 sqlWhere.Append(@" AND h.LogLevel = @LogLevel");
 29             }
 30             if (!string.IsNullOrWhiteSpace(model.LogModule))
 31             {
 32                 sqlParameters.Add(new SqlParameter("@LogModule", model.LogModule));
 33                 sqlWhere.Append(@" AND h.LogModule = @LogModule");
 34             }
 35             sql.AppendFormat(@"
 36                     WITH    t AS ( SELECT   ROW_NUMBER() OVER ( ORDER BY id DESC ) AS IndexNum ,
 37                         [Id] ,
 38                         CONVERT(VARCHAR, [LogDate], 21) AS [LogDate] ,
 39                         [UserName] ,
 40                         SUBSTRING([Description], 0, 150) AS [Description] ,
 41                         SUBSTRING([LogMsg], 0, 200) AS [LogMsg] ,
 42                         [LogLevel] ,
 43                         [LogModule]
 44                FROM     [LogSystem].[dbo].[xxxLog] h
 45                WHERE    1 = 1
 46                        {0}
 47              )
 48     SELECT  *
 49     FROM    t
 50     WHERE   IndexNum > @startIndex
 51             AND indexnum < @endIndex", sqlWhere);
 52             sqlParameters.Add(new SqlParameter("@startIndex", model.Start));
 53             sqlParameters.Add(new SqlParameter("@endIndex", model.Start + model.Length));
 54 
 55             DataTable dt = _sqlHelper.ExecuteDataTable(sql.ToString(), sqlParameters.ToArray());
 56             return DataTableTools<LogModel>.DataTableToList(dt);
 57         }
 58 
 59         public int GetxxxLogTotalCount(SM_LogModel model)
 60         {
 61             StringBuilder sql = new StringBuilder(); List<SqlParameter> sqlParameters = new List<SqlParameter>();
 62             sql.Append(@"
 63                     SELECT  COUNT(*)
 64                     FROM    [HdPubLog] h where 1=1 ");
 65             if (!string.IsNullOrWhiteSpace(model.LogStartTime))
 66             {
 67                 sqlParameters.Add(new SqlParameter("@LogStartTime", model.LogStartTime));
 68                 sql.Append(@" AND h.LogDate > @LogStartTime");
 69             }
 70             if (!string.IsNullOrWhiteSpace(model.LogEndTime))
 71             {
 72                 sqlParameters.Add(new SqlParameter("@LogEndTime", model.LogEndTime));
 73                 sql.Append(@" AND h.LogDate < @LogEndTime");
 74             }
 75             if (!string.IsNullOrWhiteSpace(model.LogLevel))
 76             {
 77                 sqlParameters.Add(new SqlParameter("@LogLevel", model.LogLevel));
 78                 sql.Append(@" AND h.LogLevel = @LogLevel");
 79             }
 80             if (!string.IsNullOrWhiteSpace(model.LogModule))
 81             {
 82                 sqlParameters.Add(new SqlParameter("@LogModule", model.LogModule));
 83                 sql.Append(@" AND h.LogModule = @LogModule");
 84             }
 85             return _sqlHelper.ExecuteScalar<int>(sql.ToString(), sqlParameters.ToArray());
 86         }
 87 
 88         [HttpPost]
 89         public LogModel GetxxxxSignelLog(int id)
 90         {
 91             string sql = @"
 92                     SELECT  [Id] ,
 93                             CONVERT(VARCHAR(30), [LogDate], 21) AS [LogDate] ,
 94                             [UserName] ,
 95                             [Description] ,
 96                             [LogMsg] ,
 97                             [LogLevel] ,
 98                             [LogModule] ,
 99                             [Id] IndexNum 
100                     FROM    [LogSystem].[dbo].[xxxxLog] h
101                     WHERE   h.id = @Id";
102             var row = _sqlHelper.ExecuteDataRow(sql, new SqlParameter("@Id", id));
103             return DataTableTools<LogModel>.DataRowToModel(row);
104         }
105     }

IV. Write at the end

     

Aren't you going to build a Log System for yourself? If you can use it, grab the collection. If you have any questions, please leave a message.
If my sharing helps you a little, please click the red button below to pay attention. I will continue to export dry goods sharing. You are also welcome to give me some praise and support for yourself.

 

Keep learning and remember modesty. It's funny and dreamy.

Posted by mblack0508 on Wed, 20 Mar 2019 09:54:27 -0700