Robert's blog
Robert Važan

How to write custom NLog time source

A short guide through building custom NLog time sources. We will build a time source with configurable time zone as an example.

NLog 2.1 allows you to define your own custom time source. This is useful when you want to use non-default time zone, time taken from another machine, or a special highly accurate timing hardware. In this post I will guide you through the process of creating your very own time source.

Before implementing your own time source, check out standard time sources provided by NLog that allow you to take time from either DateTime.Now or DateTime.UtcNow and that allow you to optionally cache the retrieved time for 16ms for performance reasons. I've originally created these specialized time sources to deal with time accuracy issues caused by default NLog time source.

All time source implementation in NLog inherit from class TimeSource and implement single inherited property getter Time. I will show you an example of a time source that returns time in specific time zone.

[TimeSource("CustomTimeZone")]
public class CustomTimeZoneTimeSource : TimeSource
{
    string ZoneName;
    TimeZoneInfo ZoneInfo;

    [Required]
    public string Zone
    {
        get { return ZoneName; }
        set
        {
            ZoneName = value;
            ZoneInfo
                = TimeZoneInfo.FindSystemTimeZoneById(value);
        }
    }
    
    public override DateTime Time
    {
        get
        {
            return TimeZoneInfo.ConvertTimeFromUtc(
                DateTime.UtcNow, ZoneInfo);
        }
    }
}

You can then configure your time source with a few lines of code, ideally inserted somewhere in your program's initialization code before any log messages are printed:

TimeSource.Current = new CustomTimeZoneTimeSource()
{
    Zone = "Central Standard Time"
}

You can also configure your new time source directly from NLog XML configuration file:

<nlog>
    <time type='CustomTimeZone' zone='Central Standard Time' />
</nlog>

Note that in order for the XML configuration to work, NLog must be able to find the class that implements the time source. This can be done with a declaration in the XML configuration file itself or it can be done programmatically. The mechanism is common to all NLog extensions. See for example how it is used to create target extension.

If you encounter any trouble implementing your time source, drop me a comment below. Chances are there could be some omissions in this post.

Comments

Hi Robert,

I've implemented your code and I use CEST (Utc +2.00). The dateformat in the logmessage is correct. However NLog doesn't write logs between 10pm and 12pm.
I have a (text) log file per day.
The messages do not appear in the file of the next day. The timezone of the server is also CEST at the moment.
Do you have a clue?

Maaike
Anonymous
This is likely due to the fact that NLog uses local time internally, then converts it to UTC or other time zone. Bad design, really. File logger is cycling files on midnight and it apparently does it in different time zone. Solving this issue would require debugging & fixing in NLog code.
Robert
Thank you, I will look into that.

Maaike
Anonymous
Hello,
I've implemented your code. It works perfectly if I pass configuration at runtime. If I want to write configuration in the config file like:

Visual Studio tell me that "time" is marked as abstract (I think in the xsd file) and the logging doesn't works.

Thank you for any suggestion
Luca
Comments are closed for this post.