4

如果 d: 存在,是否可以将 NLog 配置为将日志写入 d:\logs,如果 d: 不存在,则改为登录到 c:\logs?

4

2 回答 2

4

我认为您可以结合使用自定义 LayoutRenderer 和 XML 配置来做到这一点。在 XML 配置中,您可以使用 LayoutRenderers 来指定文件名。例如:

<target name="logfile" xsi:type="File" fileName="${basedir}/${shortdate}.log" />

FileTarget 对象将根据${basedir}${shortdate}布局渲染器的值创建一个文件。

您可以轻松编写自定义 LayoutRenderer,也许将其称为“FindAvailableDrive”,并像这样配置它:

<target name="logfile" xsi:type="File" fileName="${FindAvailableDrive}/logs/${shortdate}.log" />

FindAvailableDrive LayoutRender 可以以驱动器号开头,例如“C:”​​,然后更改直到找到有效的驱动器。为了更进一步,FindAvailableDrive 可以采用一个或多个参数来帮助定义如何搜索有效驱动器:

<target name="logfile" xsi:type="File" fileName="${FindAvailableDrive:Drives=DC}/logs/${shortdate}.log" />

在这种情况下,FindAvailableDrive 将检查驱动器 D,然后检查驱动器 C。

这是一个示例(未经测试),说明如何编写这样的 LayoutRenderer(请注意,这是基于我针对 NLog 1.0 编写的现有 LayoutRender,因此其中一些对于 NLog 2.0 可能不是必需的(或有效的)):

  [LayoutRenderer("FindAvailableDrive")]
  class FindAvailableDriveLayoutRenderer : LayoutRenderer
  {
    private string validDrive;

    [DefaultParameter]
    public string DriveCandidates { get; set; }

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
    {
      builder.Append(FindValidDrive());
    }

    protected override int GetEstimatedBufferSize(LogEventInfo logEvent)
    {
      return 2;
    }

    private string FindValidDrive()
    {
      if (!String.IsNullOrEmpty(validDrive)) return validDrive;

      if (String.IsNullOrEmpty(DriveCandidates))
      {
        if (Directory.Exists("C:"))
          validDrive = "C:";
        else
        if (Directory.Exists("D:"))
          validDrive = "D:";
        //And so on if you want to continue to check for valid drives.
        return validDrive;
      }

      validDrive = DriveCandidates.Select(c => string.Format("{0}:", c).Where(d => Directory.Exists(d)).FirstOrDefault();

      //What to do if no drives exists?

      return validDrive;
    }
  }

您可以在此处查看我对另一个问题的回答,了解有关如何在 NLog 中编写和使用自定义 LayoutRenderer 的更多信息。

于 2012-11-16T15:53:25.527 回答
0

是的,这是可能的,但不是在 xml 配置中:做这样的事情,你的程序被加载:vb.net 代码:

    Dim mt As NLog.Targets.FileTarget= Nothing
    For Each Target In LogManager.Configuration.AllTargets
        If Target.Name Like "YourTargetNameIntheXML" Then
            mt = DirectCast(Target, NLog.Targets.FileTarget)
        End If
    Next

if isnothing(mt)=false then
        mt.FileName="YourPath"
Check here if the drive exists, if not, change the path to your liking.
End If

您可能需要重新加载配置:Logger.Factory.Configuration.Reload()

也许这行不通,您可以尝试在代码中构建一个新的文件目标并将其添加到 nlog。以下是 Memorytarget 的示例:

Dim ThisLog As New MemoryTarget

ThisLog.Name = "PPTXLOG"
ThisLog.Layout = "${threadid} | ${time} | ${level:uppercase=true} | ${logger} | ${message} | ${exception}"


Logger.Factory.Configuration.AddTarget("PPTXLOG", ThisLog)
'the Logrule is needed to "route" the logs to your new target

    Dim LogRule As New LoggingRule("*", LogLevel, ThisLog)

    Logger.Factory.Configuration.LoggingRules.Add(LogRule)
    Logger.Factory.Configuration.Reload()
于 2012-11-15T08:06:12.700 回答