You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 Worker应用Serilog日志无法写入Elasticsearch求助

问题排查:.NET 6 Worker服务Serilog日志无法写入Elasticsearch及控制台测试日志不输出

问题描述

基于.NET 6开发Worker服务,采用Serilog实现日志写入Elasticsearch,遇到以下问题:

  • Elasticsearch未创建对应索引,控制台仅提示Unable to submit event,无有效错误信息用于排查
  • Program.cs中的测试日志Log.Information("test log")未输出到控制台,Worker中的日志也无法提交到Elasticsearch

相关代码与配置

Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
        
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        
        Host.CreateDefaultBuilder(args)
            
            .UseSerilog((context, configuration) =>
                {
                    configuration.Enrich.FromLogContext()
                        .Enrich.WithExceptionDetails()
                        .Enrich.WithMachineName()
                        .WriteTo.Console()
                        .WriteTo.Elasticsearch(
                            new ElasticsearchSinkOptions(new Uri("http://localhost:9200/"))
                            {
                                IndexFormat =
                                    $"Elastic-logs-ApprovalCycle-{context.HostingEnvironment.EnvironmentName?.ToLower().Replace(".", "-")}-{DateTime.UtcNow:yyyy-MM-dd}",
                                TypeName = null,
                                AutoRegisterTemplate = true,
                                BatchAction = ElasticOpType.Create,
                                CustomFormatter = new ElasticsearchJsonFormatter(),
                                OverwriteTemplate = true,
                                DetectElasticsearchVersion = true,
                                AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
                                NumberOfReplicas = 1,
                                NumberOfShards = 2,
                                FailureCallback = e => Console.WriteLine("Unable to submit event " + e.MessageTemplate),
                                EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog |
                                                   EmitEventFailureHandling.WriteToFailureSink |
                                                   EmitEventFailureHandling.RaiseCallback |
                                                   EmitEventFailureHandling.ThrowException
                            })
                        .Enrich.WithProperty("Environment", context.HostingEnvironment.EnvironmentName)
                        .ReadFrom.Configuration(context.Configuration);
                        
                }
                
            )
            
            .ConfigureServices((hostContext, services) =>
            {
                Log.Information("test log");
                Serilog.Debugging.SelfLog.Enable(msg => Debug.WriteLine(msg));
                services.AddSerilog();
                services.AddSingleton(rabbit);
                services.AddHostedService<Worker>();
                services.AddHostedService<Worker2>();
            });
}

Worker.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using Approval.Workflow;
using Microsoft.Extensions.Hosting;
using SSRM;
using ILogger = Serilog.ILogger;

namespace Approval
{
    public class Worker : BackgroundService
    {
        private readonly ILogger _logger;
        private readonly RmqOptions _options;
        private readonly RmqListener<> _listener;
        public Worker(ILogger logger,RmqOptions options)
        {
            _logger = logger;
            _options = options;
            _listener=new RmqListener<>(options);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            try
            {
                _logger.Information("Start listen ... ");
                while (!stoppingToken.IsCancellationRequested)
                {
                    await _listener.Listen("Queue");

                }
            }
            catch (Exception e)
            {
                _logger.Information("Listen to Queue: 'Queue' Exception" + e);
            }
        }
        
        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            await ApprovalDriver.StopAsync(cancellationToken);
        }
    }
}

依赖包

<PackageReference Include="Elasticsearch.Net" Version="7.17.5" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="RabbitMQ.Client" Version="6.5.0" />
<PackageReference Include="restsharp" Version="110.2.0" />
<PackageReference Include="Serilog" Version="3.0.1" />
<PackageReference Include="serilog.aspnetcore" Version="7.0.0" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="2.2.0" />
<PackageReference Include="Serilog.Exceptions" Version="8.4.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="7.0.0" />
<PackageReference Include="Serilog.Formatting.Elasticsearch" Version="9.0.3" />
<PackageReference Include="Serilog.Sinks.Console" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Debug" Version="2.0.0" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="9.0.3" />
<PackageReference Include="Synergy.Contracts" Version="2.0.132" />
<PackageReference Include="WorkflowCore.Persistence.MySQL" Version="3.0.1" />

appsettings.json

"Serilog": {
  "MinimumLevel": {
    "Default": "Information",
    "Override": {
      "Microsoft": "Information",
      "System": "Warning"
    }
  }
}

控制台输出

"C:\Program Files\JetBrains\JetBrains Rider 2021.2.1\plugins\dpa\DotFiles\JetBrains.DPA.Runner.exe" --handle=5600 --backend-pid=28808 --detach-event-name=dpa.detach.5600 C:/Users/u12749/Desktop/update/Approval/Approval/bin/Debug/net6.0/Approval.exe
[10:22:50 INF] Start listen ... 
Unable to submit event Start listen ...
Unable to submit event Start listen ...

原因分析

控制台测试日志不输出

  • Log.Information("test log")在ConfigureServices中调用时,Serilog全局Logger尚未完成初始化,静态Log类还未被正确配置。
  • Serilog.Debugging.SelfLog.Enable启用时机过晚,无法捕获Serilog初始化阶段的错误信息。

Elasticsearch无法写入

  1. 索引格式错误:IndexFormat中使用DateTime.UtcNow会导致索引名称固定为应用启动时的日期,而非日志产生时的日期,同时会干扰Serilog模板注册逻辑。
  2. 依赖版本不兼容:Serilog.Sinks.Elasticsearch 9.x版本适配Elasticsearch 8.x,而当前使用的Elasticsearch.Net是7.17.5(对应Elasticsearch 7.x),版本不匹配导致连接或序列化错误。
  3. 错误信息缺失:FailureCallback仅输出日志模板,未包含异常详细信息,无法定位具体失败原因。
  4. SelfLog启用太晚:无法捕获Serilog连接Elasticsearch阶段的初始化错误。

解决方案

修复控制台测试日志不输出

  1. 调整测试日志位置:将测试日志移到Host构建完成后,确保Serilog已初始化:
    public static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        Log.Information("test log");
        host.Run();
    }
    
    或通过依赖注入获取ILogger记录日志:
    .ConfigureServices((hostContext, services) =>
    {
        var logger = services.BuildServiceProvider().GetRequiredService<ILogger<Program>>();
        logger.LogInformation("test log");
        // 其他服务注册代码
    })
    
  2. 提前启用SelfLog:在Program类静态构造函数中启用,捕获全阶段错误:
    public class Program
    {
        static Program()
        {
            Serilog.Debugging.SelfLog.Enable(msg => Console.WriteLine($"Serilog SelfLog: {msg}"));
        }
        // 其他代码
    }
    

修复Elasticsearch无法写入

  1. 修正索引格式:使用Serilog占位符{0:yyyy-MM-dd}实现按天分片,注意用双大括号转义:
    IndexFormat = $"Elastic-logs-ApprovalCycle-{context.HostingEnvironment.EnvironmentName?.ToLower().Replace(".", "-")}-{{0:yyyy-MM-dd}}"
    
  2. 对齐依赖版本:
    • 若使用Elasticsearch 7.x,将Serilog.Sinks.Elasticsearch降级到8.4.0,保持与Elasticsearch.Net 7.17.5兼容:
      <PackageReference Include="Serilog.Sinks.Elasticsearch" Version="8.4.0" />
      
    • 或升级Elasticsearch服务器到8.x,保留当前Serilog.Sinks.Elasticsearch 9.x版本。
  3. 增强错误日志:修改FailureCallback输出完整异常信息:
    FailureCallback = e => 
    {
        Console.WriteLine($"Unable to submit event: {e.MessageTemplate}");
        if (e.Exception != null)
        {
            Console.WriteLine($"Exception details: {e.Exception.ToString()}");
        }
    }
    
  4. 简化配置调试:暂时移除非必要配置项,先确保基础连接正常:
    .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200/"))
    {
        IndexFormat = $"Elastic-logs-ApprovalCycle-{context.HostingEnvironment.EnvironmentName?.ToLower().Replace(".", "-")}-{{0:yyyy-MM-dd}}",
        TypeName = null,
        AutoRegisterTemplate = true,
        AutoRegisterTemplateVersion = AutoRegisterTemplateVersion.ESv7,
        FailureCallback = e => 
        {
            Console.WriteLine($"Unable to submit event: {e.MessageTemplate}");
            if (e.Exception != null) Console.WriteLine(e.Exception);
        },
        EmitEventFailure = EmitEventFailureHandling.WriteToSelfLog | EmitEventFailureHandling.RaiseCallback
    })
    
  5. 验证Elasticsearch连接:添加连接测试代码,确认网络可达:
    // 在Main方法中添加
    var client = new Elasticsearch.Net.ElasticLowLevelClient(new Uri("http://localhost:9200/"));
    var response = client.Ping<StringResponse>();
    Console.WriteLine($"Elasticsearch Ping Result: {response.Success} - {response.Body}");
    

内容的提问来源于stack exchange,提问作者marah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 22:19:50