修改日志框架
This commit is contained in:
1 parent
f1fa0401c2
commit
fdc9b9e36d
11 files changed
+230
-175
No files matched your search
@@ -1,22 +1,75 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog.Web;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Serilog;
|
||||
using Serilog.Debugging;
|
||||
|
||||
namespace MAX.Framework.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
/// Serilog 日志接入:读取 appsettings.Serilog.json(文件缺失时回退到主配置里的 Serilog 节点),
|
||||
/// 再把 Serilog 接入 ASP.NET Core 日志管线,使 ILogger<T> 与 Log 静态入口共用同一套 Sink。
|
||||
/// 日志按等级分目录(logs/等级/日期.log)由 appsettings.Serilog.json 里的 File sink + rollingInterval 负责。
|
||||
/// </summary>
|
||||
public static class LoggerExtensions
|
||||
{
|
||||
public static WebApplicationBuilder AddLogger(this WebApplicationBuilder builder)
|
||||
/// <summary>Serilog 独立配置文件(构建/发布会复制到输出目录)。</summary>
|
||||
private const string ConfigurationFileName = "appsettings.Serilog.json";
|
||||
|
||||
public static IHostApplicationBuilder AddLogger(this IHostApplicationBuilder host)
|
||||
{
|
||||
builder.Logging.ClearProviders();
|
||||
//builder.Logging.SetMinimumLevel(LogLevel.Information);
|
||||
builder.Host.UseNLog();
|
||||
return builder;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ namespace MAX.Framework.DependencyInjection
|
||||
/// </summary>
|
||||
public static IServiceCollection AddStore(this IHostApplicationBuilder host)
|
||||
{
|
||||
host.AddLogger();
|
||||
//host.Services.AddSingleton<ILoggerFacade>(NLogger.Instance);//注册log
|
||||
|
||||
IEnumerable<Assembly> assemblies = GetApplicationAssemblies();
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
//using MAX.Core.Interfaces;
|
||||
//using MAX.Core.Logger;
|
||||
//using NLog;
|
||||
//using System;
|
||||
//using LLogLevel = MAX.Core.Logger.LogLevel;
|
||||
//using NLogLevel = NLog.LogLevel;
|
||||
|
||||
//namespace MAX.Framework.Logger;
|
||||
|
||||
//public class NLogger : SingleInstance<NLogger>, ILoggerFacade
|
||||
//{
|
||||
// private readonly ILogger _log;
|
||||
|
||||
// private NLogger()
|
||||
// {
|
||||
// _log = LogManager.GetLogger("GlobalLogger");
|
||||
// }
|
||||
|
||||
// public bool IsDebugEnabled { get; private set; } = true;
|
||||
|
||||
// public void Debug(Exception ex, string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Debug, ex, message);
|
||||
// }
|
||||
|
||||
// public void Debug(string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Debug, message);
|
||||
// }
|
||||
// public void Error(Exception ex)
|
||||
// {
|
||||
// Execute(NLogLevel.Error, ex);
|
||||
// }
|
||||
// public void Error(Exception ex, string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Error, ex, message);
|
||||
// }
|
||||
|
||||
// public void Error(string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Error, message);
|
||||
// }
|
||||
|
||||
// public void Fatal(Exception ex, string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Fatal, ex, message);
|
||||
// }
|
||||
|
||||
// public void Fatal(string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Fatal, message);
|
||||
// }
|
||||
|
||||
// public void Info(Exception ex, string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Info, ex, message);
|
||||
// }
|
||||
|
||||
// public void Info(string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Info, message);
|
||||
// }
|
||||
|
||||
// public void Warn(Exception ex, string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Warn, ex, message);
|
||||
// }
|
||||
|
||||
// public void Warn(string message)
|
||||
// {
|
||||
// Execute(NLogLevel.Warn, message);
|
||||
// }
|
||||
// public void Log(string message, LLogLevel level)
|
||||
// {
|
||||
// NLogLevel lv = NLogLevel.Info;
|
||||
// switch (level)
|
||||
// {
|
||||
// case LLogLevel.Trace:
|
||||
// lv = NLogLevel.Trace;
|
||||
// break;
|
||||
// case LLogLevel.Debug:
|
||||
// lv = NLogLevel.Debug;
|
||||
// break;
|
||||
// case LLogLevel.Info:
|
||||
// lv = NLogLevel.Info;
|
||||
// break;
|
||||
// case LLogLevel.Warn:
|
||||
// lv = NLogLevel.Warn;
|
||||
// break;
|
||||
// case LLogLevel.Error:
|
||||
// lv = NLogLevel.Error;
|
||||
// break;
|
||||
// case LLogLevel.Fatal:
|
||||
// lv = NLogLevel.Fatal;
|
||||
// break;
|
||||
// case LLogLevel.None:
|
||||
// lv = NLogLevel.Off;
|
||||
// break;
|
||||
// }
|
||||
// Execute(lv, message);
|
||||
// }
|
||||
// /// <summary>
|
||||
// /// 是否启用
|
||||
// /// </summary>
|
||||
// private bool Enabled(NLogLevel level)
|
||||
// {
|
||||
// if (level > NLogLevel.Debug)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// return IsDebugEnabled;
|
||||
// }
|
||||
|
||||
// /// <summary>
|
||||
// /// 执行
|
||||
// /// </summary>
|
||||
// private void Execute(NLogLevel level, Exception ex, string message = "")
|
||||
// {
|
||||
// if (Enabled(level))
|
||||
// {
|
||||
// _log.Log(level, ex, message, null);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// /// <summary>
|
||||
// /// 执行
|
||||
// /// </summary>
|
||||
// private void Execute(NLogLevel level, string message)
|
||||
// {
|
||||
// if (Enabled(level))
|
||||
// {
|
||||
// _log.Log(level, message);
|
||||
// }
|
||||
// }
|
||||
|
||||
//}
|
||||
@@ -16,9 +16,10 @@
|
||||
<PackageReference Include="FreeSql.Repository" Version="3.5.311" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.10" />
|
||||
<PackageReference Include="Microsoft.IO.RecyclableMemoryStream" Version="3.0.1" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="6.2.0" />
|
||||
<PackageReference Include="Riok.Mapperly" Version="4.3.1" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="10.0.0" />
|
||||
<PackageReference Include="Serilog.Settings.Configuration" Version="10.0.1" />
|
||||
<PackageReference Include="Serilog.Filters.Expressions" Version="2.1.0" />
|
||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
|
||||
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
@@ -31,4 +32,10 @@
|
||||
<Folder Include="Models\" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="appsettings.Serilog.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,141 @@
|
||||
{
|
||||
"Serilog": {
|
||||
"Using": [
|
||||
"Serilog.Sinks.Console",
|
||||
"Serilog.Sinks.File",
|
||||
"Serilog.Filters.Expressions"
|
||||
],
|
||||
"MinimumLevel": {
|
||||
"Default": "Debug",
|
||||
"Override": {
|
||||
"Microsoft": "Information",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"System": "Warning",
|
||||
"Hangfire": "Information"
|
||||
}
|
||||
},
|
||||
"Enrich": [
|
||||
"FromLogContext"
|
||||
],
|
||||
"Properties": {
|
||||
"Application": "MyAspNetCore"
|
||||
},
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "Logger",
|
||||
"Args": {
|
||||
"configureLogger": {
|
||||
"Filter": [
|
||||
{ "Name": "ByIncludingOnly", "Args": { "expression": "@Level = 'Debug'" } }
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "Logs/Debug/.log",
|
||||
"rollingInterval": "Day",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
||||
"retainedFileCountLimit": 365,
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Logger",
|
||||
"Args": {
|
||||
"configureLogger": {
|
||||
"Filter": [
|
||||
{ "Name": "ByIncludingOnly", "Args": { "expression": "@Level = 'Information'" } }
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "Logs/Info/.log",
|
||||
"rollingInterval": "Day",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
||||
"retainedFileCountLimit": 365,
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Logger",
|
||||
"Args": {
|
||||
"configureLogger": {
|
||||
"Filter": [
|
||||
{ "Name": "ByIncludingOnly", "Args": { "expression": "@Level = 'Warning'" } }
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "Logs/Warning/.log",
|
||||
"rollingInterval": "Day",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
||||
"retainedFileCountLimit": 365,
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Logger",
|
||||
"Args": {
|
||||
"configureLogger": {
|
||||
"Filter": [
|
||||
{ "Name": "ByIncludingOnly", "Args": { "expression": "@Level = 'Error'" } }
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "Logs/Error/.log",
|
||||
"rollingInterval": "Day",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
||||
"retainedFileCountLimit": 365,
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Name": "Logger",
|
||||
"Args": {
|
||||
"configureLogger": {
|
||||
"Filter": [
|
||||
{ "Name": "ByIncludingOnly", "Args": { "expression": "@Level = 'Fatal'" } }
|
||||
],
|
||||
"WriteTo": [
|
||||
{
|
||||
"Name": "File",
|
||||
"Args": {
|
||||
"path": "Logs/Fatal/.log",
|
||||
"rollingInterval": "Day",
|
||||
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz} [{Level:u3}] {Message:lj}{NewLine}{Exception}",
|
||||
"retainedFileCountLimit": 365,
|
||||
"fileSizeLimitBytes": 104857600,
|
||||
"rollOnFileSizeLimit": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user