using Serilog; using Serilog.Context; using Serilog.Core; using Serilog.Events; using System.Diagnostics; using System.Runtime.CompilerServices; namespace YY.Admin.Core { public class SerilogLoggerService : ILoggerService { private readonly Serilog.ILogger _logger; private readonly IReadOnlyList _logReportSinks; public SerilogLoggerService(IEnumerable logReportSinks) { _logReportSinks = logReportSinks?.ToList() ?? new List(); _logger = new LoggerConfiguration() .MinimumLevel.Debug() .Enrich.WithThreadId() .Enrich.WithMachineName() .WriteTo.Debug(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}") .WriteTo.Console(outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message:lj}{NewLine}{Exception}") .WriteTo.File("logs/app.log", rollingInterval: RollingInterval.Day, retainedFileCountLimit: 7, outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] ({ThreadId}) {Message:lj}{NewLine}{Exception}") .CreateLogger(); } public void Information(string message) { _logger.Information(message); _ = PushRemoteAsync("OPERATION", message); } public void Warning(string message) { _logger.Warning(message); _ = PushRemoteAsync("WARNING", message); } public void Error(string message, Exception? ex = null) { _logger.Error(ex, message); _ = PushRemoteAsync("EXCEPTION", message, exception: ex?.ToString()); } public void Debug(string message) { _logger.Debug(message); _ = PushRemoteAsync("DEBUG", message); } public void Performance(string operationName, TimeSpan duration) { _logger.Information("Performance: {Operation} completed in {Duration}ms", operationName, duration.TotalMilliseconds); _ = PushRemoteAsync("OPERATION", $"Performance: {operationName} completed in {duration.TotalMilliseconds}ms"); } private async Task PushRemoteAsync(string category, string message, bool? success = null, string? exception = null) { if (_logReportSinks.Count == 0 || string.IsNullOrWhiteSpace(message)) { return; } foreach (var sink in _logReportSinks) { try { await sink.ReportLogAsync(category, message, null, success, exception); } catch { // 上报失败不影响本地主日志链路 } } } } }