NLog and Common.Logging nightmare

10,612

Solution 1

Okay, so after all the fixes above I had to also update the Common.Logging package to v2.2.0.0 and then update the binding redirects manually. This is really a sub-optimal deployment of the Common.Logging.NLog20 nuget package. You shouldn't have to do this.

Solution 2

Common.Logging.NLog20 - Version 2.2.0.0

Common.Logging - version 2.2.0.0

NLog - Version 2.1.0.0

Config looks like:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <configSections>
        <sectionGroup name="common">
            <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
        </sectionGroup>
        <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog" />
    </configSections>
    <common>
        <logging>
            <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
                <arg key="configType" value="INLINE" />
            </factoryAdapter>
        </logging>
    </common>
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          internalLogFile="nlog.ERRORS.txt" internalLogLevel="Error">

        <!-- 
          See http://nlog-project.org/wiki/Configuration_file 
          for information on customizing logging rules and outputs.
        -->
        <targets>
            <!-- add your targets here -->
            <target xsi:type="File" name="log" keepFileOpen="true"
                    fileName="${basedir}/log_${date:format=yyyyMMdd}.txt"
                    layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring}" />
            <target name="log_errors_memory" xsi:type="Memory"
                    layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring}" />
            <target name="log_all_memory" xsi:type="Memory"
                    layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring}" />
        </targets>

        <rules>
            <!-- add your logging rules here -->
            <logger name="*" minlevel="Trace" writeTo="log" />
            <logger name="*" minlevel="Trace" writeTo="log_all_memory" />
            <logger name="*" minlevel="Error" writeTo="log_errors_memory" />
        </rules>
    </nlog>
   </value>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-2.2.0.0" newVersion="2.2.0.0" />
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
</configuration>

Solution 3

Here's an underhanded approach that will save you a lot of hassle. The adapter that ships with Common.Logging.NLogXX, NLogLoggerFactoryAdapter, does nothing special but setup up NLog for you. This is something that most people can do on their own.

In other words, if you've already setup NLog all you need to do is hookup Common.Logging to NLog. This can be done by writing a simple factory that will create NLog Loggers like this:

public class MyAdapter : AbstractCachingLoggerFactoryAdapter
{
    protected override ILog CreateLogger(string name)
    {
        return (ILog)typeof(NLogLogger).GetConstructor(
            BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(NLog.Logger) }, null)
            .Invoke(new object[] { NLog.LogManager.GetLogger(name) });
    }
}

public static void ConfigureLogging()
{
    Common.Logging.LogManager.Adapter = new MyAdapter();
}
Share:
10,612

Related videos on Youtube

Bitfiddler
Author by

Bitfiddler

Updated on June 04, 2022

Comments

  • Bitfiddler
    Bitfiddler almost 2 years

    So I have tried everything I can find to get these two to play together.

    I have installed the nuget package Common.Logging.NLog20,

    My config looks like:

    <configSections>
        <sectionGroup name="common">
            <section name="logging" type="Common.Logging.ConfigurationSectionHandler, Common.Logging" />
        </sectionGroup>
        <section name="nlog" type="NLog.Config.ConfigSectionHandler, NLog20" />
    </configSections>
    <common>
        <logging>
            <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20">
                <arg key="configType" value="INLINE" />
            </factoryAdapter>
        </logging>
    </common>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <dependentAssembly>
                <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-2.1.0.0" newVersion="2.1.0.0" />
            </dependentAssembly>
            <dependentAssembly>
                <assemblyIdentity name="Common.Logging" publicKeyToken="af08829b84f0328e" culture="neutral" />
                <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
            </dependentAssembly>
        </assemblyBinding>
    </runtime>
    

    I am using the nuget NLog.Configuration package so my nlog config is in a separate file called NLog.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      internalLogFile="nlog.ERRORS.txt" internalLogLevel="Error" >
    
    <!-- 
    See http://nlog-project.org/wiki/Configuration_file 
    for information on customizing logging rules and outputs.
    -->
    <targets>
        <!-- add your targets here -->
        <target xsi:type="File" name="log" keepFileOpen="true"
                fileName="${basedir}/log_${date:format=yyyyMMdd}.txt"
                layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring}" />
        <target name="log_errors_memory" xsi:type="Memory"
                layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring}" />
        <target name="log_all_memory" xsi:type="Memory"
                layout="${longdate} ${level:uppercase=true:padding=5} - ${logger:shortName=true} - ${message} ${exception:format=tostring}" />
    </targets>
    
    <rules>
        <!-- add your logging rules here -->
        <logger name="*" minlevel="Trace" writeTo="log" />
        <logger name="*" minlevel="Trace" writeTo="log_all_memory" />
        <logger name="*" minlevel="Error" writeTo="log_errors_memory" />
    </rules>
    </nlog>
    

    I have tried changing the FactoryAdaptor to NLog, NLog2 and NLog20, I have tried changing the binding redirect, I have tried updating the Common.Logging to version 2.2.0.0. No matter what I do I get the exception:

    {"Failed obtaining configuration for Common.Logging from configuration section 'common/logging'."}
    
    Inner Exception:
    {"An error occurred creating the configuration section handler for common/logging: Type Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog20, Version=2.2.0.0, Culture=neutral, PublicKeyToken=af08829b84f0328e does not implement Common.Logging.ILoggerFactoryAdapter\r\nParameter name: factoryAdapterType\r\nActual value was Common.Logging.NLog.NLogLoggerFactoryAdapter. (D:\\Development\\Code\\DotNet\\vs2013\\exe\\CommandLine\\PSVImporter\\FidessaPSVImport.Test\\bin\\Debug\\FidessaPSVImport.Test.dll.config line 17)"}
    

    What am I missing? This shouldn't be this hard to get working.

    • Bitfiddler
      Bitfiddler almost 10 years
      Too much pain for too little gain. Created my own simple abstraction. Goodby Common.Logging.
    • Bitfiddler
      Bitfiddler almost 10 years
      So I noticed that my nlog configSection had NLog20 instead of NLog, fixed that, no dice. Also, the factory property said inline so I removed the NLog.config file and put the nlog section into the appconfig. Still no luck.
    • JamesQMurphy
      JamesQMurphy over 7 years
      Late to the party, but for anyone else landing here: The <arg key="configType" value="INLINE" /> entry is only if your NLog configuration is in the same file! If your NLog configuration is in a separate file (like NLog.config), then you need to specify <arg key="configType" value="FILE" /> and also specify the filename. See the docs
  • Cheese Widget
    Cheese Widget almost 10 years
    I did everything you suggested and I'm still getting the same error
  • Bitfiddler
    Bitfiddler almost 10 years
    Unfortunately I'm not an nLog/Common.Logging guru so everything above is all I have to offer. All I can suggest is to double check to make sure your config file has no typing errors in it. I'll post all my versions in another answer for you and a fragment of my config. It works for me so it should work for you.
  • Bitfiddler
    Bitfiddler almost 10 years
    The only other thing I can think of is permission problems (as in you don't have access to your app.config file). But if you are getting this error in debugging, I don't see how that could happen.
  • Llyle
    Llyle over 9 years
    This worked for me. Common Logging is in a state of ruin. Now I'm taking a dependency on NLog, because the log4net story doesn't work. Dependency hell... this is insane! @BitFiddler Thanks for the share.