You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:51:19