基于NLog的通用日志包装器实现需求问询:多.NET场景日志统一方案
刚好我之前做过类似的多平台日志统一方案,用NLog来实现你要的CommonTrace函数完全没问题!下面一步步给你拆解实现过程,覆盖ASP.NET Core Web应用、Azure Functions和Web Services场景:
1. 先搞定NLog的基础配置
首先得给不同平台安装对应的NLog包:
- ASP.NET Core:安装
NLog.Web.AspNetCore - Azure Functions:安装
NLog.AzureFunctions - 常规Web Services:安装
NLog
然后创建nlog.config文件(放在项目根目录,设置为“始终复制”),配置你需要的输出目标,比如Application Insights和Azure Table Storage:
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true"> <!-- 配置输出目标 --> <targets> <!-- Application Insights 目标 --> <target xsi:type="ApplicationInsights" name="ai" /> <!-- Azure Table Storage 目标 --> <target xsi:type="AzureTableStorage" name="azureTable" connectionString="${environment:AZURE_STORAGE_CONNECTION_STRING}" tableName="ApplicationLogs" /> </targets> <!-- 日志路由规则 --> <rules> <logger name="*" minlevel="Trace" writeTo="ai,azureTable" /> </rules> </nlog>
2. 实现通用的
CommonTrace工具类 核心就是封装一个静态工具类,自动收集你要求的额外信息,然后调用NLog写入日志。这里用到System.Runtime.CompilerServices的特性来自动获取调用行号等信息:
using System; using System.Runtime.CompilerServices; using NLog; public static class CommonLogger { // 初始化NLog实例 private static readonly ILogger _logger = LogManager.GetCurrentClassLogger(); public static void CommonTrace(string message, [CallerLineNumber] int callerLineNumber = 0, [CallerMemberName] string callerMemberName = "", [CallerFilePath] string callerFilePath = "") { // 收集你要的额外信息 var environment = GetEnvironmentIdentifier(); var localTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"); var callingApp = GetCallingApplicationName(); // 把额外信息注入NLog的上下文,这样日志目标就能捕获到这些字段 using (var scope = _logger.PushProperty("Environment", environment)) using (scope.PushProperty("LocalTime", localTime)) using (scope.PushProperty("CallerLineNumber", callerLineNumber)) using (scope.PushProperty("CallingApplication", callingApp)) using (scope.PushProperty("CallerMemberName", callerMemberName)) using (scope.PushProperty("CallerFilePath", callerFilePath)) { // 调用NLog写入Trace级别的日志 _logger.Trace(message); } } // 获取环境标识(DEV/TEST/PROD) private static string GetEnvironmentIdentifier() { // 适配不同平台的环境变量 return Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? Environment.GetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT") ?? "UNKNOWN"; } // 获取调用应用的名称 private static string GetCallingApplicationName() { // 针对不同平台做适配 #if NETCOREAPP return System.Reflection.Assembly.GetEntryAssembly()?.GetName().Name ?? "ASP.NET Core App"; #elif AZURE_FUNCTIONS return Environment.GetEnvironmentVariable("WEBSITE_SITE_NAME") ?? "Azure Function"; #else return System.Reflection.Assembly.GetExecutingAssembly()?.GetName().Name ?? "Web Service"; #endif } }
3. 在各平台中使用
CommonTrace 不管是哪种平台,调用方式都是统一的,业务代码完全不用关心底层日志实现:
- ASP.NET Core:先在
Program.cs中启用NLog,然后直接调用:
var builder = WebApplication.CreateBuilder(args); // 清除默认日志提供器,改用NLog builder.Logging.ClearProviders(); builder.Host.UseNLog(); var app = builder.Build(); // 在任意地方调用 CommonLogger.CommonTrace("用户发起了登录请求");
- Azure Functions:如果是隔离进程模型,在
Program.cs中配置NLog;如果是进程内模型,直接在函数中调用即可:
public class LoginFunction { [FunctionName("LoginFunction")] public async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req) { CommonLogger.CommonTrace("Azure Function收到登录请求"); // 业务逻辑... return new OkObjectResult("登录成功"); } }
- 常规Web Services:初始化NLog后直接调用工具类方法就行,和ASP.NET Core的调用方式一致。
4. 验证日志输出
不管是写到Application Insights还是Azure Table Storage,你都能看到每条日志都包含了这些额外字段:
Environment:当前环境标识(DEV/TEST/PROD)LocalTime:日志产生的本地时间CallerLineNumber:调用CommonTrace的代码行号CallingApplication:调用方的应用名称- 还有自动捕获的调用成员名、文件路径
这样就实现了你要的统一日志调用体验,所有平台都用同一个CommonTrace方法,底层由NLog处理多目标输出,完美适配你的需求!
内容的提问来源于stack exchange,提问作者Adrian Warbeck
相关产品推荐
相关产品推荐

