NLog: Generate configurations at runtime from template

Refresh

April 2019

Views

27 time

1

I'm trying to generate targets & logger at runtime, based on another target. Let's assume that I have a functionnal Foo logger: I'd like to generate separate rules for Foo.1, Foo.2, etc etc, but I can't know what will be the last logger I'll have to create (thus, I can't define them declaratively).

So far, I did something like this:

public GetNewClonedLogger(int fooId)
{
    var config = NLog.LogManager.Configuration;
    var newFooName = $"Foo.{fooId}";
    FileTarget baseTarget = NLog.LogManager.Configuration.FindTargetByName<FileTarget>("Foo");

    // Copy the base target
    var newTarget = new FileTarget(newFooName)
    {
        Layout = baseTarget.Layout,
        CreateDirs = true,
        FileName = baseTarget .FileName.ToString().Replace("${var:filename}", newFooName),
        ArchiveAboveSize = baseTarget.ArchiveAboveSize,
        BufferSize = baseTarget.BufferSize,
        ArchiveFileName = baseTarget.ArchiveFileName,
        MaxArchiveFiles = baseTarget.MaxArchiveFiles,
        ArchiveDateFormat = baseTarget.ArchiveDateFormat,
        ArchiveEvery = baseTarget.ArchiveEvery,
        FileAttributes = baseTarget.FileAttributes,
        KeepFileOpen = baseTarget.KeepFileOpen,
        ArchiveNumbering = baseTarget.ArchiveNumbering,
    };

    // Add configs & flush
    NLog.LogManager.Configuration.AddTarget(newTarget);
    NLog.LogManager.Configuration.AddRuleForAllLevels(newTarget, newFooName);

    // I tried every combinations of the following, without success
    NLog.LogManager.ReconfigExistingLoggers();
    NLog.LogManager.Configuration = config;
    NLog.LogManager.Configuration.Reload();

    NLog.LogManager.GetLogger(newFooName);
}

This function returns a logger, that seems OK on every points: the target name is OK, the filename is OK, the NLog.LogManager.Configuration has a new rule with the correct name (Foo.1, Foo.2, ...), and so are AllTargets. But when I log using the returned logger, no file is created, and it is exacly like nothing happened at all....

I've tried the solution proposed in this thread, without success.... What am I missing?

Thanks for your help!

1 answers

1

Actually, this was a really silly error, as this may work as I expected. The problem was that baseTarget.FileName is a Layout object, and the stringification using .ToString() made bad conversions, by adding quotes to the output ('C:\...'). Thus, NLog threw errors, that were partially silented by NLog config & quite hard to understand anyway. I fixed it by checking if baseTarget.FileName is a SimpleLayout (the only class I had to handle in my case), then retrieve the OriginalText out from that layout. Then, it worked like a charm.