Skip to content

Configure component logging

Rolf Kristensen edited this page Apr 29, 2023 · 10 revisions

The default approach for managing Loggers via the global singleton LogManager class in NLog. It works well for homogeneous applications where the main application and all the extension components are configured via a single configuration file.

By including the component class-namespace in the Logger-name (Happens automatically when using NLog.LogManager.GetCurrentClassLogger()), then it is easy to configure NLog Logging-Rules to route to the wanted destination-target for the plugin (Ex. filename="Plugin-${logger}.log").

Isolated Logger Property

If the component is complex and uses many Logger-instances, then one can consider to also imbue the component Logger-instance with a common LogEvent-PropertyName:

var pluginLogger = NLog.LogManager.GetLogger(componentName).WithProperty("ComponentName", componentName);

Then it is possible to include the component-identifier in the target output. Ex ${event-properties:ComponentName:whenEmpty=Core}

See also ${event-properties}

Isolated LogFactory

But sometimes you want to create a separate logging configuration, just for a particular component, plugin or extension. Instead of using LogManager (which is global to an application) then one can use isolated LogFactory object-instance that is local to your component/plugin. It allows you to have multiple LogFactory-instances, where each have their own isolated logging configuration.

When creating LogFactory you need to explicitly pass the configuration (either from a file or by programmatically constructing targets and rules) as in the following example:

internal class MyLogManager 
{ 
    // A Logger dispenser for the current assembly (Remember to call Flush on application exit)
    public static LogFactory Instance { get { return _instance.Value; } }
    private static Lazy<LogFactory> _instance = new Lazy<LogFactory>(BuildLogFactory);

    // 
    // Use a config file located next to our current assembly dll 
    // eg, if the running assembly is c:\path\to\MyComponent.dll 
    // the config filepath will be c:\path\to\MyComponent.nlog 
    // 
    // WARNING: This will not be appropriate for assemblies in the GAC 
    // 
    private static LogFactory BuildLogFactory()
    {
         // Use name of current assembly to construct NLog config filename 
         Assembly thisAssembly = Assembly.GetExecutingAssembly(); 
         string configFilePath = Path.ChangeExtension(thisAssembly.Location, ".nlog"); 

         LogFactory logFactory = new LogFactory();
         logFactory.Configuration = new XmlLoggingConfiguration(configFilePath, true, logFactory); 
         return logFactory;
    }
}

Then all you need to do is to create loggers with:

Logger logger = MyLogManager.Instance.GetLogger("name");

or

Logger logger = MyLogManager.Instance.GetCurrentClassLogger();

If you want multiple assemblies to share this MyLogManager – just make it a public class and get others to use it.

NLog LogFactory will attempt to automatically shutdown together with the AppDomain / ProcessExit. But it is recommended to shutdown the isolate LogFactory in the plugin-dispose-stage by calling LogFactory.Shutdown().

See Also: Explicit NLog configuration loading

Clone this wiki locally