Why can't nlog read the current date

二次信任 提交于 2019-12-10 20:49:28

问题


I'm using Nlog to write some logging to a textfile. Partial nlog.config:

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

Lines in the logfile look like this:

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

As you can see the date and time are all 0. I have tested {longdate} and {date:format=yyyyMMddHHmmss} with the same result.

The application is a console app, run from an elevated commandline.

Any clues?

[EDIT] I have tested this on 2 machine's within the organisation with the same result. Please help!

Code used:

  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);
}

回答1:


UPDATE:

@edosoft I think the problem is your use of the default constructor for LogEventInfo. If you look at the source for LogEventInfo here

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

You will see that using the default constructor does not populate the .TimeStamp field, so the field will probably just default to the default value for DateTime, which I assume is DateTime.MinValue. You should use one of the other constructors or one of the Create methods. Since you are setting only the Message and Level fields, I would suggest either:

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

Or

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

From the NLog source for DateLayoutRenderer (from here) we can see that the date value that gets written as part of the logging stream is calculated like this:

    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));
    }

What is happening here is that the DateLayoutRenderer is getting the TimeStamp value from the LogEventInfo object (NLog creates one of these each time you use the Logger.Trace, Logger.Debug, Logger.Info, etc methods. You can also create LogEventInfo objects yourself and log them with the Logger.Log method).

By default, when a LogEventInfo object is created, its TimeStamp field is set like this (from the source for LogEventInfo here) (note the use of 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();
        }
    }

The TimeStamp field is set in the LogEventInfo constructor using the TimeSource.Current.Now property, whose implementation can be seen here.

(UPDATE - At some point NLog changed from using CurrentTimeGetter to a more generic approach of having a TimeSource object that has several flavors (one of which, CachedTimeSource, is essentially the same as CurrentTimeGetter)).

To save the trouble of navigating the link, here is the source for 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;
            }
        }
    }
}

The purpose of this class is to use a relatively cheap operation (Environment.Ticks) to limit access to a relatively expensive operation (DateTime.Now). If the value of Ticks does not change from call to call (from one logged message to the next), then the value of DateTime.Now retrieved the this time will be the same as the value of DateTime.Now retrieved this time, so just use the last retrieved value.

With all of this code in play (and with Date/Time logging apparently working for most other people), one possible explanation of your problem is that you are using the Logger.Log method to log your messages and you are building the LogEventInfo objects yourself. By default, if you just new a LogEventInfo object, the automatic setting of the TimeStamp property should work fine. It is only dependent on Environment.Ticks, DateTime.Now, and the logic that reuses the last DateTime.Now value, if appropriate.

Is it possible that you are creating a LogEventInfo object and then setting its TimeStamp property to DateTime.MinValue? I ask because the date that is being logged is DateTime.MinValue.

The only other explanation that I can think of would be if Environment.Ticks returns -1 for some reason. If it did, then CurrentTimeGetter would always return the initial value of the lastDateTime private member variable. I can't imagine a scenario where Environment.Ticks would return -1.



来源:https://stackoverflow.com/questions/13344430/why-cant-nlog-read-the-current-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!