How to use NLog for a DLL

21,832

Solution 1

you have to add the nlog.config to the location of the exe file that uses the dll!

Edit: You don't have to modify the exe file just place the nlog.config in the same directory, if that is no option i guess you will have to configure it from code https://github.com/nlog/NLog/wiki/Configuration-API

Solution 2

NLog will look for a configuration file from the exe that includes your DLL. So you will need to copy a configuration file for NLog everytime you want to use your DLL.

In theory, this is the correct design pattern as many third party applications can use your DLL in different ways and would like to have your DLL's logs centralized with their logs.

In my case (and maybe your), we wanted to make sure 100% that the logs of the DLL are saved using our own configuration file, to make sure that all fatal errors are reported to our SqlServer etc. Hence we don't want the third party application to set its own logging logic.

We had the same issue where NLog (or Log4Net) couldn't find the configuration file, thus no logging activity was started and no exception / error message was printed from NLog or Log4Net.

The only alternative is to configure NLog (or Log4Net) in your DLL using code. NLog provides you with a Configuration API so that you can ditch the configuration files. See NLog configuration API

In my case, I have a static class called 'Utils' in my DLL, which is called from any third-party class that uses my DLL (e.g. they do Utils.doSomething()). So I configure NLog in a static constructor:

static Utils() // static constructor
{
    // Step 1. Create configuration object 
    var config = new LoggingConfiguration();

    // Step 2. Create targets and add them to the configuration 
    var consoleTarget = new ColoredConsoleTarget();
    config.AddTarget("console", consoleTarget);

    var fileTarget = new FileTarget();
    config.AddTarget("file", fileTarget);

    // Step 3. Set target properties 
    consoleTarget.Layout = @"${date:format=HH\:mm\:ss} ${logger} ${message}";
    fileTarget.FileName = @"C:\global-logs\logs.txt";
    fileTarget.Layout = "${message}";
    // Step 4. Define rules
    var rule1 = new LoggingRule("*", LogLevel.Debug, consoleTarget);
    config.LoggingRules.Add(rule1);

    var rule2 = new LoggingRule("*", LogLevel.Debug, fileTarget);
    config.LoggingRules.Add(rule2);

    // Step 5. Activate the configuration
    LogManager.Configuration = config; 
}

Solution 3

you should put the piece of configuration file as above in the web.config for web applications or in the app.config for windows applications. This is not done automatically and if your class library has an app.config this is anyway not used when the class library gets called by another application.

Share:
21,832
Oysio
Author by

Oysio

Updated on July 10, 2022

Comments

  • Oysio
    Oysio almost 2 years

    I am trying to implement a simple log using Nlog Refresh 1.0 for a class Library project. It seems nlog does not create a logfile when it's instantiated from within a dll.

    Is there some other way around this ?

    my config file looks like this:

    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          throwExceptions="true">
    
        <targets>
          <target name="file" xsi:type="File" fileName="${basedir}/nlog.txt" />
            <target name="console" xsi:type="Console" />
        </targets>
    
        <rules>
            <logger name="*" minlevel="Info" writeTo="file" />
            <logger name="*" minlevel="Info" writeTo="console" />
        </rules>
    
    </nlog>
    

    I know there is nothing wrong with this config because it works from within an exe project.

    Edit: just to clarify: I have no access to the calling program which uses my dll as a plugin. The calling program is in fact outlook which uses my dll as a plugin. I would want to keep a log which is only relevant to my dll and has nothing to do with outlook itself.