Serilog 与 Elasticsearch 接收器,索引格式没有滚动日期

Cla*_*doo 4 .net c# elasticsearch serilog

我使用 Serilog 和 Elasticsearch 接收器将我的日志推送到 Elastic,以及 .net 5 应用程序中 APM 中的事务。

创建 Logger 时,它使用当前日期时间作为索引格式 (mslogs-yyyy.MM.dd) 的一部分,但一旦容器运行,无论当前时间如何,这仍然是所使用的相同索引名称。例如,如果容器于 2021 年 6 月 25 日启动,则索引将创建并mslogs-2021.06.25在容器的整个生命周期内保留,因此接下来几天生成的日志仍会推送到该索引中。

当我的操作人员在 Elk 上设置删除旧日志的策略时,根据索引名称(日期时间部分),新日志可能会被删除,因为它们被放入“旧索引”中。

2021 年 6 月 30 日推送到 mslogs-2021.06.28 的日志示例(迄今为止从未重新启动的容器的开始日期)

这是我的记录器生成器

    public static Logger GetELKLogger(IConfiguration config, string varEnv = "ElasticSearchLog")
    {
        var configuration = config.Get<Configuration>(varEnv);

        return new LoggerConfiguration()
        .ReadFrom.Configuration(config)
        .Enrich.WithElasticApmCorrelationInfo()
        .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri(configuration.ElasticSearchLog))
        {
            AutoRegisterTemplate = true,
            IndexFormat = $"mslogs-{DateTime.UtcNow:yyyy.MM.dd}", // called once at startup !!
            DetectElasticsearchVersion = true,
            RegisterTemplateFailure = RegisterTemplateRecovery.IndexAnyway,
            AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
            FailureCallback = e => Console.WriteLine($"Unable to submit event {e.RenderMessage()} to ElasticSearch. Full message : " + e.Serialize()),
            EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog |
                                    EmitEventFailureHandling.WriteToFailureSink |
                                    EmitEventFailureHandling.RaiseCallback,
            BufferCleanPayload = (failingEvent, statuscode, exception) =>
            {
                dynamic e = JObject.Parse(failingEvent);
                return JsonConvert.SerializeObject(new Dictionary<string, object>()
                    {
                        { "action", "DeniedByElasticSearch"},
                        { "@timestamp",e["@timestamp"]},
                        { "level","Error"},
                        { "message","Error: "+e.message},
                        { "messageTemplate",e.messageTemplate},
                        { "failingStatusCode", statuscode},
                        { "failingException", exception}
                    });
            },
            CustomFormatter = new EcsTextFormatter()
        })
        .CreateLogger();
    }
Run Code Online (Sandbox Code Playgroud)

和记录器的创建

    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // Logger
            Log.Logger = SharedLibraries.Logging.LoggerFactory.GetELKLogger(Configuration);
Run Code Online (Sandbox Code Playgroud)

我是否应该强制每天重新创建记录器实例一次以从DateTime.UtcNow更新中受益?或者有更优雅的解决方案吗?

依赖关系

    <TargetFramework>net5.0</TargetFramework>

    <PackageReference Include="Serilog" Version="2.10.0" />
    <PackageReference Include="Serilog.Extensions.Hosting" Version="4.1.2" />
    <PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
    <PackageReference Include="Serilog.Settings.Configuration" Version="3.1.0" />
    <PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
    <PackageReference Include="Serilog.Sinks.ElasticSearch" Version="8.4.1" />
    <PackageReference Include="Serilog.Sinks.Seq" Version="5.0.1" />

    <PackageReference Include="Elastic.Apm.NetCoreAll" Version="1.11.0" />
    <PackageReference Include="Elastic.Apm.SerilogEnricher" Version="1.5.3" />
    <PackageReference Include="Elastic.CommonSchema.Serilog" Version="1.5.3" />
Run Code Online (Sandbox Code Playgroud)

Nic*_*rdt 7

IndexFormat属性是事件时间戳(以 UTC 为单位)上的.NET 格式字符串$,因此您不应使用该值来插值:

IndexFormat = "mslogs-{0:yyyy.MM.dd}"
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢,我完全错过了这样一个事实:应该提供一个模板字符串来让 Serilog 对其进行插值,而不是一个已经插值的字符串,这显然是一种 const。我的错! (2认同)