【问题标题】:NLog throws 'Target cannot be found' for any custom target running on Azure Web App对于在 Azure Web App 上运行的任何自定义目标,NLog 会抛出“找不到目标”
【发布时间】:2019-06-21 15:23:10
【问题描述】:

我在 .NET Standard 2.0 上创建了两个 NLog 自定义目标,并将它们导入到现有的 ASP.NET 4.7.2 网站中。

nlog.config 看起来像这样:

<?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="Info"
      internalLogFile="${basedir}/internal-nlog.txt"
      throwExceptions="true"
      throwConfigExceptions="true">

    <extensions>
        <add assembly="MyAssembly"/>
    </extensions>

    <targets async="false">
        <target name="logconsole" xsi:type="Console" />
        <target xsi:type="AzureTableTarget"
                  name="azureTable"
                  // some configs
        />
        <target xsi:type="PostmarkLogTarget"
                  name="postmark"
                  // some configs
        />
    </targets>

    <rules>
        <logger name="*" minlevel="Warn" writeTo="postmark" />
        <logger name="*" minlevel="Info" writeTo="azureTable" />
        <logger name="*" minlevel="Debug" writeTo="logconsole" />
    </rules>
</nlog>

当应用在本地启动时,一切正常。当它在 Azure 应用服务上启动时,我会在 nlog 内部日志(以及一个又大又胖的错误页面)中得到这个:

2019-06-21 15:08:53.5719 Info Message Template Auto Format enabled
2019-06-21 15:08:53.6015 Info Loading assembly: MyAssembly
2019-06-21 15:08:53.6926 Info Adding target ConsoleTarget(Name=logconsole)
2019-06-21 15:08:53.7595 Error Parsing configuration from D:\home\site\wwwroot\NLog.config failed. Exception: NLog.NLogConfigurationException: Exception when parsing D:\home\site\wwwroot\NLog.config.  ---> System.ArgumentException: Target cannot be found: 'AzureTableTarget'
   at NLog.Config.Factory`2.CreateInstance(String itemName)
   at NLog.Config.LoggingConfigurationParser.ParseTargetsElement(ILoggingConfigurationElement targetsElement)
   at NLog.Config.LoggingConfigurationParser.ParseNLogSection(ILoggingConfigurationElement configSection)
   at NLog.Config.XmlLoggingConfiguration.ParseNLogSection(ILoggingConfigurationElement configSection)
   at NLog.Config.LoggingConfigurationParser.LoadConfig(ILoggingConfigurationElement nlogConfig, String basePath)
   at NLog.Config.XmlLoggingConfiguration.ParseNLogElement(ILoggingConfigurationElement nlogElement, String filePath, Boolean autoReloadDefault)
   at NLog.Config.XmlLoggingConfiguration.ParseTopLevel(NLogXmlElement content, String filePath, Boolean autoReloadDefault)
   at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
   --- End of inner exception stack trace ---
2019-06-21 15:08:53.8489 Error Failed loading from config file location: D:\home\site\wwwroot\NLog.config Exception: NLog.NLogConfigurationException: Exception when parsing D:\home\site\wwwroot\NLog.config.  ---> System.ArgumentException: Target cannot be found: 'AzureTableTarget'
   at NLog.Config.Factory`2.CreateInstance(String itemName)
   at NLog.Config.LoggingConfigurationParser.ParseTargetsElement(ILoggingConfigurationElement targetsElement)
   at NLog.Config.LoggingConfigurationParser.ParseNLogSection(ILoggingConfigurationElement configSection)
   at NLog.Config.XmlLoggingConfiguration.ParseNLogSection(ILoggingConfigurationElement configSection)
   at NLog.Config.LoggingConfigurationParser.LoadConfig(ILoggingConfigurationElement nlogConfig, String basePath)
   at NLog.Config.XmlLoggingConfiguration.ParseNLogElement(ILoggingConfigurationElement nlogElement, String filePath, Boolean autoReloadDefault)
   at NLog.Config.XmlLoggingConfiguration.ParseTopLevel(NLogXmlElement content, String filePath, Boolean autoReloadDefault)
   at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
   --- End of inner exception stack trace ---
   at NLog.Config.XmlLoggingConfiguration.Initialize(XmlReader reader, String fileName, Boolean ignoreErrors)
   at NLog.Config.XmlLoggingConfiguration..ctor(XmlReader reader, String fileName, Boolean ignoreErrors, LogFactory logFactory)
   at NLog.Config.LoggingConfigurationFileLoader.LoadXmlLoggingConfiguration(XmlReader xmlReader, String configFile, LogFactory logFactory)
   at NLog.Config.LoggingConfigurationFileLoader.LoadXmlLoggingConfigurationFile(LogFactory logFactory, String configFile)
   at NLog.Config.LoggingConfigurationFileLoader.TryLoadLoggingConfiguration(LogFactory logFactory, String configFile, LoggingConfiguration& config)
2019-06-21 15:08:54.1153 Info Configuring from an XML element in D:\home\site\wwwroot\NLog.config...
2019-06-21 15:08:54.1457 Info Message Template Auto Format enabled
2019-06-21 15:08:54.1457 Info Loading assembly: MyAssembly
2019-06-21 15:08:54.1457 Info Adding target ConsoleTarget(Name=logconsole)
2019-06-21 15:08:54.3332 Info Adding target AzureTableTarget(Name=azureTable)
2019-06-21 15:08:54.3525 Info Adding target PostmarkLogTarget(Name=postmark)
2019-06-21 15:08:54.4120 Info Found 38 configuration items
2019-06-21 15:08:54.4738 Info Configuration initialized.

第二次加载是因为我在 global.asax.cs 中有代码来专门注册和配置目标。此代码在设置 AutoFac 后立即触发,在任何尝试登录到任何地方之前。

在本地运行,代码按顺序执行这些步骤,即使在发布模式下也是如此。在 Azure 上运行时,它似乎尝试在配置完成之前记录一条消息。

即使是这样,两个自定义目标都有默认的公共构造函数,因此 NLog 应该能够自动实例化它们。 (这就是我在设置目标后重新加载配置的原因。)

两个问题:

  1. 导致(或允许)NLog 像这样开枪的 Azure 应用服务有什么不同?

  2. 没有删除 nlog.config 并设置登录代码,如何防止这种行为发生?

【问题讨论】:

标签: asp.net azure nlog


【解决方案1】:

找到了。哇。

我将这段代码放在一个 .cs 文件中:

public static readonly Logger Logger = LogManager.GetCurrentClassLogger();

在应用服务部署中,包含该行的类的静态构造函数在 App_Start 完成之前运行。在我的本地盒子上,它没有。

所以我把它改成了这样:

public static Logger Logger => _logger ?? (_logger = LogManager.GetCurrentClassLogger());
private static Logger _logger;

...现在一切正常。 Logger 仅在使用时创建,不仅仅是因为 ASP.NET 想要提前实例化静态类。

【讨论】:

    【解决方案2】:

    找不到目标:'AzureTableTarget'

    这意味着在其中一个程序集中找不到目标类“AzureTableTarget”,因此无法创建实例。

    您需要告诉 NLog 在哪个程序集中可以找到 AzureTableTarget 类型。

    类似这样的:

    <extensions>
        <add assembly="AssemblyNameWhereAzureTableTargetIsDefined"/>
    </extensions>
    

    导致(或允许)NLog 像这样开枪的 Azure 应用服务有什么不同?

    是否有相同的程序集可用?那么带有 AzureTableTarget 的程序集是否已发布?

    删除 nlog.config 并在代码中设置日志记录

    对于这种情况,NLog 是从文件配置还是从代码配置都没有关系。

    如何防止这种行为发生?

    始终将所有外部 NLog 扩展添加到 &lt;extensions&gt;

    最后但同样重要的是,不建议将throwExceptions="true" 用于生产! (如果您的日志记录中断,您真的喜欢您的应用程序中断吗?)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      相关资源
      最近更新 更多