WHAT TO LOG
It is not enough to log errors in order to use them for troubleshooting purposes. It is also useful to log successful requests so we can have a clear idea of how users work with the application .
Logs are also useful to detect mistakes that users make, as well as for security purposes. Writing good logs about a user’s activity can alert us about malicious activity or any other kind of problems that we didn’t detect .
Why use Serilog ?
Serilog provides basic diagnostic logging not only to the console, files, Amazon, Azure, but more ,it’s easy to integrate and to use in a few steps .
This article will demonstrate the console and file sinks. It is easy as 1, 2, 3 to set up with appsettings configurations.
Steps :
First thing that we are going to do is to create a new empty solution (Web Api )
Now we need to use the package manager to install some extensions as in pictures below or you can use the command :
Serilog.AspNetCore package
Logger initialization in Program.cs :
To start working with Serielog we need to initilize it first in the program.cs .
You can copy replace your code with the below code :
public static void Main(string[] args) { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .Build(); Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration).WriteTo.Console().CreateLogger(); try { Log.Information("Application startinng up"); CreateHostBuilder(args).Build().Run(); } catch (Exception ex) { Log.Fatal(ex, "The application failed to start correctly"); } finally { Log.CloseAndFlush(); } }
Also , we need to add : .UseSerilog() inside the CreateHostBuilder :
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .UseSerilog() .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
Next , inside the Startup.cs we need to add : app.UseSerilogRequestLogging();
Now if we run our solution , we should see inside the console a message saying : Application startinng up ,
if you remember we added a line of code that will fire when the application start :
Log.Information("Application startinng up");
Cleaning up The default logger :
There are a few more changes that we are going to do and now inside the appsettings.json .
Serilog completely replaces the logging implementation on .NET Core,it will not work together but it will replace the default implementation . The benefit of this is that you’re not running two different logging frameworks with tricky edge cases where they overlap in functionality.
{ "AllowedHosts": "*", "Serilog": { "Using": [], "MinimumLevel": { "Default": "Information", "Override": { "Microsoft": "Warning", "System": "Warning" } }, "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], "WriteTo": [ { "Name": "Console" }, { "Name": "File", "Args": { "path": "Logs/log.txt", "rollingInterval": "Day", "outputTemplate": "{Timestamp:G} {Message}{NewLine:1}{Exception:1}" } }, { "Name": "File", "Args": { "path": "Logs/log.json", "rollingInterval": "Day", "formatter": "Serilog.Formatting.Json.JsonFormatter, Serilog" } } ] } }
The “Name” key here specifies the sink desired. To write to multiple sinks, add another object to the “WriteTo” array , in our case we want to create files inside a logs folder and each day we want to create a new different file that contain the date time .
The MinimumLevel
configuration object provides for one of the log event levels to be specified as the minimum.
If you see ,we have “path“: “Logs/log.txt”, where we define where we want our file to be written to and stored .
rollingInterval here mean that we want to create a new file per day .
as you can see inside write to , we defined to object , one that will write to a text file and another one that’s going to write inside a json file .
Now let’s run our solution :
As you can see there is a new Folder created : Logs , that contain a json file and a txt file .
let explore those 2 files :
{"Timestamp":"2020-09-13T15:04:23.3942682+01:00","Level":"Information","MessageTemplate":"Application startinng up"} {"Timestamp":"2020-09-13T15:04:25.9319025+01:00","Level":"Information","MessageTemplate":"Getting WeatherForecast details","Properties":{"ActionId":"9612d1c8-4c4e-44b7-b7fd-374fe905687c","ActionName":"SerielogDemoDay.Controllers.WeatherForecastController.Get (SerielogDemoDay)","RequestId":"0HM2NTNM09MCA:00000001","RequestPath":"/weatherforecast","SpanId":"|b35b87a8-42a0adeaed09085c.","TraceId":"b35b87a8-42a0adeaed09085c","ParentId":""}} {"Timestamp":"2020-09-13T15:04:25.9642904+01:00","Level":"Information","MessageTemplate":"HTTP {RequestMethod} {RequestPath} responded {StatusCode} in {Elapsed:0.0000} ms","Properties":{"RequestMethod":"GET","RequestPath":"/weatherforecast","StatusCode":200,"Elapsed":134.7792,"SourceContext":"Serilog.AspNetCore.RequestLoggingMiddleware","RequestId":"0HM2NTNM09MCA:00000001","SpanId":"|b35b87a8-42a0adeaed09085c.","TraceId":"b35b87a8-42a0adeaed09085c","ParentId":""},"Renderings":{"Elapsed":[{"Format":"0.0000","Rendering":"134.7792"}]}}
As You can see the json file is very detailed file that contain all the event that happened .
while the txt file below , contain the actions with date time .
09/13/2020 15:04:23 Application startinng up 09/13/2020 15:04:25 Getting WeatherForecast details 09/13/2020 15:04:25 HTTP "GET" "/weatherforecast" responded 200 in 134.7792 ms
and now you can log anywhere inside your application by just using :
Log.Debug("debug test!"); Log.Information("Informations here.....!"); Log.Error("Error here ....!");
Link to demo project .