如何在运行时使用NLog获取当前目标文件的路径?

Win*_*ter 49 c# nlog

我使用NLog进行下一个配置:

  <targets>
    <target xsi:type="File" name="f" fileName="${basedir}/logs/${shortdate}.log"
            layout="${longdate} ${uppercase:${level}} ${message}" />
  </targets>
  <rules>
    <logger name="*" minlevel="Trace" writeTo="f" />
  </rules>
Run Code Online (Sandbox Code Playgroud)

我试图获得(我检查,集合中只有一个FileTarget)的FileName属性FileTarget

NLog.LogManager.GetCurrentClassLogger().Info("test");
var logFile = (from t in NLog.LogManager.Configuration.AllTargets
                where t is NLog.Targets.FileTarget
                select (NLog.Targets.FileTarget)t).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

但是logFile.FileName只包含文件名的模式,确切地说它是如何在设置中指定的.

如何获取当前日志文件的运行时路径?

Mik*_*ike 62

这对我有用:

var fileTarget = (FileTarget) LogManager.Configuration.FindTargetByName("file");
// Need to set timestamp here if filename uses date. 
// For example - filename="${basedir}/logs/${shortdate}/trace.log"
var logEventInfo = new LogEventInfo {TimeStamp = DateTime.Now}; 
string fileName = fileTarget.FileName.Render(logEventInfo);
if (!File.Exists(fileName))
    throw new Exception("Log file does not exist.");
Run Code Online (Sandbox Code Playgroud)


mar*_*etz 27

即使您已在NLog XML配置中设置async="true"(即您的目标由a包裹AsyncTargetWrapper),此方法也将起作用:

    private string GetLogFileName(string targetName)
    {
        string fileName = null;

        if (LogManager.Configuration != null && LogManager.Configuration.ConfiguredNamedTargets.Count != 0)
        {
            Target target = LogManager.Configuration.FindTargetByName(targetName);
            if (target == null)
            {
                throw new Exception("Could not find target named: " + targetName);
            }

            FileTarget fileTarget = null;
            WrapperTargetBase wrapperTarget = target as WrapperTargetBase;

            // Unwrap the target if necessary.
            if (wrapperTarget == null)
            {
                fileTarget = target as FileTarget;
            }
            else
            {
                fileTarget = wrapperTarget.WrappedTarget as FileTarget;
            }

            if (fileTarget == null)
            {
                throw new Exception("Could not get a FileTarget from " + target.GetType());
            }

            var logEventInfo = new LogEventInfo { TimeStamp = DateTime.Now };
            fileName = fileTarget.FileName.Render(logEventInfo);
        }
        else
        {
            throw new Exception("LogManager contains no Configuration or there are no named targets");
        }

        if (!File.Exists(fileName))
        {
            throw new Exception("File " + fileName + " does not exist");
        }

        return fileName;
    }
Run Code Online (Sandbox Code Playgroud)

  • +1 - 酷 - 渲染部分让我投入曲线球.不确定这是否需要获取文件名,但无论如何.我正在使用异步日志记录,因此您的解决方案帮助了我 - 谢谢! (2认同)

Ski*_*kip 5

目标可以多次包装(在我的例子中,我有一个过滤器),因此以下代码片段是一种更通用的展开方法,适用于多个级别,并且不会对目标名称做出假设。

Target target = LogManager.Configuration.FindTargetByName(targetName);
while ((target != null) && (target is WrapperTargetBase))
{
    target = (target as WrapperTargetBase).WrappedTarget;
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*Jon 5

这里有一些对我有用的简化实现——至少对于较新版本的.Net/NLog。

如果您只有一个 FileTarget 并且没有任何异步环绕它并且只想要一个简单的文件名:

var file = LogManager.Configuration?.AllTargets.OfType<FileTarget>()
    .Select(x => x.FileName.Render(LogEventInfo.CreateNullEvent()))
    .FirstOrDefault(x => !string.IsNullOrWhiteSpace(x));
Console.WriteLine($"Logging to file: {file}");
Run Code Online (Sandbox Code Playgroud)

输出:

记录到文件:C:\MyApp\logs\2022-05-04.log

或者,这里还有一个方法可以解包异步和缓冲目标:

public static IEnumerable<string> GetNLogFileTargets()
{
    var allTargets = LogManager.Configuration?.AllTargets;
    if (allTargets == null)
    {
        return Enumerable.Empty<string>();
    }

    var wrappedFileTargets = allTargets.OfType<WrapperTargetBase>()
        .Where(x => x.WrappedTarget is FileTarget)
        .Select(x => x.WrappedTarget).Cast<FileTarget>();
    var fileTargets = allTargets.OfType<FileTarget>().Concat(wrappedFileTargets);
    return fileTargets.Select(x => x.FileName.Render(LogEventInfo.CreateNullEvent())).Where(x => !string.IsNullOrWhiteSpace(x));
}
Run Code Online (Sandbox Code Playgroud)