c# - NLog - 文件目标文件名的参数

标签 c# nlog

我在 .NET 应用程序中使用 NLog。目前,我的 App.config 中的配置部分如下所示:

<nlog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <targets>
    <target name="assemblyLogFile" xsi:type="File" fileName="${basedir}/logs/${shortdate}/assembly.log" createDirs="true" keepFileOpen="true" encoding="utf-8" layout="${longdate} ${message}${exception:format=ToString}"></target>
    <target name="appLogFile" xsi:type="File" fileName="${basedir}/logs/app.log" createDirs="true" keepFileOpen="true" encoding="utf-8" layout="${longdate} ${message}${exception:format=ToString}"></target>
  </targets>

  <rules>
    <logger name="Assembly" minlevel="Trace" writeTo="assemblyLogFile" />
    <logger name="*" minlevel="Trace" writeTo="appLogFile" />
  </rules>
</nlog>

我的应用程序正在动态加载程序集。我想将每个程序集日志记录到自己的文件中。本质上,我想将 target 元素上的 filename 属性更新为如下所示:

fileName="${basedir}/logs/${shortdate}/assembly.[Name].log"

在此模式中,“[Name]”在代码中定义。我的问题是,有没有办法通过 NLog 以编程方式将变量传递到目标?如果是这样,怎么办?

最佳答案

如果您希望这是完全动态的,我认为您有两种方法。

1) 为 NLog.ILogger 创建一个自定义日志工厂和包装器,用于跟踪程序集名称并将其注入(inject)到 NLog logEvent 中。这意味着所有程序集都必须使用您的记录器工厂,而不是直接使用 NLog。

2) 创建一个 NLog 扩展,让您可以将程序集名称作为从记录器名称派生的布局变量进行访问。如果您在所有程序集中使用默认的 LogManager.GetCurrentClassLogger(),则此方法有效。

这是一个简单的缓存渲染器,它使用反射来查找正确的程序集。您可以通过在加载程序集时扫描程序集来提高效率 - 或者可能只是对记录器名称进行字符串整理。

[NLog.LayoutRenderers.LayoutRenderer("assemblyName")]
public class AssemblyNameLayoutRenderer : NLog.LayoutRenderers.LayoutRenderer
{
    static ConcurrentDictionary<string, string> loggerNameToAssemblyNameCache = new ConcurrentDictionary<string, string>();

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
        var fullClassName = logEvent.LoggerName;
        var assemblyName = FindAssemblyNameFromClassName(fullClassName);

        if (!string.IsNullOrEmpty(assemblyName))
            builder.Append(assemblyName);
    }

    private string FindAssemblyNameFromClassName(string fullClassName)
    {
        return loggerNameToAssemblyNameCache.GetOrAdd(fullClassName, cl =>
        {
            var klass = (
                from a in AppDomain.CurrentDomain.GetAssemblies()
                from t in a.GetTypes()
                where t.FullName == fullClassName
                select t).FirstOrDefault();

            return klass?.Assembly.GetName().Name;
        });
    }
}

然后在配置文件中使用它,如下所示:

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

<targets>
  <target xsi:type="FilteringWrapper" name="assemblyLogFile" condition="'${assemblyName}' != ''">
    <target name="realAssemblyLogFile" xsi:type="File" fileName="logs/${shortdate}/assembly.${assemblyName}.log" createDirs="true" keepFileOpen="true" encoding="utf-8" layout="${longdate} ${message}${exception:format=ToString}" /
  </target>  
</targets>

关于c# - NLog - 文件目标文件名的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49986060/

相关文章:

c# - 更改 FirstPersonController MouseLook 灵敏度

c# - 即使焦点更改后键盘也不会消失

c# - NLog 使用 WCF C#.NET 将对象写入数据库

c# - 在 C# 中编码(marshal)带有指针参数的方法指针

c# - 在 C# 中将 RichTextFormat 信息转换为 HTML 的最佳解决方案是什么?

c# - 如何实现实现另一个接口(interface)的通用接口(interface)?

azure - NLog 自定义目标在 Azure .NET Core 2.1 中失败

c# - 记录异常属性

asp.net-mvc - NLog上的配置转换不起作用

logging - 如何使用nlog写入关键级别的事件日志?