Ask or search…
K
Links

Hello Logs

Logging Introduction

When building an application it is very important to have information communicated clearly about what is going on inside your application. Whether this is a success message or a critical failure that needs someones attention.
We use Serilog behind the scenes. So any configuration you can perform with Serilog, also applies here.

Log Sinks

Serilog can output it's data to all kinds of sources. The console, Azure, Amazon, Elastic, Log4Net, Loggly, NLog, SQL Server, file... just to name a few. These sources are called Log Sinks.
Any time a sink is added to the configuration, all logging within Perigee automatically sends it's log data to the configured sources. This simple configuration strategy makes it incredibly easy to send log data wherever you need it.

Configure logs

We recommend doing most of this configuration within the appsettings.json file, so let's take a look at configuring a simple logger.
In the Hello Configuration Section we configured the console sink to have a different logging template. using the following section of code:
{
"Serilog": {
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}]({ThreadName}) {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
The first tag, MinimumLevel - This describes what events get emitted to the sinks. At Debug, anything logged at the Verbose level is ignored. It's great for controlling what types of messages are visible.
The seconds tag, WriteTo is the array of configured logging sinks. You can control these sinks with the various settings they accept and can be found on the Serilog Sink Configuration page for the given sink.
If you configure another sink like the Microsft SQL Server sink, don't forget to also add the relevent nuget package to your project or it will be ignored!
1) Add the appropriate object to the AppSettings.Serilog.WriteToarray:
{ "Name": "MSSqlServer", ...}
2) Install the package with Nuget:
Install-Package Serilog.Sinks.MSSqlServer
3) You're now ready to log away as usual!

Configuration - With Hosting

The hosting configuration also includes a few additional keys, let's take a look here:
{
"Serilog": {
"MinimumLevel": {
"Default": "Information",
"Override": {
"Microsoft": "Warning",
"System": "Warning",
"Microsoft.AspNetCore": "Warning"
}
},
"WriteTo": [
{ "Name": "Console" }
]
}
}
This time, the MinimumLevel is an object, not a string. This allows us to set the default logging level, as well as override the logging levels for several other namespaces.
The overrides supplied here will squash the incredible amount of information being logged from ASPNetCore hosting by default.

Perigee Logging

Logging is built throughout Perigee. Any thread that is managed and created is automatically sent a logger with the appropriate configurations.
PerigeeApplication.ApplicationNoInit("DemoApp", (c) =>
{
c.AddRecurring("Recurring Task" (ct, l) => {
l.LogInformation("See how this Thread is automatically sent a logger?");
});
});
Want to see more information about perigee application design?

Getting a log directly

We can easily get a log directly from the ThreadRegistry any time we want outside of a ManagedThread. This log is tied into the Serilog system and will automatically inherit the configuration defined.
PerigeeApplication.ApplicationNoInit("DemoApp", (c) =>
{
//Get a logger from the ThreadRegistry
c.GetLogger<Program>();
});

Log Scopes

As shown above, you can override the logging template with additional parameters. Here we've added the ThreadName to the logging template. The reason this works out of the box is because Perigee's internal thread management system injects this log scope before sending an ILogger back.
You can add as many custom log scopes as you need. They will appear differently for different log sinks. This is very helpful when adding a BatchID, CorrelationID, SystemID, NetworkID or other identifying information to the log request.
  • If logging to a database with an additional column added to the logging table - any matching log scope will fill that column value
  • If logging to something like Splunk, you'll see those log scopes present in the additional log data
  • If an overriden template in the console logger includes the custom scope, it will be written when present

Scope demo

Make sure to setup your appsettings.json with the modified logging template:
{
"Serilog": {
"MinimumLevel": "Debug",
"WriteTo": [
{
"Name": "Console",
"Args": {
"outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}]({ThreadName}) {Message:lj}{NewLine}{Exception}"
}
}
]
}
}
Then add a simple recurring method and override the ThreadName supplied by Perigee:
PerigeeApplication.ApplicationNoInit("Scopes", (c) =>
{
c.AddRecurring("RecurringLogger", (ct, l) => {
//Begin a new log scope on this logger, overriding the ThreadName
using var scopes = l.BeginScope(new Dictionary<string, object> { { "ThreadName", "CUSTOMIZED" } });
//Anything now logged from here will have it's "ThreadName" set to "CUSTOMIZED"
l.LogInformation("See the overriden thread name?");
});
});
The output will look like this:
[15:09:16 INF](CUSTOMIZED) See the overriden thread name?