修改日志框架

This commit is contained in:
chfei committed 2026-10-15 17:15:10 +08:00
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&lt;T&gt; 与 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();
-138
View File
@@ -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);
// }
// }
//}
+8 -1
View File
@@ -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>
+141
View File
@@ -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
}
}
]
}
}
}
]
}
}
+10 -4
View File
@@ -10,12 +10,18 @@
<ItemGroup>
<ProjectReference Include="..\..\Store.Framework\Store.Framework.csproj" />
</ItemGroup>
<ItemGroup>
<!-- 本模块自己的配置文件:源码里叫 appsettings.json,构建后复制到宿主输出目录时改名为
<!--<ItemGroup>
--><!-- 本模块自己的配置文件:源码里叫 appsettings.json,构建后复制到宿主输出目录时改名为
appsettings.CloudProduct.json,避免和宿主自己的 appsettings.json 互相覆盖。
由 builder.AddStoreHub() 自动并入宿主配置树(在 appsettings*.json 之后、环境变量之前)。 -->
由 builder.AddStoreHub() 自动并入宿主配置树(在 appsettings*.json 之后、环境变量之前)。 --><!--
<None Update="appsettings.json" Link="appsettings.CloudProduct.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</ItemGroup>-->
<ItemGroup>
<None Update="appsettings.CloudProduct.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.25" />
<PackageReference Include="Hangfire.Dashboard.Basic.Authentication" Version="8.0.0" />
+5 -1
View File
@@ -16,13 +16,15 @@ namespace Store.Api.Controllers
private readonly ITokenService _tokenService;
private readonly ICurrentUser _currentUser;
private readonly IOnlineUserStore _onlineUserStore;
private readonly ILogger<AuthController> _logger;
public AuthController( ITokenService tokenService, ICurrentUser currentUser, IOnlineUserStore onlineUserStore)
public AuthController(ITokenService tokenService, ICurrentUser currentUser, IOnlineUserStore onlineUserStore, ILogger<AuthController> logger)
{
//_userService = userService;
_tokenService = tokenService;
_currentUser = currentUser;
_onlineUserStore = onlineUserStore;
_logger = logger;
}
/// <summary>
@@ -32,6 +34,8 @@ namespace Store.Api.Controllers
[AllowAnonymous]
public async Task<ApiResult> Login([FromBody] LoginRequest request)
{
_logger.LogError("login errr");
_logger.LogInformation("login");
if (request is null || string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password))
{
return ApiResult.Fail("用户名或密码不能为空", 400);
+2 -3
View File
@@ -1,5 +1,4 @@
using Asp.Versioning;
using MAX.Core.Logger;
using MAX.Framework.DependencyInjection;
using Scalar.AspNetCore;
@@ -10,7 +9,7 @@ public partial class Program
var builder = WebApplication.CreateBuilder(args);
// IOC 注册:自动注册 ISingletonDependency / IScopedDependency / ITransientDependency,并执行所有 IStartup / IModule.AddModule
// 模块服务注册阶段(等价于 builder.Services.AddStoreHub(builder.Configuration, builder.Environment),额外把配置/环境交给模块)
// 模块服务注册阶段(等价于 builder.Services.AddStoreHub(builder.Configuration, builder.Environment),额外把配置/环境交给模块)
builder.AddStore();
builder.Services.AddFreeSqlDB();
// JWT 验证:注册 JwtBearer 认证 + 令牌服务 + OpenAPI Bearer 安全方案(配置节 Jwt)
@@ -37,7 +36,7 @@ public partial class Program
WebApplication app = builder.Build();
app.UseStore();
// 初始化 KJD 迁移的静态提供者(MysqlUtils 连接提供 / 业务配置读取)
//StoreHub.KJDWebService.Commons.AdoProvider.SetServiceProvider(app.Services);
+1 -6
View File
@@ -7,12 +7,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Log\**" />
<Content Remove="Log\**" />
<EmbeddedResource Remove="Log\**" />
<None Remove="Log\**" />
</ItemGroup>
<ItemGroup>
-13
View File
@@ -1,13 +0,0 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "10.0.13",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}