自定义 NLog 布局渲染器在某些项目中不产生任何输出

Posted

技术标签:

【中文标题】自定义 NLog 布局渲染器在某些项目中不产生任何输出【英文标题】:Custom NLog Layout Renderer Produces No Output In Some Projects 【发布时间】:2022-01-22 11:26:38 【问题描述】:

.NET 框架 4.8、NLog 4.7.6

我已经实现了两个简单的 LayoutRenderer 子类,它们只编写了一个 Guid(从 Web 上下文或静态 Stack<T> 获取)。这些在两个 Web 项目中运行良好,但它们不适用于第三个 Web 应用程序或几个控制台应用程序/服务。应用之间的配置是一致的,但有些可以工作,有些不能。

例子:

[LayoutRenderer("request-guid")]
public class RequestGuidLayoutRenderer:
    LayoutRenderer

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    
        var guid = RequestIdentityService.Current.RequestGuid?.ToString() ?? Constants.NullSession;
        builder.Append(guid);
    

还有一个几乎相同的session-guid 布局渲染器,除了获取SessionGuid 而不是RequestGuid

我的配置部分如下所示,其中 MyAssemblyName 包含布局渲染器:

<nlog autoReload="true">
  <extensions>
    <assembly name="MyAssemblyName" />
  </extensions>
  <variable name="brief" value="$longdate $session-guid $request-guid $level $replace:searchFor=^.*\.([^.]+)$:replaceWith=$1:regex=true:inner=$logger $message$onexception:inner= $exception:format=toString,Data" />
  <variable name="verbose" value="$longdate | $machinename | $processid | $processname | $session-guid $request-guid | $level | $logger | $message$onexception:inner= $exception:format=toString,Data" />
  <targets>
    <target name="all_in" type="File" layout="$verbose" fileName="C:/log/appx/current.txt" archiveFileName="C:/log/appx/archive/#.txt" archiveNumbering="DateAndSequence" archiveAboveSize="10485760" archiveDateFormat="yyyyMMdd" keepFileOpen="false" maxArchiveFiles="100" encoding="iso-8859-2" />
    <target name="LogStreaming"  type="Trace" layout="$verbose" />
  </targets>
  <rules>
    <logger name="*" minlevel="Debug" writeTo="all_in" />
    <logger name="*" minlevel="Error" writeTo="LogStreaming" />
  </rules>
</nlog>

为了确保注册这些布局渲染器,我还在 Application_Start() 的开头为 Web 应用程序注册它们,并在 Main() 或其他应用程序类型的等效项中注册它们。

    public static void Register()
    
        LayoutRenderer.Register<RequestGuidLayoutRenderer>("request-guid");
        LayoutRenderer.Register<SessionGuidLayoutRenderer>("session-guid");

        LogManager.GetCurrentClassLogger().Error($"Registered NLog LayoutRenderers request-guid and session-guid.");
    

对于两个 Web 应用程序来说,这是完美无缺的,但对于第三个应用程序,它不会为这些布局渲染器生成任何输出。内部日志确认它无法找到它们,或者它可能在注册之前尝试使用它们。

Error parsing layout session-guid will be ignored. Exception: System.ArgumentException: LayoutRenderer cannot be found: 'session-guid'
   at NLog.Config.Factory`2.CreateInstance(String itemName)
   at NLog.Layouts.LayoutParser.GetLayoutRenderer(ConfigurationItemFactory configurationItemFactory, String name, Nullable`1 throwConfigExceptions)

Error parsing layout request-guid will be ignored. Exception: System.ArgumentException: LayoutRenderer cannot be found: 'request-guid'
   at NLog.Config.Factory`2.CreateInstance(String itemName)
   at NLog.Layouts.LayoutParser.GetLayoutRenderer(ConfigurationItemFactory configurationItemFactory, String name, Nullable`1 throwConfigExceptions)

我偶然发现,如果我在配置中设置throwConfigExceptions="true",那么它会突然在 Web 应用程序中工作,否则它不会!但为什么?是否有替代方法来修复它,这样我就不必冒着运行时错误的风险,因为日志记录会破坏我们的应用程序?

【问题讨论】:

也许尝试在工作和不工作的应用程序上激活NLog InternalLogger 和internalLogLevel="Debug"。然后比较输出。如果您在比较方面需要帮助,欢迎您使用 2 个日志来 create an issue。 猜你在等功能:github.com/NLog/NLog/issues/3557 【参考方案1】:

由于某种原因,您注册太晚了。

也许有一个静态调用在注册之前解析配置。

注册后可以重新加载配置:

LogManager.Configuration = LogManager.Configuration.Reload();
LogManager.ReconfigExistingLoggers();

【讨论】:

谢谢,似乎可以工作,而且这是有道理的。

以上是关于自定义 NLog 布局渲染器在某些项目中不产生任何输出的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 Java 自定义单元格渲染器在选择行/单元格时不显示突出显示?

Android布局预览器在添加自定义LinearLayout时抛出错误

通过自定义单元格渲染器在Jtable中显示超链接

自定义标签渲染器在 Xamarin iOS 的滚动列表视图中显示错误的文本样式

使用 NLog 事件上下文布局渲染器以毫秒精度记录日期时间

第 n 个子选择器在反应地图渲染功能中不起作用