Serilog with Elasticsearch sink, indexformat 没有滚动日期

Serilog with Elasticsearch sink, indexformat has no rolling date

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

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

由于我的 Ops 在 Elk 上制定了删除旧日志的政策,基于索引名称(日期时间部分),新日志可能会被删除,因为它们被放入“旧索引”。

这是我的记录器生成器

    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();
    }

和记录器创建

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

我是否应该强制每天重新创建一次记录器实例以受益于 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" />

IndexFormat 属性 是 a .NET format string 超过事件的时间戳(UTC),所以你不应该使用 $ 来插入值:

IndexFormat = "mslogs-{0:yyyy.MM.dd}"