当前位置:网站首页>Analysis of serilog source code -- how to use it

Analysis of serilog source code -- how to use it

2020-11-06 20:10:10 itread01

In the last two articles ([ Link to 1](https://www.cnblogs.com/iskcal/p/implementation-of-the-log-demo-1.html) and [ Link to 2](https://www.cnblogs.com/iskcal/p/implementation-of-the-log-demo-2.html)) in , We go through a simple demo Learned a simple logging class library needs the function , That is, what information is contained in a log , And how to record the same log message to multiple log media at one time . In this paper , For Serilog, We can learn from the following aspects Serilog Core functional requirements and usage , And for the next article to officially start to explore the source code related work .([ Series catalog ](https://www.cnblogs.com/iskcal/p/introduction-to-the-source-code-of-serilog.html# Catalog )) ## Serilog Core functions at present , stay Asp.net core in , For the logbook Library , Except for what Microsoft officially prepared Microsoft.Extensions.Logging Outside ,Serilog It is also one of the most commonly used logging class libraries . As one of the most commonly used logging Libraries ,Serilog It has good expansibility , The organization maintains 60 Many projects are for Serilog An extension kit class library that provides additional functionality . To better understand what the source code is doing , We need to be right Serilog There is a basic function to understand . ### 1. Serilog Where to record the log information ? Serilog The medium of logging is called Sink, stay Serilog In the class library maintained by the organization , There are all kinds of Sink, For example, write to the console ConsoleSink And the ones written into the file FileSink etc. . These Sink The package name of is usually named Serilog.Sinks.XXX. So Serilog How to get to more than one Sinks Write to the log in ? Here is an example of writing logs to the console and file . Before that , We need to add three packages to our project : - Serilog - Serilog.Sinks.Console - Serilog.Sinks.File After adding three packages , The log can be written to the console and file through the following call methods . ```csharp var log = new LoggerConfiguration() .WriteTo.Console() .WriteTo.File("./log.txt") .CreateLogger(); log.Information("Hello world."); log.Error("Hello world, again."); ``` If you're right about the previous Demo If you understand , Then you will feel that this code is very familiar .`LoggerConfiguration` Similar to the previous `LogBuilder`, Through `CreateLogger` Function to create the corresponding logger , call `Console` and `File` The function is similar to the previous `AddConsole` as well as `AddFile` Method , The number and form of the input arguments are exactly the same . But the difference is that these functions are in `WriteTo` Call on the object instead of `LoggerConfiguration` Make a call on , This is the same as the previous Demo It's not the same , But this does not affect our understanding of . Later , The log is recorded by `Information` and `Error` Function to call , and LogDemo Used in `LogInformation` and `LogError` Function logging . ![Serilog Log information output to the console ](https://img2020.cnblogs.com/blog/1077681/202009/1077681-20200901222348617-1132924867.jpg) The picture above shows Serilog Log information recorded to the console , You can see , The final log information and LogDemo almost , It's all log time + Grade + Message . ### 2. Serilog towards Sink What exactly is written in ? Prior to LogDemo in , We've always thought that log messages are essentially strings of words . To log is to combine the relevant information into a string and write it to the corresponding Sink in , This is a common practice of unstructured logging libraries . However , There are two problems with this approach : **2.1 Log messages cannot have data attached to them . There are many advantages to attaching data to log messages , For example , If the class library has the ability to parse data automatically , Then we just need to give the data and the message string template with the insertion position , The corresponding log can be constructed by the class library itself . stay Serilog in , This log message with data is called a log event , It contains the string template to be parsed and the data to be rendered .** Here's an example from the official website . It can be seen that ,`position` Is an anonymous class object , It contains longitude and latitude . When using logging , Pass in three arguments to the function , The first is the string template , The last two are information . Its format follows [Message Template](https://messagetemplates.org/) Define , String templates are written very much like C# Medium $ The opening string , The string uses `{}` To mark the location of the data , Adopt `:` Split variable name and data output format , The difference between the two is almost the same as whether there is $. in addition , In the variable name part of the string template , You can also use @ and $ To decide how to render the data ( That is, how to write data content into a string ).@ The deconstruction method is used , Take out the internal content until the basic type is written ,$ It's a direct data call `ToString` Method rendering . In the following example ,`position` Rendering in the form of deconstruction , And integers `elapseMs` utilize `000` The format string controls its rendering method . ```csharp var position = new { Latitude = 25, Longitude = 134 }; var elapsedMs = 34; var log = new LoggerConfiguration() .WriteTo.Console() .CreateLogger(); log.Information("Processed {@Position} in {Elapsed:000} ms.", position, elapsedMs); // Output : [20:54:34 INF] Processed {"Latitude": 25, "Longitude": 134} in 034 ms. ``` **2.2 Different people have different ways of logging . For example , The time contained in the log 、 People with different levels and messages want to enter in different formats . It can be found that , Before Demo in , Through `LogData` Class `Tostring()` Method conversion is not conducive to the customized needs of different people .** For this need , If you have a good understanding of the former question , It can be found that , Log events 、 Log level and log message can be regarded as data in log events , We can set the output template (output template) Reach . Actually , stay Serilog in , Most of the Sink Both provide a default output template , By providing user-defined output template, the purpose of log information customization can be achieved . ```csharp var log = new LoggerConfiguration() .WriteTo.Console(outputTemplate: "({Timestamp:HH:mm:ss}/{Level}) {Message:lj}{NewLine}{Exception}") .CreateLogger(); log.Information("Hello world."); // Output : (21:22:14/Information) Hello world. ``` Here, by setting `outputTemplate` Enter arguments to control the output format of the log . Changes in the output template will cause changes in the output content of the log , But you can see that the content of the information is the same . **2.3 After completing the first two requirements , By combining the two , We can offer a new feature . That is to add other custom data to the log and render it to the log .** This function is very convenient , For example , We also need to record the current user's name in the log . One simple way is to put the user name in the message string , But this method will need to manually fill in the relevant information and template every time a log is recorded . A better operation is , Put the user name in the log event , Just like log time and level , Automatically record in the right place instead of every call . ```csharp var log = new LoggerConfiguration() .Enrich.WithProperty("User", "Dave") .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{User}] {Message:lj}{NewLine}{Exception}") .CreateLogger(); log.Information("Hello world."); // Output : [21:44:04 INF] [Dave] Hello world. ``` stay Serilog in , This behavior of adding data to a log event is called Enrichment, The corresponding data object is Enricher.Enrichment yes Serilog In terms of data, a powerful extended suite function , Through Serilog Fill in new data when logging , And use it in the log template , It can greatly reduce the repeatability of code when calling , And it reduces the possibility of omission . For example , Some people want each log record to record the current thread information 、 Program information, environment variable data, etc , By adding the corresponding Enricher It is possible to record directly without paying too much attention to these values . even to the extent that , Like these more commonly used Enrichers, The official organization has already given the corresponding extension package : - Serilog.Enrichers.Thread: With the current process information - Serilog.Enrichers.Process: With the thread information of the current process - Serilog.Enrichers.Environment: With current environmental information ### 3. Serilog Should this log be recorded For a log record , Many times , We're not asking for everything to be recorded , It is often necessary to discard some logs . It seems counter intuitive , Information is important , Some data should not be implicitly discarded , however , In practical application, such a requirement is indeed reasonable , Sometimes we just want to record the most important log instead of all the log information . There are two ways to filter logs , One is to log to each Sink It needs to be filtered before , This is usually global filtering . The other is each Sink Objects have their own way of filtering , It's usually regional filtering . Here are two examples to illustrate . #### Global filtering The global filtering application scenario is that the logger will record a large number of logs , Most of them are very low-level logs , Such logs are often useful for development , It should not be exported during execution . In this case , We need to set the minimum log output level to Information that will do . Its usage is as follows : ```csharp var log = new LoggerConfiguration() .WriteTo.Console() .MinimumLevel.Information() .CreateLogger(); log.Debug("Test here."); // There's no output ``` in addition , Global filtering conditions can also be complex , We can even put the previous Enricher Together , For example , In the original user name of Enricher in , We want to record only the user name as Lily The Journal of , No other user names are recorded . Here `ForContext` It's also a new addition Enricher Methods , The difference is , It will Enricher Add to child `Logger` in , That is to say, the newly added information is only `log1` and `log2` Yes ,`log` There is no . ```csharp var log = new LoggerConfiguration() .Filter.ByIncludingOnly(Matching.WithProperty("User", "Lily")) // New filter conditions .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] [{User}] {Message:lj}{NewLine}{Exception}") .CreateLogger(); var log1 = log.ForContext("User", "Lily"); log1.Information("Log successed."); // Output var log2 = log.ForContext("User", "Dave"); log2.Information("Log failed."); // No output ``` #### Regional filtering Similarly ,Serilog It allows us to narrow down the log filtering criteria from the global setting to a certain Sink The filtration of , That is, only designated Sink It has the function of filtering log . ```csharp var log = new LoggerConfiguration() .WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Debug) .WriteTo.File("log.txt") .CreateLogger(); log.Information("Hello world."); // stay Console There is no record of , stay File Was recorded in ``` ### 4. Serilog Configuration of loggers in It can be seen from the above problems that , All loggers go through `LogConfiguration` After the relevant properties of the object are configured, the `CreateLogger` Method . Because it has been mentioned more or less before , I won't go into details here . It is worth mentioning that Serilog Not only does the code provide a way to configure text ( That is, by calling a function to execute the setting ), It also provides a set of configuration string setting method , This method is more dynamic , It does not need to write a fixed code flow, but only needs to provide relevant configuration files , The specific processing flow will be mentioned later . ## Serilog Source code preparation Okay , Finally began to contact Serilog The original code of . This part mainly prepares the source code , In order to follow-up learning . ### Prepare the source code Serilog The address of is https://github.com/Serilog/Serilog . We open Windows terminal, Download it with the following command . ```powershell git clone https://github.com/Serilog/Serilog ``` After downloading, we can see Serilog Folder . Then the command line goes to the folder . ```powershell cd ./Serilog ``` Serilog The default branch of the source code is in dev On , This branch is mainly the development version , It is mainly used to develop new functions and repair bug, The changes are usually large , It's not good for learning . Usually we use the latest version of the release to see , Here we use 2.9.0 edition ,Serilog It's been tagged , We just need to switch over . > By the end of the article ,Serilog It's out 2.10.0 edition , But it wasn't updated at that time , I'm looking at 2.9.0 edition , There is not much difference between the two versions . ```powershell git chekckout v2.9.0 ``` After that , Package restore requires , Compile code ,Serilog A file was written to help us compile the project , stay windows Next execution build.ps1 Archives , stay Linux Next execution build.sh Just file . ```powershell ./build.ps1 ``` > There may be some people who can't execute it , It may need to be modified powershell License to execute the instruction code . build.ps1 Files not only restore packages needed by your project , It will also run the test code again , Is there anything wrong with the test . Consider Serilog It's multi platform (.net framwork as well as .net core), During validation testing , If there is no corresponding implementation framework , They will also report mistakes , But it doesn't matter , Just have one of them , We're not modifying the source code , Read the source code as long as it can be executed on a framework . The main focus of this series is .net core Code flow on . After all the above steps have been completed , You can use it vs Open up research . ### Project architecture Through vs Turn on Serilog.sln After filing , The entire project is shown below . ![Serilog Original code structure ](https://img2020.cnblogs.com/blog/1077681/202009/1077681-20200903232912298-943125532.jpg) It can be found that , Its structure is relatively clear . - assert Folder : It's commonly called an asset folder , There are usually some descriptive files and configuration files stored here . For example README.md、build.ps1 as well as build.sh etc. , There's not much to do with this series , You can ignore . - src Folder :src yes source Short for , What's stored in it is Serilog The original code file of , Is the focus of this study , Basically, most of the work is done here . - test Folder : It stores the test function code file for the source code . This folder contains 3 A project ,Serilog.PerformanceTests It should be Serilog Project for performance testing ,Serilog.Tests It should be a source code functional test project , Last TestDummies It is the data class and function class for related test . Considering that the test code uses a test framework , This part is not the focus of this article , So it's not too much about this . Of course , If you know something about software testing , Testing code can help you quickly understand the specific functions of some functions . Next , Let's see src There is something inside .Serilog The organizer is more careful in maintaining this part of the code , Basically, a folder is responsible for one function , This is the same as before LogDemo The same thing , So most of the folders can see at a glance what functions they are responsible for . + Root directory : The root directory contains four files , This and LogDemo almost , From LogDemo The structure and previous experience can be guessed ,`ILogger` It's the core function interface ,`Log` It's a static class , It is similar to `ILogger` Call method of ,`LogConfiguration` and `LogBuilder` The same thing , Designed to construct `ILogger` Object of , and `LogExtensions` It's the extended suite approach . + Core Catalog : As you can guess from the name, it's probably Serilog The core processing logic of the project . + Events Catalog : stay Serilog in , Log records are not called log messages but log events ,Events The internal storage should be related to the description of log events , Similar to LogDemo Medium Data Folder . + Confiuration Catalog : From the name and `LogConfiguration` It can be seen that , It should be used internally to set the relevant configuration functions . + Debugging Catalog : For debugging function . + Filters Catalog : Used to set the filter . + Properties Catalog : There are many projects in this directory , It's stored in it `AssemblyInfo` Class , This class is mainly used to describe some information about the current assembly , It doesn't do much , You can ignore . # Summary This is the end of today's article , This paper mainly talks about two contents , One is serilog Demand analysis of , What functions does it need . The other is Serilog The source code of the project , Made a very simple guess and Analysis , Provide the basis for the later analysis . Start with the next one , We will officially enter the source of the project

版权声明
本文为[itread01]所创,转载请带上原文链接,感谢