.NET 7 C# Worker应用Serilog对接Elasticsearch日志问题咨询
问题解答
1. 异常消息附加特定数据且保留堆栈跟踪
别只靠日志属性记录错误,必须把异常对象作为参数传给Serilog的Error方法,同时在消息模板里嵌入自定义数据。示例代码:
try { // 业务逻辑代码 } catch (Exception ex) { var customInfo = new { OrderId = 456, Operator = "admin" }; Log.Error(ex, "业务执行失败,附加信息:{CustomInfo}", customInfo); }
这样既会保留完整的异常堆栈跟踪,又能把CustomInfo作为结构化字段输出到Elasticsearch。如果需要全局统一附加固定数据(比如应用版本、运行环境),可以在Serilog初始化时配置Enrich:
Log.Logger = new LoggerConfiguration() .Enrich.WithProperty("AppVersion", "2.1.0") .Enrich.WithProperty("Env", "Staging") .WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://your-es-url:9200"))) .CreateLogger();
2. 首次异常后重启应用
方法一:依赖外部进程监控(推荐)
把Worker注册为Windows服务或Linux的systemd服务,通过服务配置开启失败自动重启:
- Windows服务:在服务属性的「恢复」选项卡,设置第一次失败时执行「重启服务」
- Linux systemd:在服务配置文件(
.service)中添加Restart=on-failure和RestartSec=3,systemd会在进程异常退出后自动重启
方法二:代码内触发重启并退出
在Worker类中注入IHostApplicationLifetime,捕获到首次异常后终止当前主机,再启动新进程(可选):
private readonly IHostApplicationLifetime _appLifetime; private bool _hasThrownException = false; public Worker(IHostApplicationLifetime appLifetime) { _appLifetime = appLifetime; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { try { await Task.Delay(60000, stoppingToken); // 模拟业务异常 throw new InvalidOperationException("执行出错"); } catch (Exception ex) { Log.Error(ex, "任务执行异常"); if (!_hasThrownException) { _hasThrownException = true; // 终止当前应用主机 _appLifetime.StopApplication(); // 启动新进程(需确保路径和权限正确) var currentProc = Process.GetCurrentProcess(); Process.Start(currentProc.MainModule.FileName); break; } } } }
注意:代码内自我重启可能存在进程残留风险,优先用外部服务监控的方式更稳定。
内容的提问来源于stack exchange,提问作者marah
相关产品推荐
相关产品推荐

