web-dev-qa-db-fra.com

Filtrer les journaux Serilog sur différents récepteurs en fonction de la source du contexte?

J'ai une application .NET Core 2.0 dans laquelle j'utilise avec succès Serilog pour la journalisation. Maintenant, je voudrais enregistrer certaines statistiques de performances de la base de données dans un récepteur séparé (elles ne sont pas destinées au débogage, ce qui est fondamentalement le but de toutes les autres connexions dans l'application, donc je voudrais les garder séparées) et j'ai pensé que cela pourrait être accompli en créant l'enregistreur de statistiques DB avec Log.ForContext<MyClass>().

Je ne sais pas comment je suis censé configurer Serilog en utilisant mes appsettings.json pour enregistrer mes "journaux de débogage" dans un récepteur et mon journal de statistiques DB dans un autre? J'espère qu'il est possible de faire quelque chose comme:

"Serilog": {
  "WriteTo": [
    {
      "Name": "RollingFile",
      "pathFormat": "logs/Log-{Date}.log",
      "Filter": {
        "ByExcluding": "FromSource(MyClass)"
      }
    },
    {
      "Name": "RollingFile",
      "pathFormat": "logs/DBStat-{Date}.log",
      "Filter": {
          "ByIncludingOnly": "FromSource(MyClass)"
      }
    }
  ]
}

Le "Filter" des parties de la configuration sont de la pure conjecture de ma part. Est-ce possible en utilisant mon fichier de configuration ou dois-je le faire dans le code dans mon Startup.cs fichier?

EDIT: Je l'ai fait fonctionner en utilisant l'API C # mais j'aimerais toujours le comprendre en utilisant la configuration JSON:

Log.Logger = new LoggerConfiguration()
            .WriteTo.Logger(lc => lc
                .Filter.ByExcluding(Matching.FromSource<MyClass>())
                .WriteTo.LiterateConsole())
            .WriteTo.Logger(lc => lc
                .Filter.ByExcluding(Matching.FromSource<MyClass>())
                .WriteTo.RollingFile("logs/DebugLog-{Date}.log"))
            .WriteTo.Logger(lc => lc
                .Filter.ByIncludingOnly(Matching.FromSource<MyClass>())
                .WriteTo.RollingFile("logs/DBStats-{Date}.log", outputTemplate: "{Message}{NewLine}"))
            .CreateLogger();
18
David Nordvall

J'ai terminé ce travail aujourd'hui, et j'ai pensé que j'apporterais une réponse appropriée, car il m'a fallu pas mal de messages, de problèmes et d'autres pages pour résoudre ce problème.

Il est utile d'avoir tous les journaux, mais je voulais également consigner uniquement mon code API séparément et omettre le Microsoft. journaux d'espace de noms. La configuration JSON pour ce faire ressemble à ceci:

  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": "Debug",
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "/var/logs/system.log",
          ... //other unrelated file config
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {
            "WriteTo": [
              {
                "Name": "File",
                "Args": {
                  "path": "/var/logs/api.log",
                  ... //other unrelated file config
                }
              }
            ],
            "Filter": [
              {
                "Name": "ByExcluding",
                "Args": {
                  "expression": "StartsWith(SourceContext, 'Microsoft.')"
                }
              }
            ]
          }
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
    ... //Destructure and other config
  }

Le niveau supérieur WriteTo est le premier récepteur simple et global. Tous les événements du journal y écrivent. Si vous ajoutez une section Filter au même niveau que cela, cela affectera tous les éléments WriteTo configurés.

Ensuite, je configure un autre WriteTo en tant que Logger (pas File), mais le Args pour cela semble différent et a un élément configureLogger qui sert le même but que Serilog au niveau supérieur, c'est-à-dire qu'il s'agit du niveau supérieur du sous-enregistreur. Cela signifie que vous pouvez facilement diviser la configuration pour cela en un fichier séparé et l'ajouter en plus dans le générateur de configuration (voir en bas).

À partir d'ici, ce sous-enregistreur fonctionne de la même manière: vous pouvez configurer plusieurs WriteTos et l'élément Filter à ce niveau n'affectera que ce sous-enregistreur.

Ajoutez simplement plus "Name": "Logger" éléments au niveau supérieur WriteTo section et filtres de configuration pour chacun séparément.

Note Il est également important de noter que, même si vous faites tout cela dans la configuration et ne faites pas référence à un seul bit du Serilog.Filters.Expressions package dans votre code, vous devez toujours ajouter la référence NuGet à ce package. Cela ne fonctionne pas sans la référence du package .

A propos du fractionnement de la config:

Si je dois ajouter d'autres enregistreurs, je diviserais certainement les différents enregistreurs en fichiers séparés pour plus de clarté, par exemple.

appsettings.json:

  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": "Error",
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "/var/logs/system.log",
          ...
        }
      },
      {
        "Name": "Logger",
        "Args": {
          "configureLogger": {} // leave this empty
        }
      }
    ],
    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
    ...

apilogger.json:

{
  "Serilog:WriteTo:1:Args:configureLogger": {   //notice this key
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "/var/logs/api_separateFile.log",
          ...
        }
      }
    ],
    "Filter": [
      {
        "Name": "ByExcluding",
        "Args": {
          "expression": "StartsWith(SourceContext, 'Microsoft.')"
        }
      }
    ]
  }
}

Et puis ajustez mon générateur IWebHost pour inclure la configuration supplémentaire:

    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((hostingContext, config) =>
        {
            config.AddJsonFile("apilogger.json", optional: false, reloadOnChange: false);
        })
        .UseStartup<Startup>();

De cette façon, il est plus facile à comprendre, à lire et à entretenir.

12
helloserve