如何使用 Serilog 和 ElasticSearch 拥有不同的日志类型

How to have different log types using Serilog and ElasticSearch

我目前正在尝试更改我们的系统配置以使用 Serilog而不是使用 FileBeat 作为 LogStash 的托运人

我们还在各种查询中使用日志 type 字段(很容易在 FileBeat 配置文件中配置),并在 Elastic 上索引日志。

问题是,当使用Serilog时,我们得到的是默认类型logevent,我没有找到在哪里可以配置它。 我想要一个选项来确定每个 Serilog 实例的特定日志类型。 目前我的所有日​​志都有默认类型。

我的 Serilop 配置是:

        var path = GetLogPath();
        var logger = new LoggerConfiguration()
            .MinimumLevel.Information()
            .Enrich.WithMachineName()
            .Enrich.WithProperty("RequestId", Guid.NewGuid())
            .WriteTo.RollingFile(
                pathFormat: path,
                outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u4}] [{RequestId}] {Message}{NewLine}{Exception}", buffered: false, shared: true);
        logger.WriteTo.Elasticsearch(
                new ElasticsearchSinkOptions(new Uri(this.configurationService.ElasticSearchUrl())));

如何更改日志类型?

编辑

经过一些调查,我发现我想更改 LoggerConfiguration 中的 typeName 文件,而且我似乎只能通过 AppConfig 文件这样做,这再次发生事件,如果我要更改它,更改将影响 所有 记录器实例。

我错过了什么吗?

更新答案

要向您的记录器添加属性和值,您可以使用 Contextual logging and Enrichment

上下文记录器

The simplest and most direct way to attach contextual properties to a log event

首先初始化你的记录器:

Log.Logger = new LoggerConfiguration().ReadFrom.AppSettings().CreateLogger();

然后您可以创建上下文记录器:

// adding Log Context
var StudentLogger = Log.Logger.ForContext<Student>();

StudentLogger.Error(/* log message */);

或者您可以使用关联日志条目:

// correlation Log Entries
var orderId = "some value";
var corrLog = Log.Logger.ForContext("orderId", orderId)

corrLog.Error(/* log message */);

充实

In some cases we would like every event created by a logger to carry the same, fixed, property value. The Application example is one of these.

Serilog provides Enrich.WithProperty() at the level of a LoggerConfiguration for this:

Log.Logger = new LoggerConfiguration()
    .Enrich.WithProperty("Application", "e-Commerce")
    .Enrich.WithProperty("Environment", ConfigurationManager.AppSettings["Environment"])
    // Other logger configuration

原答案

配置Serilog有两种方式:

使用API(需要serilog.sinks.elasticsearch包):

var loggerConfig = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200") ){
         AutoRegisterTemplate = true,
 });
var logger = loggerConfig.CreateLogger();

Serilog Documentation

使用 AppSettings 中的配置(除了 serilog.sinks.elasticsearch 之外还需要 Serilog.Settings.AppSettings)

这样,您就可以将所有设置放入 AppSetting 文件中,例如

<appSettings>
    <add key="serilog:using" value="Serilog.Sinks.Elasticsearch"/>
    <add key="serilog:write-to:Elasticsearch.nodeUris" value="http://localhost:9200;http://remotehost:9200"/>
    <add key="serilog:write-to:Elasticsearch.indexFormat" value="custom-index-{0:yyyy.MM}"/>
    <add key="serilog:write-to:Elasticsearch.templateName" value="myCustomTemplate"/>
  </appSettings>

并告诉 serilog 从 appSettigns 读取配置

Log.Logger = new LoggerConfiguration()
  .ReadFrom.AppSettings()
  ... // Other configuration here, then
  .CreateLogger()

参见:AppSetting and ElasticSearch Configure Sink

我不确定您指的是哪种日志事件类型?在我的例子中,我在记录错误时传递了对象类型:

catch (Exception ex)
{
    Logger.Error(ex, string.Format("Exception occured in Controller: {0}, Action: Post.", this.GetType()), this.GetType());

只需为 Elasticsearch 接收器使用另一个重载:

var path = GetLogPath();
var logger = new LoggerConfiguration()
    .MinimumLevel.Information()
    .Enrich.WithMachineName()
    .Enrich.WithProperty("RequestId", Guid.NewGuid())
    .WriteTo.RollingFile(
        pathFormat: path,
        outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u4}] [{RequestId}] {Message}{NewLine}{Exception}", buffered: false, shared: true);
logger.WriteTo.Elasticsearch(
        this.configurationService.ElasticSearchUrl(), typeName: "type");

因此您不必在应用程序设置中指定类型名称,它也不会影响所有实例。

另一种选择是创建全局静态加载程序 class。定义多个 ILogger 字段,一个用于错误,另一个用于诊断等等。配置静态构造函数中的字段。然后创建几个 public 方法,WriteError()、WriteDebug()、WriteInfo() 等等。例如,当从 WriteDebug(logDetail) 方法调用 ILogger.Write(LogEventLevel.Debug, logDetail) 时,您将能够决定 LogEventLevel。