在 ASP.NET Core 应用程序中使用 NLog

Posted

技术标签:

【中文标题】在 ASP.NET Core 应用程序中使用 NLog【英文标题】:Use NLog in ASP.NET Core application 【发布时间】:2016-04-13 07:03:36 【问题描述】:

我找到了一个CodeProject,其中有一个如何让它工作的例子,但它不起作用。主要问题似乎是 Nuget 中似乎不存在 "Microsoft.Framework.Logging.NLog": "1.0.0-*" 包。我查看了 this *** question 并查看了它引用的 GitHub 示例,但它似乎包含相同的问题。

我试图让它自己工作,我想出的最好的方法如下:

public class NLogLogger : ILogger

    public NLogLogger()
    
        new WebLoggerConfigurer().ConfigureDefault();
    

    public void Log(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)
    
        // currently need the global:: for LogLevels because our namespace contains NLog in it. Is there a better naming convention we could use instead?
        var ll = logLevel == LogLevel.Debug ? global::NLog.LogLevel.Debug
                : logLevel == LogLevel.Verbose ? global::NLog.LogLevel.Trace
                : logLevel == LogLevel.Critical ? global::NLog.LogLevel.Fatal
                : logLevel == LogLevel.Error ? global::NLog.LogLevel.Error
                : logLevel == LogLevel.Information ? global::NLog.LogLevel.Info
                : logLevel == LogLevel.Warning ? global::NLog.LogLevel.Warn
                : global::NLog.LogLevel.Off;

        LogManager.GetCurrentClassLogger().Log(ll, formatter(state, exception));
    

    public bool IsEnabled(LogLevel logLevel)
    
        return true;
    

    public IDisposable BeginScopeImpl(object state)
    
        return new Disposable(() =>  );
    


public class NLogLoggerProvider : ILoggerProvider

    public void Dispose()
    
    

    public ILogger CreateLogger(string categoryName)
    
        return new NLogLogger();
    


public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    loggerFactory.AddProvider(new NLogLoggerProvider());
    ..

BeginScopeImpl 的实现似乎是一个 hack,但我不确定如何最好地实现它。

    这看起来像是一个有效的实施选项吗? 是否有更好的方法来实现 BeginScopeImpl? 还有其他方法可以让 NLog 与 ASP.NET Core 一起工作吗?

【问题讨论】:

你有Github上的实现代码 【参考方案1】:

Microsoft.Framework.Logging.NLog 已替换为 NLog.Extensions.Logging on NuGet,由 NLog 团队维护。

对于 ASP.NET Core,您需要 NLog.Web.AspNetCore(它依赖于 NLog.Extensions.Logging)。

使用方法:

设置

需要启用 NLog,以便将其集成到 ASP.NET Core 的 DI 和日志 API 中。 这将导致所有由外部(例如 Microsoft)写入的日志也将发送到 NLog - 您可以在 NLog 的配置中将其过滤掉(不会影响性能)。

ASP.NET Core 1

在 ASP.NET Core 中的 Configure 和可选的 ConfigureServices 需要更新。

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    //add NLog to .NET Core
    loggerFactory.AddNLog();

    //Enable ASP.NET Core features (NLog.web) - only needed for ASP.NET Core users
    app.AddNLogWeb();

    //configure nlog.config in your project root. 
    env.ConfigureNLog("nlog.config");
    ...
    //you could use LogManager.Configuration from here


public void ConfigureServices(IServiceCollection services)

    // Add framework services.
    // e.g. services.AddMvc();

    //needed for NLog.Web
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

ASP.NET Core 2

对于 ASP.NET Core 2,设置不同于 ASP.NET Core 1

在 program.cs 中设置 NLog:

using NLog.Web;
using Microsoft.Extensions.Logging;

public static void Main(string[] args)

    // NLog: setup the logger first to catch all errors
    var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    try
    
        logger.Debug("init main");
        CreateWebHostBuilder(args).Build().Run(); 
    
    catch (Exception ex)
    
        //NLog: catch setup errors
        logger.Error(ex, "Stopped program because of exception");
        throw;
    
    finally
    
        // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
        NLog.LogManager.Shutdown();
    


public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureLogging(logging =>
        
            logging.ClearProviders();
            logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
        )
        .UseNLog();  // NLog: setup NLog for Dependency injection

ASP.NET Core 3 & 5

与 ASP.NET Core 2 相比,有一些小的变化,例如有一个IHostBuilder 而不是IWebHostBuilder

对于 ASP.NET Core 5,步骤相同。

在 program.cs 中设置 NLog:

using System;
using NLog.Web;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Hosting;

public static void Main(string[] args)

    var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
    try
    
        logger.Debug("init main");
        CreateHostBuilder(args).Build().Run();
    
    catch (Exception exception)
    
        //NLog: catch setup errors
        logger.Error(exception, "Stopped program because of exception");
        throw;
    
    finally
    
        // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
        NLog.LogManager.Shutdown();
    


public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
      .ConfigureWebHostDefaults(webBuilder =>
      
          webBuilder.UseStartup<Startup>();
      )
      .ConfigureLogging(logging =>
      
          logging.ClearProviders();
          logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
      )
      .UseNLog();  // NLog: Setup NLog for Dependency injection

写日志

使用类类型作为泛型参数注入ILogger

public class HomeController : Controller

    public HomeController(ILogger<HomeController> logger)
    
        logger.LogInformation("created homeController");
    

ASP.NET Core 6

对于 ASP.NET Core 6,您可以在没有 Startup 类的情况下对其进行配置。更新Program.cs如下:

using NLog;
using NLog.Web;

var logger = NLog.LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
logger.Debug("init main");

try

    var builder = WebApplication.CreateBuilder(args);

    // Add services to the container.
    builder.Services.AddControllersWithViews();

    // NLog: Setup NLog for Dependency injection
    builder.Logging.ClearProviders();
    builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
    builder.Host.UseNLog();

    var app = builder.Build();

    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    
        app.UseExceptionHandler("/Home/Error");
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.MapControllerRoute(
        name: "default",
        pattern: "controller=Home/action=Index/id?");

    app.Run();

catch (Exception exception)

    // NLog: catch setup errors
    logger.Error(exception, "Stopped program because of exception");
    throw;

finally

    // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
    NLog.LogManager.Shutdown();

配置 NLog 规则

有关如何配置、记录和过滤的示例。

创建一个 nlog.config(有关 nlog.config 的更多信息,请参阅docs)。

此示例将创建 2 个文件,一个包含所有日志(包括 Microsoft 的),一个文件仅包含您的日志。

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        autoReload="true"
        internalLogLevel="Warn"
        internalLogFile="c:\temp\internal.txt">


    <extensions>
        <!--enable NLog.Web for ASP.NET Core-->
        <add assembly="NLog.Web.AspNetCore"/>
    </extensions>

    <!-- define various log targets -->
    <targets>
        <!-- write logs to file -->
        <target xsi:type="File" name="allfile" fileName="c:\temp\nlog-all-$shortdate.log"
                        layout="$longdate|$logger|$uppercase:$level|$message $exception" />

        <target xsi:type="File" name="ownFile" fileName="c:\temp\nlog-own-$shortdate.log"
                    layout="$longdate|$logger|$uppercase:$level|$message $exception" />

    </targets>

    <rules>
        <!--All logs, including from Microsoft-->
        <logger name="*" minlevel="Trace" writeTo="allfile" />

        <!--Skip Microsoft logs - no writeTo attribute-->
        <logger name="Microsoft.*" minlevel="Trace" final="true" />
        <logger name="*" minlevel="Trace" writeTo="ownFile" />
    </rules>
</nlog>

发布 nlog.config

这不是 ASP.NET Core 5 的必需步骤

确保 nlog.config 将被发布,例如在您的 csproj 文件中:

<ItemGroup>
    <Content Update="nlog.config" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

输出

“nlog-own-2018-02-14.log”包含:

2018-02-14 16:27:04.0547|aspnetCoreApplication.Controllers|INFO|创建的 homeController

2018-02-14 16:27:04.0547|aspnetCoreApplication.Controllers|INFO|创建的 homeController

疑难解答

在 ASP.NET Core 2 中缺少调试日志消息?虽然我们在 program.cs 中使用 SetMinimumLevel,但 appsettings.json 也可以将其融合。

你可以改变如下:

更改 appsettings.json:


    "Logging": 
        "LogLevel": 
            "Default": "Trace"
        
    

你也可以在这里过滤微软的日志,例如


    "Logging": 
        "LogLevel": 
            "Default": "Trace",
            "Microsoft": "Information"
        
    

其他问题,看这个步骤计划查找原因: Logging-troubleshooting in NLog

干杯,

朱利安 (NLog)

编辑:为 NLog.Web.AspNetCore 4.3 更新

编辑 2:针对 ASP.NET Core 2 和最新建议进行了更新

编辑 3:针对 ASP.NET Core 3 更新

编辑 4:针对 ASP.NET Core 5 更新

编辑 5:针对 ASP.NET Core 6 更新

【讨论】:

app.AddNLogWeb() 对于 NetStandard 2.0 已过时,因为 NLog.Web.AspNetCore v4.7.0 / 2017 年 9 月 29 日:github.com/NLog/NLog.Web/commit/7c6429c7。 @Julian ,到目前为止看起来不错,如果我有 BaseClass => ChildClasses,如果我需要登录 Base,注入如何工作?有什么想法吗? @Gopichandar 很难在评论中回答,建议创建一个新问题。 (但请先搜索,我认为它已经在 *** 上得到了回答)【参考方案2】:

更新到Julian's answer:NLog.Framework.Logging 被标记为已过时,请改用NLog.Extensions.Logging(不过只是一个包重命名)。此外,env.ConfigureNLog("nlog.config"); 仅适用于 Visual Studio (IIS Express) 中的调试。在测试环境中向常规 IIS 发布服务后,它无法以500 internal server error 启动。花了很长时间才发现服务在启动时找不到nlog.config。终于找到解决方案in NLog issues:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationEnvironment appEnv)

    ...
    env.ConfigureNLog(Path.Combine(appEnv.ApplicationBasePath, "nlog.config"));
    ...

问题是在本地调试时工作目录是你的项目目录,里面有nlog.config,但是发布到IIS后,所有源文件都在%PATH_TO_PUBLISHED_SERVICE%\approot\src\%PROJECT_NAME%\,而工作目录是%PATH_TO_PUBLISHED_SERVICE%\

【讨论】:

【参考方案3】:

也可用于 .net 核心控制台应用程序。

private static void ConfigureNlogConfig(string configFile)
  LogManager.Configuration = new XmlLoggingConfiguration(Path.Combine(Microsoft.Extensions.PlatformAbstractions.PlatformServices.Default.Application.ApplicationBasePath,configFile), true);

【讨论】:

这正是我在 .Net 核心控制台应用程序中运行 NLog 所缺少的部分。 loggerFactory.AddNLog();似乎(还没有?)将 NLog 配置为使用应用程序目录中的 nlog.config 文件。 从 NLog.Extensions.Logging 的 1.0.0-rtm-beta1 开始,这应该是不必要的【参考方案4】:

现在有关于如何将 NLog 与 ASP.NET Core 一起使用的官方 Wiki 页面:

NLog Wiki - Getting started with ASP.NET Core 6 NLog Wiki - Getting started with ASP.NET Core 5 NLog Wiki - Getting started with ASP.NET Core 3 NLog Wiki - Getting started with ASP.NET Core 2 NLog Wiki - Getting started with ASP.NET Core 1

【讨论】:

以上是关于在 ASP.NET Core 应用程序中使用 NLog的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)

asp.net core中托管SPA应用

如何使用 EF Core 在 ASP.NET Core 中取消应用迁移

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)

如何在 ASP.Net Core 中使用 IHostedService

在 ASP.NET Core 应用程序中使用多个 HttpClient 对象