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实例,各自管理自己的日志输出:
为每个程序创建专属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(...)。若坚持用全局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实例。
额外排查点:SHVDN脚本的加载顺序
SHVDN的脚本加载顺序是按文件名排序的,如果你不确定哪个程序先启动,可以在脚本的ScriptMain里加个初始化日志,确认加载顺序,这样能帮你快速定位问题。
内容的提问来源于stack exchange,提问作者meimeiriver

