Serilog

De Banane Atomic
Aller à la navigationAller à la recherche

Utilisation

Cs.svg
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

Cs.svg
const string customTemplate = "{Timestamp:yyyy-MMM-dd HH:mm:ss} [{Level}] {Message}{NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
    .WriteTo.Console(outputTemplate: customTemplate)
    .CreateLogger();

Nuget packages: Serilog.Sinks.Console

Rolling file

Le fichier sera nommé file-YYYYMMDD.log.

Cs.svg
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

Cs.svg
// configure log4net
XmlConfigurator.Configure();

Log.Logger = new LoggerConfiguration()
    .WriteTo.Log4Net(supplyContextMessage: true)
    .CreateLogger();
Il n'est pas possible d'utiliser les Repositories.

Application Insights

Nuget package: Serilog.Sinks.ApplicationInsights

Cs.svg
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é.

Cs.svg
Log.Logger.Information("Text {NamedProperty1} {NamedProperty2}", value1, value2);

Destructured object

Cs.svg
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

Cs.svg
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.

Cs.svg
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

Cs.svg
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

Cs.svg
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

App.config

Nuget package: Serilog.Settings.AppSettings

Cs.svg
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>

appsettings.json

Nuget package: Microsoft.Extensions.Configuration.Json Serilog.Settings.Configuration

Cs.svg
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

Cs.svg
// afficher les infos de debug
SelfLog.Enable(Console.WriteLine);