0

In our organization, each customer has their own database, with a respective logging table. How can I configure NLog programmatically so that I can point it at the correct database per customer?

Something like:

var loggerA = LogManager.GetLogger("CustomerA");
loggerA.Log("Customer A Record");
//Outputs to DatabaseA

LogManager.GetLogger("CustomerB");
loggerB.Log("Customer B Record");
//Outputs to DatabaseB

Additionally, we're trying to configure this using Common.Logging, if that is relevant.

We currently have the following that we're going to try to adapt:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using NLog.Config;
using NLog;
using NLog.Targets;

namespace Internal.Logging
{
    public static class LoggingManager
    {
        public static void ConfigureLogging(string databaseTargetConnectionString = null)
        {
            ConfigureCommonLogging();
            ConfigureAdapter(databaseTargetConnectionString);
        }

        private static void ConfigureAdapter(string databaseTargetConnectionString)
        {
            // Step 1. Create configuration object 
            var config = new LoggingConfiguration();

            // Step 2. Create targets and add them to the configuration
            var debuggerTarget = new DebuggerTarget();
            config.AddTarget("console", debuggerTarget);
            var fileTarget = new FileTarget();
            config.AddTarget("file", fileTarget);

            if (!string.IsNullOrEmpty(databaseTargetConnectionString))
            {
                var databaseTarget = new DatabaseTarget();
                databaseTarget.ConnectionString = databaseTargetConnectionString;
                config.AddTarget("database", databaseTarget);
            }

            // Step 3. Set target properties 
            debuggerTarget.Layout = @"${date:format=HH\\:MM\\:ss} ${message}";
            fileTarget.FileName = "${basedir}/file.txt";
            fileTarget.Layout = "${message}";

            // Step 4. Define rules
            var rule1 = new LoggingRule("*", LogLevel.Debug, debuggerTarget);
            config.LoggingRules.Add(rule1);

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

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

        private static void ConfigureCommonLogging()
        {
            var properties = new Common.Logging.Configuration.NameValueCollection();
            properties.Add("configType", "INLINE");
            Common.Logging.LogManager.Adapter = new Common.Logging.NLog.NLogLoggerFactoryAdapter(properties);
        }
    }
}
Paul Coghill
  • 667
  • 6
  • 27

1 Answers1

0

Something like that:

<?xml version="1.0" ?>
<nlog autoReload="true">
    <targets>
        <target name="databaseA" type="Database">
            <dbprovider>mssql</dbprovider>
            <!-- params -->
        </target>
        <target name="databaseB" type="Database">
            <dbprovider>mssql</dbprovider>
            <!-- params -->
        </target>       
    </targets>

    <rules>
        <logger name="CustomerA" minlevel="Debug" appendTo="databaseA" />
        <logger name="CustomerB" minlevel="Debug" appendTo="databaseB" />       
    </rules>
</nlog>
Andrey
  • 59,039
  • 12
  • 119
  • 163
  • Thanks, though the question was for a programmatic solution rather than using a config, as we can't really maintain this for every customer. Though this may point me in the right direction. – Paul Coghill Jan 15 '15 at 12:03
  • @PaulCoghill xml config can be translated to code essentially 1 to 1 and the opposite. I don't see any reasons not to use XML, it is much better for maintenance and other reasons. – Andrey Jan 15 '15 at 12:13