gpt4 book ai didi

date - 为什么nlog不能读取当前日期

转载 作者:行者123 更新时间:2023-12-01 11:49:06 26 4
gpt4 key购买 nike

我正在使用 Nlog 将一些日志记录写入文本文件。部分 nlog.config:

 <target name="file" xsi:type="File" fileName="${basedir}/MBWRunner_log.txt"
layout="${date} (${level}): ${message}
Exception: ${exception:format=Method, ToString}"/>

日志文件中的行如下所示:

0001-01-01 00:00:00 (Trace): MBWRunner started

如您所见,日期和时间均为 0。我测试了 {longdate} 和 {date:format=yyyyMMddHHmmss},结果相同。

该应用程序是一个控制台应用程序,从提升的命令行运行。

有什么线索吗?

[编辑] 我已经在组织内的 2 台机器上对此进行了测试,结果相同。请帮忙!

使用的代码:

  static Logger _logger = LogManager.GetCurrentClassLogger();

public static void Log(string message, LogLevel priority)
{
LogEventInfo eventinfo = new LogEventInfo(); ;
eventinfo.Message = message;
eventinfo.Level = priority;
Log(eventinfo);
}

static void Log(LogEventInfo logentry)
{
_logger.Log(logentry);
}

最佳答案

更新:

@edosoft 我认为问题在于您使用了 LogEventInfo 的默认构造函数。如果您在此处查看 LogEventInfo 的源代码

https://github.com/NLog/NLog/blob/master/src/NLog/LogEventInfo.cs

您会看到使用默认构造函数不会填充 .TimeStamp 字段,因此该字段可能只是默认为 DateTime 的默认值,我假设是 DateTime.MinValue 。您应该使用其他构造函数之一或 Create 方法之一。由于您只设置 Message 和 Level 字段,我建议:

var logEvent = new LogEventInfo(priority, "", message); //Second param is logger name.

或者

var logEvent = LogEventInfo.Create(priority, "", message);

DateLayoutRenderer 的 NLog 源代码(来自 here )我们可以看到作为日志流的一部分写入的日期值是这样计算的:

    protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
var ts = logEvent.TimeStamp;
if (this.UniversalTime)
{
ts = ts.ToUniversalTime();
}

builder.Append(ts.ToString(this.Format, this.Culture));
}

这里发生的是 DateLayoutRendererLogEventInfo 对象中获取 TimeStamp 值(NLog 会在您每次创建其中一个使用Logger.Trace, Logger.Debug, Logger.Info等方法,也可以创建LogEventInfo对象并使用 Logger.Log 方法记录它们。

默认情况下,当 LogEventInfo 对象被创建时,它的 TimeStamp 字段设置如下(来自 LogEventInfo 的来源 here )(注意 CurrentTimeGetter.Now 的使用):

    public LogEventInfo(LogLevel level, string loggerName, IFormatProvider formatProvider, [Localizable(false)] string message, object[] parameters, Exception exception)
{
this.TimeStamp = CurrentTimeGetter.Now;
this.Level = level;
this.LoggerName = loggerName;
this.Message = message;
this.Parameters = parameters;
this.FormatProvider = formatProvider;
this.Exception = exception;
this.SequenceID = Interlocked.Increment(ref globalSequenceId);

if (NeedToPreformatMessage(parameters))
{
this.CalcFormattedMessage();
}
}

TimeStamp 字段是在 LogEventInfo 构造函数中使用 TimeSource.Current.Now 属性设置的,其实现可见 here .

(更新 - 在某些时候,NLog 从使用 CurrentTimeGetter 更改为使用具有多种风格的 TimeSource 对象的更通用的方法(其中之一, CachedTimeSource,本质上与CurrentTimeGetter))相同。

为了省去导航链接的麻烦,这里是 CachedTimeSource 的源代码:

public abstract class CachedTimeSource : TimeSource
{
private int lastTicks = -1;
private DateTime lastTime = DateTime.MinValue;

/// <summary>
/// Gets raw uncached time from derived time source.
/// </summary>
protected abstract DateTime FreshTime { get; }

/// <summary>
/// Gets current time cached for one system tick (15.6 milliseconds).
/// </summary>
public override DateTime Time
{
get
{
int tickCount = Environment.TickCount;
if (tickCount == lastTicks)
return lastTime;
else
{
DateTime time = FreshTime;
lastTicks = tickCount;
lastTime = time;
return time;
}
}
}
}

此类的目的是使用相对便宜的操作 (Environment.Ticks) 来限制对相对昂贵的操作 (DateTime.Now) 的访问。如果 Ticks 的值在调用之间没有变化(从一个记录的消息到下一个),则此时检索到的 DateTime.Now 的值将与 DateTime 的值相同。这次现在检索,所以只使用最后检索的值。

所有这些代码都在运行(并且日期/时间日志记录显然适用于大多数其他人),对您的问题的一种可能解释是您正在使用 Logger.Log 方法来记录您的消息,并且您正在自己构建 LogEventInfo 对象。默认情况下,如果您只是新建一个 LogEventInfo 对象,TimeStamp 属性的自动设置应该可以正常工作。它仅依赖于 Environment.TicksDateTime.Now 和重用最后一个 DateTime.Now 值的逻辑(如果适用)。

是否有可能您正在创建一个 LogEventInfo 对象,然后将其 TimeStamp 属性设置为 DateTime.MinValue?我问是因为记录的日期是 DateTime.MinValue

我能想到的唯一其他解释是 Environment.Ticks 出于某种原因返回 -1。如果是,则 CurrentTimeGetter 将始终返回 lastDateTime 私有(private)成员变量的初始值。我无法想象 Environment.Ticks 会返回 -1 的场景。

关于date - 为什么nlog不能读取当前日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13344430/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com