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.