Introduction
Logging is a very critical and essential part of any software. It helps us in the investigation of the essence of problems. ASP.NET Core has built-in support for logging API's, which is able to work with various logging providers. Using these built-in providers, we can send application logs to one or more destinations and also, we can plug in third party logging frameworks such as Serilog, Nlog, etc.
Serilog is a good logging framework and it is built with the structured log data in mind. It is a kind of serializer. Serilog determines the right representation when the properties are specified in log events.
Feature of Serilog
- Simple and extendable API
- Support structured data
- Log to variety of targets such as file, database, event log, etc.
To use Serilog logging feature with ASP.NET core, we need to add the dependency of "Serilog.Extensions.Logging". As we are aware that Serilog has a variety of providers like file provider, SQL provider etc., using file provider, we can write the log data in to the file in text format. Serilog does not support .NET Framework Core for SQL Server provider, so if we want to do SQL logging with Serilog, we need to use .NET Framework 4.5.
Log Data into File using Serilog
To write log data in to the file, we can use "Serilog.Extensions.Logging.File" extension dependency. This extension has a method known as "AddFile" on the LoggerFactory. It accepts the file path as a parameter.
Project.json
- {
- "version": "1.0.0-*",
- "buildOptions": {
- "preserveCompilationContext": true,
- "debugType": "portable",
- "emitEntryPoint": true
- },
- "dependencies": {},
- "frameworks": {
- "netcoreapp1.0": {
- "dependencies": {
- "Microsoft.NETCore.App": {
- "type": "platform",
- "version": "1.0.1"
- },
- "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
- "Microsoft.AspNetCore.Mvc": "1.0.0",
- "Serilog.Extensions.Logging.File": "1.0.0"
- },
- "imports": "dnxcore50"
- }
- }
- }
Startup.cs
- public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) {
- loggerFactory.AddFile("Logs/Example-{Date}.txt");…….…….
- }
Here, the file name includes {Date} to specify the date portion in the file name. We may use any environment variable as a part of the file name.
By Default, Serilog writes the file in plain text and the log file contains the fields given below.
Field
|
Description
|
Timestamp
|
Event time
|
Request id
|
Uniquely identifies for all the messages raised during a single Web request.
|
Level
|
Event log level (Three character code in square brackets).
|
Message
|
Log message.
|
Event id
|
Identifies the messages generated from the same format string/message template.
|
Exception
|
Exception if any.
|
As we know, ASP.NET Core has a built-in support for DI (Dependency Injection). Therefore, we can get the instance of ILogger object to controller or Middleware. Here, we need to store the instance of ILogger object to the local variable, so that we can use this instance anywhere in Controller, as we need.
HomeController.cs
- public class HomeController: Controller {
- ILogger _logger;
- public HomeController(ILogger < HomeController > logger) {
- _logger = logger;
- }
- }
In the example given below, I have logged the some text, using LogInformation and LogWarning method.
- [Route("home/LogData")]
- public IActionResult LogData() {
- _logger.LogInformation("Log Information to Debug Window!");
- _logger.LogWarning("Log Warning to Debug Window!");
- return View();
- }
Output
Serilog has a capability to serialize a log event property as a structured object. Serilog provides the “@” de-structuring operator and by this operator, it pulls the value from the structured data. For example, I have a user class object and I want to store the property values into the log file. In this case, Serilog will help us. In the example given below, I have passed the user object and Serilog will store the user class properties in form of JSON.
Action method in Controller class
- [Route("home/LogDataFormated")]
- public IActionResult LogDataFormated() {
- User user = new User();
- user.ID = 1;
- user.Name = "Jignesh";
- _logger.LogInformation("Log Information {@User}", user);
- _logger.LogWarning("Log Warning to Debug Window!");
- return View("LogData");
- }
Output in text File
It is also able to handle the collection type object.
Example
- var intValue = new[] { 1, 2, 3, 4 };
-
- _logger.LogWarning("Log Warning: {IntValue}", intValue);
Output
Serilog is able to recognize the list given below of basic scalar types.
- Booleans
- Numeric byte, short, ushort, int, uint, long, ulong, float, double, decimal
- Strings string, byte[]
- Temporal DateTime, DateTimeOffset, TimeSpan
- Others Guid, Uri
- Nullables nullable versions of any of the above define type
Serilog also supports Stringification. The Stringification is the process of taking the value of ToString() method for the supplied .NET property. Some .NET types do not support serialization or support it very poorly and it is also handled by Serilog, using Stringification.
For example, when we pass SqlConnection object for the formatted string, Serilog doesn't recognize the type, then Serilog renders an object, using ToString() method.
Example
- SqlConnection connection = new SqlConnection();
- _logger.LogWarning("Log Warning: Connection object - {connection}", connection);
Output
Summary
Using the method described above, we can create log file, using Serilog with ASP.NET Core. It is very simple to use and maintain. We can create different log files or break up our log file logically, as per our need. As described above, I have breakup log file, which is based on the current date.