我已经在.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 App Service上启动时,我在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应该能够自动实例化它们。 (这就是为什么我在设置目标后重新加载配置的原因。)
两个问题:
Azure App Service导致(或允许)NLog这样跳动的是什么?
删除nlog.config并设置登录代码的时间短,如何防止这种行为发生?
答案 0 :(得分:1)
找到了。哇!
我将此代码挂在.cs文件中:
public static readonly Logger Logger = LogManager.GetCurrentClassLogger();
在App Service部署中,包含该行的类的静态构造函数在App_Start完成之前运行。在我的本地盒子上没有。
所以我将其更改为:
public static Logger Logger => _logger ?? (_logger = LogManager.GetCurrentClassLogger());
private static Logger _logger;
...现在一切正常。记录器仅在使用时创建,而不仅仅是因为ASP.NET希望提前实例化静态类。
答案 1 :(得分:0)
找不到目标:“ AzureTableTarget”
这意味着无法在其中一个程序集中找到目标类'AzureTableTarget',因此无法创建实例。
您需要告诉NLog在哪个程序集中可以找到AzureTableTarget类型。
类似这样的东西:
<extensions>
<add assembly="AssemblyNameWhereAzureTableTargetIsDefined"/>
</extensions>
Azure App Service导致(或允许)NLog这样跳动的是什么?
是否有相同的程序集?那么发布带有AzureTableTarget的程序集了吗?
删除nlog.config并设置代码登录的简短过程
在这种情况下,从文件还是从代码配置NLog都没关系。
如何防止这种行为发生?
始终将所有外部NLog扩展名添加到<extensions>
最后但并非最不重要的是,不建议将throwExceptions="true"
用于生产! (如果您的日志记录中断了,您是否真的喜欢您的应用程序中断?)