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

Serilog跨程序日志写入异常求助:独立程序日志串入其他日志文件

问题原因分析及解决方案

这事儿我太熟了——你碰到的是SHVDN运行环境下,多.NET脚本共享进程/应用程序域导致的Serilog全局Logger冲突问题。

核心原因

SHVDN本质是把多个.NET脚本加载到同一个宿主进程(比如GTA游戏进程)的同一个应用程序域里运行的。而Serilog的Log.Logger是一个静态全局变量,所有在同一个AppDomain里的代码都会共用这个实例。

具体到你的场景:

  • 当程序A先启动,它初始化了Log.Logger指向testA-.log的文件接收器;
  • 之后程序B启动,如果它的Logger初始化逻辑没成功覆盖全局的Log.Logger(或者初始化时机滞后、代码执行出了问题),那它写日志时就会复用程序A已经设置好的全局Logger实例,自然就把日志写到testA-.log里了。

哪怕程序B自己写了初始化代码,也可能因为初始化时机晚于程序A,或者某个环节没正确替换全局Logger,导致日志串流。

解决方案

要彻底解决这个问题,你需要避免依赖Serilog的全局静态Log.Logger,转而给每个程序创建独立的Logger实例,各自管理自己的日志输出:

  1. 为每个程序创建专属Logger实例
    不要用全局的Log.Logger,而是在每个程序里单独实例化Logger对象,比如:

    // 程序A的专属Logger
    private static readonly Logger _loggerA = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .Filter.ByExcluding(e => e.MessageTemplate.Text.Contains("Could not find file"))
        .WriteTo.File("testA-.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 1, outputTemplate: template)
        .CreateLogger();
    
    // 程序B的专属Logger
    private static readonly Logger _loggerB = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .WriteTo.File("testB-.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 1, outputTemplate: template)
        .CreateLogger();
    

    之后写日志时,直接用各自的_loggerA.Information(...)或_loggerB.Error(...),而不是Log.Information(...)。

  2. 若坚持用全局Logger,需确保隔离性和初始化顺序
    如果你一定要用Log.Logger,那必须保证每个程序在初始化时完全替换全局实例,并且最好在脚本启动的最早期执行这个初始化。另外,为了避免互相干扰,可以给不同程序的日志加上专属标识,比如在输出模板里加上程序名:

    // 程序A的初始化
    var templateA = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [ProgramA] {Message:lj}{NewLine}{Exception}";
    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .Filter.ByExcluding(e => e.MessageTemplate.Text.Contains("Could not find file"))
        .WriteTo.File("testA-.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 1, outputTemplate: templateA)
        .CreateLogger();
    
    // 程序B的初始化
    var templateB = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] [ProgramB] {Message:lj}{NewLine}{Exception}";
    Log.Logger = new LoggerConfiguration()
        .MinimumLevel.Debug()
        .WriteTo.File("testB-.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 1, outputTemplate: templateB)
        .CreateLogger();
    

    但这种方式依然有风险——如果两个程序的初始化时机重叠,还是可能出现日志串流的情况,所以更推荐第一种方案:使用独立Logger实例。

  3. 额外排查点:SHVDN脚本的加载顺序
    SHVDN的脚本加载顺序是按文件名排序的,如果你不确定哪个程序先启动,可以在脚本的ScriptMain里加个初始化日志,确认加载顺序,这样能帮你快速定位问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:12:38