using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Serilog; using Serilog.Events; using SlnMesnac.Config; using System; using System.IO; #region << 版 本 注 释 >> /*-------------------------------------------------------------------- * 版权所有 (c) 2024 WenJY 保留所有权利。 * CLR版本:4.0.30319.42000 * 机器名称:LAPTOP-E0N2L34V * 命名空间:SlnMesnac.Serilog * 唯一标识:496f8d2b-70e3-4a05-ae18-a9b0fcd06b82 * * 创建者:WenJY * 电子邮箱:wenjy@mesnac.com * 创建时间:2024-03-27 21:58:35 * 版本:V1.0.0 * 描述: * *-------------------------------------------------------------------- * 修改人: * 时间: * 修改说明: * * 版本:V1.0.0 *--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> namespace SlnMesnac.Serilog { /// /// Serilog /// public static class SerilogExtensions { public static void UseSerilogExtensions(this IServiceProvider service) { #region 通过配置文件读取日志存放位置 var appConfig = service.GetService(); var logPath = appConfig?.logPath ?? "Logs"; // 如果是多实例,使用实例专用的日志路径 // 注意:App类中的InstanceDataPath已经是实例专用的路径 if (appConfig?.InstanceDataPath != null) { // 使用实例数据路径下的Logs目录 logPath = Path.Combine(appConfig.InstanceDataPath, "Logs"); } // 确保日志目录存在 EnsureLogDirectories(logPath); #endregion // 构建日志配置,包含实例ID作为上下文 Log.Logger = new LoggerConfiguration() .MinimumLevel.Information() .Enrich.WithProperty("InstanceId", appConfig?.InstanceId ?? "Unknown") .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3} {InstanceId}] {Message:lj}{NewLine}{Exception}") .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Info")) .WriteTo.File( Path.Combine($"{logPath}/Info/", "Info.log"), rollingInterval: RollingInterval.Day, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3} {InstanceId}] {Message:lj}{NewLine}{Exception}", retainedFileCountLimit: 7)) // 保留最近7天的日志文件 .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Data")) .WriteTo.File( Path.Combine($"{logPath}/Data/", "Data.log"), rollingInterval: RollingInterval.Day, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3} {InstanceId}] {Message:lj}{NewLine}{Exception}", retainedFileCountLimit: 7)) .WriteTo.Logger(lc => lc .Filter.ByIncludingOnly(logEvent => logEvent.Properties.ContainsKey("Module") && logEvent.Properties["Module"].ToString().Contains("Error")) .WriteTo.File( Path.Combine($"{logPath}/Error/", "Error.log"), rollingInterval: RollingInterval.Day, outputTemplate: "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff} {Level:u3} {InstanceId}] {Message:lj}{NewLine}{Exception}", retainedFileCountLimit: 30)) // 错误日志保留更长时间 .CreateLogger(); } /// /// 确保日志目录存在 /// private static void EnsureLogDirectories(string baseLogPath) { try { // 确保基础日志目录存在 if (!Directory.Exists(baseLogPath)) { Directory.CreateDirectory(baseLogPath); } // 确保各模块日志子目录存在 string[] subDirectories = { "Info", "Data", "Error", "Debug", "Audit" }; foreach (var subDir in subDirectories) { string dirPath = Path.Combine(baseLogPath, subDir); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } } // 创建当前实例的启动日志文件 string startupLog = Path.Combine(baseLogPath, "Startup.log"); File.AppendAllText(startupLog, $"=== Instance Startup ===\r\n" + $"Time: {DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}\r\n" + $"Base Log Path: {baseLogPath}\r\n" + $"=================================================================\r\n"); } catch (Exception ex) { // 如果无法创建目录,使用临时目录 Console.WriteLine($"无法创建日志目录 {baseLogPath}: {ex.Message}"); // 尝试使用临时目录作为后备 string tempLogPath = Path.Combine(Path.GetTempPath(), "SlnMesnac", "Logs"); if (!Directory.Exists(tempLogPath)) { Directory.CreateDirectory(tempLogPath); } } } } }