01. Receiver provided
Serilog uses receivers to write log events to storage in a variety of formats. Many receivers are developed and supported by the wider Serilog community; they can be found by searching for the serilog tag on NuGet.
02. Enhancer
Log events can be augmented with properties in a number of ways. A number of pre-built enhancers are available through NuGet:
Install-Package
Enhanced configuration is done through the Enrich configuration object:
var log = new LoggerConfiguration()
.()
.()
.CreateLogger();
All events written via the log will carry an attribute named ThreadId, indicating the ID of the managed thread that wrote them. (By convention, any .WithXyz() method on Enrich creates an attribute named Xyz.)
1. Log context
This can be used to dynamically add and remove attributes from the environment's "execution context"; for example, all messages written during a transaction may carry the transaction's ID, and so on.
This feature must be added to the logger at configuration time via .FromLogContext():
var log = new LoggerConfiguration()
.()
Properties can then be added and removed to the context using ():
("No contextual properties");
using (("A", 1))
{
("Carries property A = 1");
using (("A", 2))
using (("B", 1))
{
("Carries A = 2 and B = 1");
}
("Carries property A = 1, again");
}
Pushing a property into the context overwrites any existing properties with the same name until the object returned from PushProperty() is released, as shown in the example for property A.
Important: Properties must be populated from the context in the exact order they were added. Otherwise, the behavior is undefined.
2. Available enhancer packages
Courtesy of the Serilog project:
- - WithMachineName() and
WithEnvironmentUserName() - - WithProcessId()
- - WithThreadId()
Other interesting enhancers:
- - WithHttpRequestId() and many other useful enhancers in classic applications
- - WithExceptionDetails() adds additional structured properties from the exception
- - WithDemystifiedStackTraces()
- - WithClientIp(), WithCorrelationId() and WithRequestHeader("header-name") will add properties with client IP, correlation ID and HTTP request header values
- - WithXllPath() and many other useful enhancers in the Excel-DNA plug-in
- - WithSensitiveDataMasking() Masking sensitive data in log events
- - FromGlobalLogContext() dynamically adds properties from the Global Context.
03. Formatting output
Serilog provides several output formatting mechanisms.
1. Formatting plain text
Receivers that write plain text output, such as console and file-based receivers, typically accept output templates to control the format of log event data.
The format of the events written by these receivers can be modified using the outputTemplate configuration parameter. For example, to console receivers:
= new LoggerConfiguration()
.(outputTemplate:
"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
.CreateLogger();
Multiple built-in attributes can appear in the output template:
- Exception - The complete exception message and stack trace in multi-line format. Empty if the event has no exception associated with it.
- Level - The log event level, formatted as a full level name. For a more compact level name, use the format {Level:u3} or {Level:w3} for a three-character upper or lower case level name, respectively.
- Message - The message of the log event, rendered as plain text. The :l format specifier turns off string references, and :j renders any embedded structured data using JSON style.
- NewLine - the value of the property is .
- Properties - All event property values that do not appear in the output. JSON rendering is possible using the :j format.
- Timestamp - The timestamp of the event, of type DateTimeOffset.
- TraceId - The trace ID that was active at the time the event was created (if any).
- SpanId - The span ID of the activity when the event was created (if any).
Event attributes attached via enhancers can also appear in output templates.
2、Formatting JSON
Many receivers log log events as JSON, or can be configured to do so. To output JSON instead of plain text, you can specify a formatter. The following example uses the formatting program profile receiver from.
= new LoggerConfiguration()
.(new CompactJsonFormatter(), "")
.CreateLogger();
The Serilog project provides three JSON formatters:
- - This is the historical default formatter in the Serilog package. It generates a complete rendering of log events and supports a number of configuration options.
- - This is a newer, more space-efficient JSON formatter, and is provided with it.
- - Also supplied, this formatter pre-renders the message template as text.
3, flexible formatting and ExpressionTemplate
The ExpressionTemplate class is included for more complex text and JSON formatting. Expression templates can contain conditional blocks, repeating sections, calculations on event properties, and custom formatting functions.
ExpressionTemplate implements the ITextFormatter interface, so it can be used with any text-based Serilog receiver, including consoles (with ANSI color themes), files, debugging, and email.
4. Righteous formatting procedures
Both plain text and JSON formatting are implemented through the ITextFormatter interface. Implementations of this interface can format log events into any text-based format.
Custom JSON formatters can be built around the JsonValueFormatter class included in Serilog.
format provider
There are various options for formatting individual types of output, such as dates. An example is the formatting provider program accepted by most receivers.
The following is a simple console example using the Receiver. This uses the default date rendering behavior.
class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Created { get; set; }
}
public class Program
{
public static void Main(string[] args)
{
= new LoggerConfiguration()
.()
.CreateLogger();
var exampleUser = new User { Id = 1, Name = "Adam", Created = };
("Created {@User} on {Created}", exampleUser, );
();
}
}
This writes the following to the console.
[18:46:45 INF] Created {"Id": 1, "Name": "Adam", "Created": "2018-05-17T18:46:45.9064879+10:00", "$type": "User"} on 05/17/2018 18:46:45
In some cases, it may be desirable to override or specify the format of DateTime. This can be accomplished by implementing an IFormatProvider. This strategy applies to any type you pass to Serilog.
class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Created { get; set; }
}
class CustomDateFormatter : IFormatProvider
{
readonly IFormatProvider basedOn;
readonly string shortDatePattern;
public CustomDateFormatter(string shortDatePattern, IFormatProvider basedOn)
{
= shortDatePattern;
= basedOn;
}
public object GetFormat(Type formatType)
{
if (formatType == typeof(DateTimeFormatInfo))
{
var basedOnFormatInfo = (DateTimeFormatInfo)(formatType);
var dateFormatInfo = (DateTimeFormatInfo)();
= ;
return dateFormatInfo;
}
return (formatType);
}
}
public class Program
{
public static void Main(string[] args)
{
var formatter = new CustomDateFormatter("dd-MMM-yyyy", new CultureInfo("en-AU"));
= new LoggerConfiguration()
.(formatProvider: new CultureInfo("en-AU")) // Console 1
.(formatProvider: formatter) // Console 2
.CreateLogger();
var exampleUser = new User { Id = 1, Name = "Adam", Created = };
("Created {@User} on {Created}", exampleUser, );
();
}
}
The following is the output of the above example with two console receivers configured.
[13:57:12 INF] Created {"Id": 1, "Name": "Adam", "Created": "2020-09-01T13:56:59.7803740-05:00", "$type": "User"} on 1/09/2020 1:57:12 PM
[13:57:12 INF] Created {"Id": 1, "Name": "Adam", "Created": "2020-09-01T13:56:59.7803740-05:00", "$type": "User"} on 01-Sep-2020 1:57:12 PM
classifier for sums of money: All relevant source code has been uploaded to the codebase for those who are interested./hugogoos/Planner