Pal*_*raz 1 .net c# logging nlog multiprocessing
在此线程中 -当调用 Flush() 时,NLog 是否应该刷新 AsyncTargetWrapper 中的所有排队消息?- 我读到 \xe2\x80\x9eLogManager在域卸载或进程退出\xe2\x80\x9c 时将配置设置为 null(请参阅第一个答案中的编辑部分)。根据我的理解,这应该会导致所有待处理的日志条目被写入已注册的目标。然而,在FileTarget用wrapped with进行测试后AsyncTargetWrapper,这并不成立。我在 GitHub 上创建了一个最小的重现 - https://github.com/PaloMraz/NLogMultiProcessTargetsSample,其工作原理如下:
LogLib是一个.netstandard2.0引用NLog4.6.8 NuGet 包并公开一个CompositeLogger以编程方式配置NLog目标的类的库:
public class CompositeLogger\n{\n private readonly ILogger _logger;\n\n public CompositeLogger(string logFilePath)\n {\n var fileTarget = new FileTarget("file")\n {\n FileName = logFilePath,\n AutoFlush = true\n };\n var asyncTargetWrapper = new AsyncTargetWrapper("async", fileTarget)\n {\n OverflowAction = AsyncTargetWrapperOverflowAction.Discard\n };\n\n var config = new LoggingConfiguration();\n config.AddTarget(asyncTargetWrapper);\n config.AddRuleForAllLevels(asyncTargetWrapper);\n LogManager.Configuration = config;\n\n this._logger = LogManager.GetLogger("Default");\n }\n\n public void Log(string message) => this._logger.Trace(message);\n}\nRun Code Online (Sandbox Code Playgroud)\n\nLogConsoleRunner是一个 .NET Framework 4.8 控制台应用程序,用于LogLib.CompositeLogger将指定数量的日志消息写入文件(指定为命令行参数),写入之间有短暂的延迟:
public static class Program\n{\n public const int LogWritesCount = 10;\n public static readonly TimeSpan DelayBetweenLogWrites = TimeSpan.FromMilliseconds(25);\n\n static async Task Main(string[] args)\n {\n string logFilePath = args.FirstOrDefault();\n if (string.IsNullOrWhiteSpace(logFilePath))\n {\n throw new InvalidOperationException("Must specify logging file path as an argument.");\n }\n\n logFilePath = Path.GetFullPath(logFilePath);\n Process currentProcess = Process.GetCurrentProcess();\n var logger = new CompositeLogger(logFilePath);\n for(int i = 0; i < LogWritesCount; i++)\n {\n logger.Log($"Message from {currentProcess.ProcessName}#{currentProcess.Id} at {DateTimeOffset.Now:O}");\n await Task.Delay(DelayBetweenLogWrites);\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n最后,LogTest是一个XUnit测试程序集,其中一个测试启动十个LogConsoleRunner写入同一日志文件的实例:
[Fact]\npublic async Task LaunchMultipleRunners()\n{\n string logFilePath = Path.GetTempFileName();\n using var ensureLogFileDisposed = new Nito.Disposables.AnonymousDisposable(() => File.Delete(logFilePath));\n\n string logConsoleRunnerAppExePath = Path.GetFullPath(\n Path.Combine(\n Path.GetDirectoryName(this.GetType().Assembly.Location),\n @"..\\..\\..\\..\\LogConsoleRunner\\bin\\Debug\\LogConsoleRunner.exe")); \n var startInfo = new ProcessStartInfo(logConsoleRunnerAppExePath)\n {\n Arguments = logFilePath,\n UseShellExecute = false\n };\n const int LaunchProcessCount = 10;\n Process[] processes = Enumerable\n .Range(0, LaunchProcessCount)\n .Select(i => Process.Start(startInfo))\n .ToArray();\n while (!processes.All(p => p.HasExited))\n {\n await Task.Delay(LogConsoleRunner.Program.DelayBetweenLogWrites);\n }\n\n string[] lines = File.ReadAllLines(logFilePath);\n Assert.Equal(LaunchProcessCount * LogConsoleRunner.Program.LogWritesCount, lines.Length);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n最后一行Assert.Equal总是失败,因为目标文件写入的行数始终少于预期计数(即 100)。在我的计算机上,每次运行它都会在 96 \xe2\x80\x93 99 之间变化,但它从不包含所有内容100 行。
我的问题:我应该如何配置NLog以确保在所有进程退出后,所有挂起的日志条目都写入目标日志文件?
只需LogManager.Shutdown()
在Main. 它将刷新所有待处理的日志事件。阅读更多。
旁注:如果您在刷新后需要 NLog,那么您可以使用 来代替 shutdown LogManager.Flush()。
| 归档时间: |
|
| 查看次数: |
3569 次 |
| 最近记录: |