Utilisation
|
public sealed class MyClass
{
private readonly ILogger logger = Log.Logger.ForContext<MyClass>();
public void MyMethod()
{
logger.Verbose("message");
|
Sinks
Définit où les log doivent être écris.
Console
|
// configuration
const string customTemplate = "{Timestamp:yyyy-MMM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}";
ILogger logger = new LoggerConfiguration()
.WriteTo.Console(outputTemplate: customTemplate)
.CreateLogger();
// make the log available statically
Log.Logger = logger;
|
Nuget packages: Serilog, Serilog.Sinks.Console
Rolling file
Le fichier sera nommé file-YYYYMMDD.log.
|
ILogger logger = new LoggerConfiguration()
.WriteTo.RollingFile("file.log", retainedFileCountLimit: 3)
.CreateLogger();
// retainedFileCountLimit, max number of log files to keep
|
Nuget packages: Serilog.Sinks.RollingFile
Log4net
|
// configure log4net
XmlConfigurator.Configure();
Log.Logger = new LoggerConfiguration()
.WriteTo.Log4Net(supplyContextMessage: true)
.CreateLogger();
|
Nuget package: Serilog.Sinks.ApplicationInsights
|
Log.Logger = new LoggerConfiguration()
.WriteTo.ApplicationInsights(TelemetryConverter.Traces)
.CreateLogger();
|
Trace vs Event
Ne pas oublier de configurer Application Insights.
Structured data
Par défaut, Serilog gère les types suivant: bool numbers string dates nullables IEnumerable Dictionary (si la clé est type de base)
Pour les autres types, ToString est utilisé.
|
Log.Logger.Information("Text {NamedProperty1} {NamedProperty2}", value1, value2);
|
Destructured object
|
var user = new User
{
Name = "Joe",
Age = 35
};
// pour éviter que ToString ne soit utilisé, ajouter un @ devant le nom
Log.Logger.Information("User: {@User}", user);
// User: {"Name": "Joe", "Age": 35, "$type": "User"}
// configurer la déstructuration
ILogger logger = new LoggerConfiguration()
.Destructure.ByTransforming<User>(u => new { u.Name, u.Age })
.WriteTo.Console()
.CreateLogger();
Log.Logger.Information("User: {@User}", user);
// User: {"Name": "Joe", "Age": 35}
|
Format
|
Log.Logger.Information("{StringProperty}", myString); // "MyString"
Log.Logger.Information("{StringProperty:l}", myString); // MyString
Log.Logger.Information("{NumberProperty:0.00}", Math.PI); // 3,14
|
Level
Par défaut, les levels Verbose et Debug ne sont logués.
|
Log.Logger.Verbose("Text");
Log.Logger.Debug("Text");
Log.Logger.Information("Text");
Log.Logger.Warning("Text");
Log.Logger.Error("Text");
Log.Logger.Fatal("Text");
ILogger logger = new LoggerConfiguration()
.MinimumLevel.Verbose() // définit le level minimum de log pour tous les sink
.WriteTo.Console(LogEventLevel.Information) // restreint le level minimum de log pour le sink Console
.CreateLogger();
|
Filter
|
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.Filter.ByIncludingOnly(Matching.FromSource<Program>()) // inclus seulement les log avec un SourceContext = type Program
.Filter.ByIncludingOnly(Matching.FromSource("MyNamespace")) // inclus seulement les log avec un SourceContext commençant par MyNamespace
.CreateLogger();
// SourceContext
Log.Logger.ForContext<Program>().Information("Text");
|
Event enricher
|
ILogger logger = new LoggerConfiguration()
.Enrich.WithProperty("ApplicationName", "MyApp")
.WriteTo.Console()
.CreateLogger();
Log.Logger.Information("{ApplicationName} - Text"); // MyApp - Text
ILogger logger = new LoggerConfiguration()
.Enrich.With<MyEventEnricher>()
.WriteTo.Console()
.CreateLogger();
Log.Logger.Information("{ApplicationName} - {ApplicationVersion} - Text"); // MyApp - 1.0.0.0 - Text
|
MyEventEnricher.cs
|
class MyEventEnricher : ILogEventEnricher
{
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
var applicationAssembly = Assembly.GetEntryAssembly();
var name = applicationAssembly.GetName().Name;
var version = applicationAssembly.GetName().Version;
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ApplicationName", name));
logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("ApplicationVersion", version));
}
}
|
App settings
NuGet package: Serilog.Extras.AppSettings
Timing
NuGet package: Serilog.Extras.Timing
Configuration file
Nuget package: Serilog.Settings.AppSettings
|
var logger = new LoggerConfiguration()
.ReadFrom.AppSettings()
.CreateLogger();
|
App.config
|
<configuration>
<appSettings>
<add key="serilog:minimum-level" value="Warning" />
<add key="serilog:using:Console" value="Serilog.Sinks.Console" />
<add key="serilog:write-to:Console" />
<add key="serilog:using:ApplicationInsights" value="Serilog.Sinks.ApplicationInsights" />
<add key="serilog:write-to:ApplicationInsights.telemetryConverter"
value="Serilog.Sinks.ApplicationInsights.Sinks.ApplicationInsights.TelemetryConverters.TraceTelemetryConverter, Serilog.Sinks.ApplicationInsights" />
<add key="serilog:using:Log4Net" value="Serilog.Sinks.Log4Net" />
<add key="serilog:write-to:Log4Net.supplyContextMessage" value="true" />
</appSettings>
|
Nuget package: Microsoft.Extensions.Configuration.Json Serilog.Settings.Configuration
|
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
|
appsettings.json
|
{
"Serilog": {
"Using": ["Serilog.Sinks.Console"],
"MinimumLevel": "Debug",
"WriteTo": [
{ "Name": "Console" },
{ "Name": "File", "Args": { "path": "%TEMP%\\Logs\\serilog-configuration-sample.txt" } }
],
"Enrich": ["FromLogContext", "WithMachineName", "WithThreadId"],
"Destructure": [
{ "Name": "With", "Args": { "policy": "Sample.CustomPolicy, Sample" } },
{ "Name": "ToMaximumDepth", "Args": { "maximumDestructuringDepth": 4 } },
{ "Name": "ToMaximumStringLength", "Args": { "maximumStringLength": 100 } },
{ "Name": "ToMaximumCollectionCount", "Args": { "maximumCollectionCount": 10 } }
],
"Properties": {
"Application": "Sample"
}
}
}
|
Debug
|
// afficher les infos de debug
SelfLog.Enable(Console.WriteLine);
|