With .NET Core, diagnostic information can be written using the ILogger interface. ILogger offers provider-based functionality to write to the console, the debug window, the Windows Event Log, to Microsoft Azure Ap Services diagnostics and logs, as well as to the TraceSource and the EventSource. Adapters to write to 3rd party logging frameworks such as Log4Net and NLog are available as well. What about just logging to files?
Logging with ILogger
ILogger interface can be injected into a service, and easily used with extension methods to write information using different trace levels such trace, information, and error using the methods
LogError as shown in the following code snippet.
ILoggerinterface can also be used without dependency injection, using the
LoggerFactory. The interface
ILoggerFactorycan also be injected using DI.
Making the application ready for using the ILogger interface, the logging is added to the DI container invoking the extension method
AddLogging. Using the overload with the
Action delegate, logging is configured with the providers for the console and the debug window. Configuration information is used as well by applying the section
Logging with the configuration. Other than logging, the HTTP client factory is registered with the DI container as well.
TraceSource to write files
TraceSource class (namespace
System.Diagnostics) to write diagnostic information was introduced with the .NET Framework 1.1. TraceSource gives a separation between tracing, providers where to log trace information, and a switch to turn tracing on or off. One of the available switches offers to differentiate trace levels such as verbose, information, and error traces. A provider needs to derive from the base class
TraceListener. Derived from this class is the
TextWriterTraceListener. Concrete classes deriving from
XmlWriterTraceListener which allow tracing to files.
To extend the .NET Core logging with trace source logging, the NuGet package Microsoft.Extensions.Logging.TraceSource is needed.
ConfigureTraceSourceLogging from the following code snippet creates a text file and passes the stream to the constructor of the
TextWriterTraceListener. This listener can then be used with the configuration to log to the trace source.
The extension method
AddTraceSource adds trace source logging to .NET Core logging – passing a SourceSwitch to write verbose information, and the previously created
Running the application, the following log information is written to the log file. Because the provider is configured to write all verbose trace information, you can also see the information logged from the
ClientHandler which is used with the HTTP client factory:
LoggingConfigurationSample.SampleController Information: 2002 : NetworkRequestSampleAsync started with url https://csharp.christiannagel.com System.Net.Http.HttpClient.SampleController.LogicalHandler Information: 100 : Start processing HTTP request GET https://csharp.christiannagel.com/ System.Net.Http.HttpClient.SampleController.ClientHandler Information: 100 : Sending HTTP request GET https://csharp.christiannagel.com/ System.Net.Http.HttpClient.SampleController.ClientHandler Information: 101 : Received HTTP response after 857.3442ms - OK System.Net.Http.HttpClient.SampleController.LogicalHandler Information: 101 : End processing HTTP request after 902.6099ms - OK LoggingConfigurationSample.SampleController Information: 2002 : NetworkRequestSampleAsync completed, received 71575 characters
SeriLog to write files
A more modern way to write log information is offered from a third-party library Serilog. Serilog integrates with .NET Core logging and allows logging to many different sinks, e.g. to Email, Microsoft Teams, NLog, UDP, Azure Table Storage, and many others. With this library, you can also log to files.
To extend the .NET Core logging with serilog and logging to files, the NuGet packages Serilog.Extensions.Logging and Serilog.Sinks.File are needed.
To configure Serilog, either static members of the
Log class in the namespace
Serilog can be configured, or a new
Logger can be created and supplied to the
AddSerilog extension method.
With the following code snippet, the extension method
AddSerilog is used to define another logging provider. Using the overload of
AddSerilog to pass an
ILogger, a logger is created with a new
LoggerConfiguration that is configured to write to the
File sink using the
WriteTo property. With the configuration in place, the logger is created using the
Running the application, now the log information shows up in the serilog configured log file:
2018-11-11 14:36:45.095 +01:00 [INF] NetworkRequestSampleAsync started with url https://csharp.christiannagel.com 2018-11-11 14:36:45.156 +01:00 [INF] Start processing HTTP request GET "https://csharp.christiannagel.com/" 2018-11-11 14:36:45.165 +01:00 [INF] Sending HTTP request GET "https://csharp.christiannagel.com/" 2018-11-11 14:36:46.026 +01:00 [INF] Received HTTP response after 857.3442ms - "OK" 2018-11-11 14:36:46.029 +01:00 [INF] End processing HTTP request after 902.6099ms - "OK" 2018-11-11 14:36:46.100 +01:00 [INF] NetworkRequestSampleAsync completed, received 71575 characters
The logging facility offered by .NET Core offers great flexibility. With your services you can work with
ILoggerFactory, and can use any logger provider configured. Providers for the console class and debugging are built-in. For logging to files, you can use the old and traditional trace source, or other providers such as Serilog which offers a new and modern API. No matter what you select, it’s just a configuration of the logging provider and doesn’t influence the implementation of your service classes.
If this information helped you programming your .NET Core applications, consider buying me a coffee which helps me staying up longer and writing more articles.
Enjoy learning and programming!
Important links for the article: