NLog выбрасывает «Цель не найдена» для любой настраиваемой цели, работающей в веб-приложении Azure. - PullRequest
0 голосов
/ 21 июня 2019

Я создал две пользовательских цели NLog в .NET Standard 2.0 и импортировал их в существующий веб-сайт 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 и до того, как что-либо пытается войти в любое место.

При локальном запуске код выполняет эти шаги по порядку, даже в режиме Release.Похоже, что он пытается записать сообщение в журнал до завершения настройки при работе в Azure.

Даже если бы это было так, обе пользовательские цели имеют общедоступные конструкторы по умолчанию, поэтому NLog должен иметь возможность автоматически создавать их экземпляры.(Именно поэтому я перезагружаю конфиги после установки целей.)

Два вопроса:

  1. Чем отличается служба приложений Azure от того, что вызывает (или разрешает) NLogвот так прыгнуть?

  2. Если не считать удаления nlog.config и настройки регистрации в коде, как я могу предотвратить такое поведение?

Ответы [ 2 ]

1 голос
/ 21 июня 2019

Нашел это. Ничего себе.

У меня был этот код в файле .cs:

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

При развертывании службы приложений статический конструктор класса, содержащего эту строку, запускался до завершения App_Start. На моей локальной коробке это не так.

Так что я изменил это на:

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

... и все работает сейчас. Регистратор создается только при использовании, а не только потому, что ASP.NET хотел создать экземпляры статических классов заранее.

0 голосов
/ 21 июня 2019

Цель не может быть найдена: 'AzureTableTarget'

Это означает, что целевой класс AzureTableTarget не может быть найден в одной из сборок и, следовательно, экземпляр не может быть создан.

Вы должны указать NLog, в какой сборке может быть найден тип AzureTableTarget.

Примерно так:

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

Чем отличается служба приложений Azure, которая заставляет (или позволяет) NLog бросать оружие таким образом?

Доступны ли такие же сборки? Так опубликована ли сборка с AzureTableTarget?

Если не считать удаления nlog.config и настройки регистрации в коде

Для этого случая не имеет значения, настроен ли NLog из файла или из кода.

как я могу предотвратить такое поведение?

Всегда добавлять все внешние расширения NLog в <extensions>

И последнее, но не менее важное: throwExceptions="true" не рекомендуется для производства! (Если ваша регистрация прерывается, вам действительно нравится, что ваше приложение прерывается?)

...