Thomas
Thomas

Reputation: 12117

Redirect all ASP.NET Core logging into a single NLog logger

I have an ASP.NET project that sends its logs to NLog.

However in this project, I have my own NLog logger and I would like to know how to route all the logs through it.

I guess I shouldn't add NLog as a logger, but I should find a way to register a method that will get called each time ASP tries to log anything.

How can this be accomplished?


This is the code that creates the logger:

        // create the module name
        var ProcessName = Process.GetCurrentProcess().ProcessName;
        _ModuleName = ProcessName  + " (\"" + Oracle.GuessMyName() + "\")";

        // create the logger configuration
        var Configuration = new LoggingConfiguration();

        // create the file target
        var FileTarget = new FileTarget ("file")
        {
            FileName            = @"x:\Logs\${processname}.log",
            ArchiveFileName     = @"x:\Logs\${processname}.{#}.log",
            Layout              = @"${longdate}|${logger}|${level}|${message}${onexception:|Exception occurred:${exception:format=tostring}${newline}",
            ArchiveEvery        = FileArchivePeriod.Day,
            ArchiveNumbering    = ArchiveNumberingMode.Rolling,
            MaxArchiveFiles     = 7,
            ConcurrentWrites    = true
        };

        Configuration.AddTarget(FileTarget);


        // create the viewer target
        var ViewerTarget = new NLogViewerTarget ("viewer")
        {
            Layout              = @"${message}${onexception:${newline} --> Exception occurred\:${exception:format=tostring}",
            IncludeSourceInfo   = true,
            IncludeCallSite     = true,
            Address             = @"udp://127.0.0.1:9999"
        };

        Configuration.AddTarget(ViewerTarget);

        // set the rules
        Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, FileTarget));
        Configuration.LoggingRules.Add(new LoggingRule("*", LogLevel.Info, ViewerTarget));

        // set the configuration
        LogManager.Configuration = Configuration;

        // create a new logger
        _Logger = LogManager.GetLogger(_ModuleName);

and this is also how ASP.net gets attached to nlog:

        LoggerFactory.AddNLog();
        Application.AddNLogWeb();

Now the current log layout looks like this for two process (the animal names are automatically changing every time the process is restarted) log layout

so both process: shinobi and mouserun here have their own log output, but anything ASP related goes to ASP's nlog instance called Microsoft, regardless of the process.

the goal is to have the ASP output of shinobi to go in the shinobi logger and the mouserun ASP output to go in the mouserun logger.

Upvotes: 0

Views: 2456

Answers (3)

Rolf Kristensen
Rolf Kristensen

Reputation: 19867

Look at the code of NLog.Extensions.Logging, where it injects its own custom log-provider.

You can do the same and just wrap your global-logger object:

https://github.com/NLog/NLog.Extensions.Logging/blob/e48d6cc54d9abd70d976066265c7992117cbac5a/src/NLog.Extensions.Logging/NLogLoggerProvider.cs

https://github.com/NLog/NLog.Extensions.Logging/blob/1474ffe5b26d2ac95534ed01ef259133133bfb67/src/NLog.Extensions.Logging/NLogLoggerFactory.cs

https://github.com/NLog/NLog.Extensions.Logging/blob/2c05a4fbdda0fe026e60814d535e164e18786aef/src/NLog.Extensions.Logging/ConfigureExtensions.cs

    public static ILoggerFactory AddNLog(this ILoggerFactory factory, NLogProviderOptions options)
    {
        ConfigureHiddenAssemblies();

        using (var provider = new NLogLoggerProvider(options))
        {
            factory.AddProvider(provider);
        }
        return factory;
    }

Upvotes: 1

Rolf Kristensen
Rolf Kristensen

Reputation: 19867

Alternative you can create a custom target wrapper, that fixes the Logger on LogEventInfo's, so when forwarded to the wrapped target (UDP- / File-target), then it looks like they are all come from the same logger.

Similar to what this guy is trying to do:

https://github.com/NLog/NLog/issues/2352

Again really ugly solution, and should only be used when not able to figure out, how to avoid using the logger-name in the configuration of the wanted Nlog-targets (Ex. configure file-target-filename using something else).

Upvotes: 0

Rolf Kristensen
Rolf Kristensen

Reputation: 19867

You could also create a custom-target, and redirect all non-global-logger messages to this target using NLog rules:

https://github.com/nlog/NLog/wiki/Configuration-file#rules

The custom target can then just forward the log-event to the global-logger:

https://github.com/NLog/NLog/wiki/How-to-write-a-custom-target

You should be careful with cyclic logging. Maybe have a filter in the custom-target to ignore messages from the global-logger.

But I think this is an ugly solution, and I fail to understand the restriction of only one logger-object. Especially when the reason is because it should be named after the application. Why not not a global variable for the name instead of abusing the logger-name?

Upvotes: 0

Related Questions