Files
StoreWeb/Core/MAX.Framework/DependencyInjection/LoggerExtensions.cs
T
2026-10-15 17:15:10 +08:00

76 lines
2.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Serilog;
using Serilog.Debugging;
namespace MAX.Framework.DependencyInjection
{
/// <summary>
/// Serilog 日志接入:读取 appsettings.Serilog.json(文件缺失时回退到主配置里的 Serilog 节点),
/// 再把 Serilog 接入 ASP.NET Core 日志管线,使 ILogger&lt;T&gt; 与 Log 静态入口共用同一套 Sink。
/// 日志按等级分目录(logs/等级/日期.log)由 appsettings.Serilog.json 里的 File sink + rollingInterval 负责。
/// </summary>
public static class LoggerExtensions
{
/// <summary>Serilog 独立配置文件(构建/发布会复制到输出目录)。</summary>
private const string ConfigurationFileName = "appsettings.Serilog.json";
public static IHostApplicationBuilder AddLogger(this IHostApplicationBuilder host)
{
IConfigurationManager configuration = host.Configuration;
// Serilog 默认会静默吞掉配置错误(Sink 名写错、过滤器语法错误等),
// 开发环境把自诊断信息输出到控制台,避免再出现「配置了却没有日志」却查不到原因。
if (host.Environment.IsDevelopment())
{
SelfLog.Enable(Console.Error.WriteLine);
}
string? configurationPath = ResolveConfigurationPath(host);
if (configurationPath is null)
{
// 不直接抛异常:允许把 Serilog 节点写进 appsettings.json,但必须显式提示,而不是静默降级成「无任何 Sink」。
Console.Error.WriteLine($"[Serilog] 未找到 {ConfigurationFileName},将使用主配置中的 Serilog 节点。");
}
else
{
configuration.AddJsonFile(configurationPath, optional: false, reloadOnChange: true);
}
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
// 接管 ASP.NET Core 日志管线:宿主日志与 ILogger<T> 统一写入 Log.Logger;
// dispose: true 让宿主停止时自动 CloseAndFlush,保证缓冲中的日志落盘。
host.Services.AddSerilog(Log.Logger, dispose: true);
return host;
}
/// <summary>
/// 定位 Serilog 配置文件:支持绝对路径,其余情况依次在内容根目录(开发时即项目目录)与程序输出目录中查找。
/// </summary>
private static string? ResolveConfigurationPath(IHostApplicationBuilder host)
{
if (Path.IsPathRooted(ConfigurationFileName))
{
return File.Exists(ConfigurationFileName) ? ConfigurationFileName : null;
}
string[] candidates =
[
Path.Combine(host.Environment.ContentRootPath, ConfigurationFileName),
Path.Combine(AppContext.BaseDirectory, ConfigurationFileName),
];
return candidates.FirstOrDefault(File.Exists);
}
}
}