2 votes

Dans Serilog, chemin du fichier journal changeant dynamiquement ?

Je dispose de la fonctionnalité de changement dynamique du chemin du fichier journal. Mais quand je change le chemin qui est configurable dans Consul, il écrit partiellement le journal à la fois à l'ancien emplacement et au nouveau emplacement. Le changement du chemin du fichier journal devrait fonctionner sans redémarrage du service. Comment pouvons-nous y parvenir?

Nous écrivons dans le fichier journal comme suit:

.WriteTo.File(logFolderFullPath + "\\" + applicationName + "_.txt",
                         LogEventLevel.Error, shared: true,
                         fileSizeLimitBytes: fileSizeLimitBytes, rollOnFileSizeLimit: true, rollingInterval: RollingInterval.Day,
                          outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level}] [{MachineName}] [{SourceContext}] {RequestId} {CorrelationId} {Message}{NewLine}{Exception}{properties}")

logFolderFullPath est le chemin configurable depuis appsetting.json. Lorsque nous changeons le chemin, cela crée des fichiers journaux au nouvel emplacement, mais continue également d'écrire dans les fichiers de l'ancien emplacement en même temps.

Nous voulons donc qu'il cesse d'écrire à l'ancien emplacement.

2voto

Caio Proiete Points 524

Vous pouvez essayer d'utiliser Serilog.Settings.Reloader qui peut remplacer l'instance de votre journaliseur en cours d'exécution lorsque votre configuration change.


Une autre façon courante de modifier les propriétés d'un journaliseur en cours d'exécution est d'utiliser Serilog.Sinks.Map, un réceptacle qui répartit les événements en fonction des propriétés des événements de journalisation.

L'exemple ci-dessous utilise une propriété d'événement de journalisation appelée FileName pour décider du nom du fichier journal dans lequel il écrira, donc à chaque fois que cette propriété change, le fichier journal change en conséquence:

Log.Logger = new LoggerConfiguration()
    .WriteTo.Map("FileName", "IDontKnow", (fileName, wt) => wt.File($"{fileName}.txt"))
    .CreateLogger();

Log.ForContext("FileName", "Alice").Information("Bonjour!"); // écrit dans Alice.txt
Log.ForContext("FileName", "Bob").Information("Bonjour!"); // écrit dans Bob.txt
Log.Information("Bonjour encore!"); // écrit dans IDontKnow.txt (par défaut si la propriété est manquante)

Log.CloseAndFlush();

Dans votre cas, vous souhaitez changer dynamiquement le nom de cette propriété en fonction des changements de votre configuration. Une manière simple de procéder consiste à créer un enrichisseur personnalisé qui peut modifier les valeurs d'une propriété comme celle ci-dessus en fonction de vos paramètres de configuration.

Votre enrichisseur personnalisé ressemblerait à ceci :

internal class LogFilePathEnricher : ILogEventEnricher
{
    private string _cachedLogFilePath;
    private LogEventProperty _cachedLogFilePathProperty;

    public const string LogFilePathPropertyName = "LogFilePath";

    public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
    {
        var logFilePath = // Lire le chemin depuis votre appsettings.json
        // Vérifier la nullité, etc...

        LogEventProperty logFilePathProperty;

        if (logFilePath.Equals(_cachedLogFilePath))
        {
            // Le chemin n'a pas changé, donc utilisons la propriété mise en cache
            logFilePathProperty = _cachedLogFilePathProperty;
        }
        else
        {
            // Nous avons un nouveau chemin pour le journal. Créons une nouvelle propriété
            // et mettons en cache pour que les futurs événements de journalisation l'utilisent
            _cachedLogFilePath = logFilePath;

            _cachedLogFilePathProperty = logFilePathProperty =
                propertyFactory.CreateProperty(LogFilePathPropertyName, logFilePath);
        }

        logEvent.AddPropertyIfAbsent(logFilePathProperty);
    }
}

NB : L'enrichisseur exemple ci-dessus pourrait être plus efficace si vous utilisez le modèle d'options, au lieu de vérifier la configuration à chaque fois qu'un message de journal est écrit.

Avec un enrichisseur qui peut définir dynamiquement la propriété LogFilePath pour vous en fonction de la configuration, vous n'avez qu'à configurer le pipeline de journalisation pour mapper en fonction de cette propriété.

Log.Logger = new LoggerConfiguration()
    .Enrich.FromLogContext()
    .Enrich.With()
    .WriteTo.Map(LogFileNameEnricher.LogFilePathPropertyName,
        (logFilePath, wt) => wt.File($"{logFilePath}"), sinkMapCountLimit: 1)
    .CreateLogger();

// ...

Log.CloseAndFlush();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X