using MAX.Framework.Logger; using NLog; using NLog.Config; using NLog.Targets; using Store.Management.Framework.Configs; using System.Diagnostics; using System.IO; using System.Text; namespace Store.Management.Framework.Services; /// 默认运行日志与不依赖容器的同步崩溃报告。 public static class ApplicationLogService { public static void Initialize() { // 在加载文件配置前注入目录,配置自动重载时仍可读取。 GlobalDiagnosticsContext.Set("LoggingFolder", FolderConfig.LoggingFolder); // 尊重宿主提供的 NLog 配置。 if (LogManager.Configuration != null) return; var target = new FileTarget("application") { FileName = Path.Combine(FolderConfig.LoggingFolder, "${shortdate}.log"), Layout = "${longdate}|${level:uppercase=true}|${logger}|${message} ${exception:format=tostring}", Encoding = Encoding.UTF8, MaxArchiveDays = 30 }; var configuration = new LoggingConfiguration(); configuration.AddRule(LogLevel.Debug, LogLevel.Fatal, target); LogManager.Configuration = configuration; } /// 报告路径;所有目录均写入失败时返回 null。 public static string? WriteFatal(Exception exception, string source) { ArgumentNullException.ThrowIfNull(exception); string id = $"{DateTime.UtcNow:yyyyMMdd-HHmmssfff}-{Guid.NewGuid():N}"; string report = $"Id: {id}\nTime: {DateTimeOffset.Now:O}\nSource: {source}\nApp: {Config.AppFullName}\nVersion: {Config.Version}\nSession: {Config.SessionID}\nStarted: {Config.AppStartTime:O}\nWindows: {Config.WindowsVersion}\n{exception}"; Debug.WriteLine(report); string? savedPath = null; foreach (string directory in new[] { FolderConfig.LoggingFolder, Path.Combine(Path.GetTempPath(), FolderConfig.AppName, "Logs") }) { try { Directory.CreateDirectory(directory); savedPath = Path.Combine(directory, $"fatal-{id}.log"); File.WriteAllText(savedPath, report, Encoding.UTF8); break; } catch (Exception ex) { savedPath = null; Debug.WriteLine(ex); } } try { LogManager.GetLogger("GlobalLogger").Fatal(exception, "{0}: {1}; Report: {2}", source, id, savedPath); LogManager.Flush(TimeSpan.FromSeconds(2)); } catch (Exception ex) { Debug.WriteLine(ex); } return savedPath; } }