【问题标题】:How to configure NLog for Azure Functions?如何为 Azure Functions 配置 NLog?
【发布时间】:2019-06-09 07:12:05
【问题描述】:

我真的需要一些帮助。

我想将 NLog 与 Azure Functions v2(Target Framework .NET Core 2.2)一起使用,并创建了一个

Startup : FunctionsStartup

类装饰

[assembly: FunctionsStartup(typeof(PmsFunctions.Startup))]

并创建了这个方法

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddLogging(loggingBuilder =>
    {
        loggingBuilder.ClearProviders();
        loggingBuilder.SetMinimumLevel(LogLevel.Trace);
        loggingBuilder.AddNLog();
    }).BuildServiceProvider();
}

在 Startup 类的构造函数中,我使用代码创建了 NLog 的配置:

var mailTarget = new MailTarget("mandrill")
{

    Html = true,
    AddNewLines = true,
    ReplaceNewlineWithBrTagInHtml = true,
    Subject = "XXXXX",
    To = "john@doe.com,
    From = "john@doe.com",
    Body = "Message: ${message}${newline}${newline}Date: ${date}${newline}${newline}Exception: ${exception:format=tostring}${newline}${newline}",
    SmtpUserName = "XXXXXXX",
    SmtpPassword = "XXXXXXX",
    SmtpAuthentication = SmtpAuthenticationMode.Basic,
    SmtpServer = "XXXXXXXX",
    SmtpPort = 587
};

var bufferedMailTarget = new BufferingTargetWrapper("bufferedMandril", mailTarget)
{
    SlidingTimeout = false,
    BufferSize = 100,
    FlushTimeout = 10000
};
config.AddTarget(bufferedMailTarget);

var mailRule = new LoggingRule("*", NLog.LogLevel.Warn, bufferedMailTarget);
config.LoggingRules.Add(mailRule);

var logger = NLogBuilder.ConfigureNLog(config).GetCurrentClassLogger

我尝试通过使用注入的 ILogger 在函数中使用记录器。它在本地完美运行,但在使用 Azure 时完全“死机”。我想这是我配置 NLog 的方式。

我应该如何正确地做到这一点?

【问题讨论】:

  • 你记得在退出前冲洗吗?好主意打电话NLog.LogManager.Shutdown()
  • @RolfKristensen:在 Azure Fuctions 中,您会在哪里调用 NLog.LogManager.Shutdown()?只是为了让我做对了。
  • 好吧,使用 try-catch-finally 并将 NLog.LogManager.Shutdown() 放在 finally 块中,并将错误记录放在 catch 块中。也许您想在使用超长超时(例如 60 秒)执行 Shutdown() 之前执行并显式调用 NLog.LogManager.Flush()。默认情况下,超时为“仅”15 秒,这可能不足以完成 mail-smtp-call。
  • 不要打电话给ClearProviders()(这会删除一些内部日志记录——我们很快就会阻止)或BuildServiceProvider()。如果这在本地有效但在 Azure 上无效,我怀疑应用服务沙箱中的某些内容可能会影响您。我会做一些调查并尝试重现这一点。
  • 您确定要等待 10 秒以上的冲洗时间吗?我能够让它工作(在下面添加了一个答案,以便您可以准确地看到我的代码)。

标签: c# azure-functions nlog


【解决方案1】:

为确保 NLog 遵循 Azure 函数的生命周期,您应该将其配置为与 Microsoft-Extension-Logging 一起关闭(和刷新):

[assembly: FunctionsStartup(typeof(MyNamespace.Startup))]

namespace MyNamespace
{
    public class Startup : FunctionsStartup
    {
        private readonly NLog.Logger Logger;

        public Startup()
        {
            Logger = LogManager.Setup()
               .SetupExtensions(e => e.AutoLoadAssemblies(false))
               .LoadConfigurationFromFile("NLog.config", optional: false)
               .LoadConfiguration(builder => builder.LogFactory.AutoShutdown = false)
               .GetCurrentClassLogger();
        }

        public override void Configure(IFunctionsHostBuilder builder)
        {
            // ... other setup code
            builder.Services.AddLogging((loggingBuilder) =>
            {
                var nlogOptions = new NLogProviderOptions() {
                    ShutdownOnDispose = true, 
                    RemoveLoggerFactoryFilter = true
                };
                loggingBuilder.AddNLog(nlogOptions);
            });
        }
    }
}

通知ShutdownOnDispose = trueAutoShutdown = false

【讨论】:

  • 您正在重复 NLog.Extensions.Logging 文档中的代码。 Logger 字段的用途是什么?它有什么帮助? (而readonly readonly 是一个语法错误)。
  • @TsahiAsher 已修复语法错误。 Logger 主要用于在 Microsoft ILogger 可用之前进行任何日志记录。
  • 谢谢。因此,如果我不需要 Startup 类中的记录器,我可以跳过它吗?还是我至少需要代码来设置LogFactory.AutoShutdown = false
  • @TsahiAsher 是的,重要的部分是 AutoShutdown = falseShutdownOnDispose = true 以确保 LoggerFactory-lifetime 处理关闭(在 AppDomain-shutdown 上禁用 NLog 自动关闭)。 Microsoft 在 .Net5 中引入了一个错误,即 AppDomain-shutdown-event 被过早触发(可能已使用 .Net6 修复)
【解决方案2】:

我就是这样设置的,并且我成功地从 Azure 中的服务接收电子邮件(我设置了一个函数来显式记录警告,因此当我调用它时,我会收到一封电子邮件)。

public Startup()
{
    LoggingConfiguration config = new LoggingConfiguration();

    var mailTarget = new MailTarget("mandrill")
    {
        Html = true,
        AddNewLines = true,
        ReplaceNewlineWithBrTagInHtml = true,
        Subject = "Test...",
        To = "-----",
        From = "john@doe.com",
        Body = "Message: ${message}${newline}${newline}Date: ${date}${newline}${newline}Exception: ${exception:format=tostring}${newline}${newline}",
        SmtpUserName = "-----",
        SmtpPassword = "-----",
        SmtpAuthentication = SmtpAuthenticationMode.Basic,
        SmtpServer = "-----",
        SmtpPort = 587
    };

    var bufferedMailTarget = new BufferingTargetWrapper("bufferedMandril", mailTarget)
    {
        SlidingTimeout = false,
        BufferSize = 100,
        FlushTimeout = 10000
    };

    config.AddTarget(bufferedMailTarget);

    var mailRule = new LoggingRule("*", NLog.LogLevel.Warn, bufferedMailTarget);
    config.LoggingRules.Add(mailRule);

    NLogBuilder.ConfigureNLog(config);
}

public override void Configure(IFunctionsHostBuilder builder)
{
    builder.Services.AddLogging(b =>
    {
        b.AddNLog();
    });
}

【讨论】:

    【解决方案3】:

    使用 MicrosoftILoggerTarget:

    var loggerTarget = new NLog.Extensions.Logging.MicrosoftILoggerTarget(azureILogger);
    loggerTarget.Layout = new NLog.Layouts.Layout("${message}${exception:format=tostring}");  // Can also be JsonLayout
    var nlogConfig = new NLog.Config.LoggingConfiguration();
    nlogConfig.AddRuleForAllLevels(loggerTarget);
    NLog.LogManager.Configuration = nlogConfig;
    var nlogLogger = NLog.LogManager.GetCurrentClassLogger();
    nlogLogger.Info("Hello World");
    

    来源:https://github.com/NLog/NLog.Extensions.Logging/wiki/NLog-cloud-logging-with-Azure-function-or-AWS-lambda

    【讨论】:

    • 这实际上是为了当你不想想要使用 NLog 作为日志提供者的时候。这会将日志重定向到配置的ILogger,这不是 NLog 的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2017-07-11
    • 2023-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-20
    相关资源
    最近更新 更多