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);
}
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
.TimeStampfield, so the field will probably just default to the default value for DateTime, which I assume isDateTime.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:Or
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:What is happening here is that the
DateLayoutRendereris getting theTimeStampvalue from theLogEventInfoobject (NLog creates one of these each time you use theLogger.Trace,Logger.Debug,Logger.Info, etc methods. You can also createLogEventInfoobjects yourself and log them with theLogger.Logmethod).By default, when a
LogEventInfoobject is created, itsTimeStampfield is set like this (from the source forLogEventInfohere) (note the use ofCurrentTimeGetter.Now):The
TimeStampfield is set in theLogEventInfoconstructor using theTimeSource.Current.Nowproperty, whose implementation can be seen here.(UPDATE – At some point NLog changed from using
CurrentTimeGetterto a more generic approach of having aTimeSourceobject that has several flavors (one of which,CachedTimeSource, is essentially the same asCurrentTimeGetter)).To save the trouble of navigating the link, here is the source for
CachedTimeSource: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 ofDateTime.Nowretrieved 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.Logmethod to log your messages and you are building theLogEventInfoobjects yourself. By default, if you just new aLogEventInfoobject, the automatic setting of theTimeStampproperty should work fine. It is only dependent onEnvironment.Ticks,DateTime.Now, and the logic that reuses the lastDateTime.Nowvalue, if appropriate.Is it possible that you are creating a
LogEventInfoobject and then setting itsTimeStampproperty toDateTime.MinValue? I ask because the date that is being logged isDateTime.MinValue.The only other explanation that I can think of would be if
Environment.Ticksreturns -1 for some reason. If it did, thenCurrentTimeGetterwould always return the initial value of the lastDateTime private member variable. I can’t imagine a scenario whereEnvironment.Tickswould return -1.