0

I'm doing an NLog logger wrapper dll to use in some projects and I want to give multiple options to load configuration files.

  1. NLog default paths
  2. File specified by parameters
  3. Nlog config file path specified in some app.config setting.
  4. File located inside entry assembly path
  5. Default app.config file
  6. If anythig fails or no configuration file is found use default configuration created in code.

NLog Logger provider class

public NLogLoggerProvider(LoggerProviderOptions options)
{
    _options = options;
    _logFactory = BuildLogFactory();
}

private LogFactory BuildLogFactory()
{
    LogFactory factory = null;
    if (LogManager.Configuration != null)
    {
        factory = LogManager.LogFactory;
    }
    else
    {
        factory = new LogFactory();
        LoadNLogConfigurationOnFactory(factory);
    }

    ApplyDefaultConfigurationIfNeeded(factory);
    return factory;
}

private void LoadNLogConfigurationOnFactory(LogFactory nlogFactory)
{
    try
    {
        var nlogConfigFilePath = GetNLogConfigurationFilePath();
        if (nlogConfigFilePath != null)
        {
            var loggingConfiguration = new XmlLoggingConfiguration(nlogConfigFilePath);
            nlogFactory.Configuration = loggingConfiguration;
        }
    }
    catch (Exception ex)
    {
        ApplyDefaultConfigurationIfNeeded(nlogFactory);
    }
}

/// <summary>
/// Get NLog config file to load in the following order
/// <br /> 1. File Specified in LoggerProvider options
/// <br /> 2. Path specified in App config setting named 'NLogConfigFile'
/// <br /> 3. EntryAssembly path /Configuration/Sedecal.Crosscutting.Logging.NLog.config
/// <br /> 4. Default exe config file path
/// </summary>
/// <returns>Nlog config file to load</returns>
private string GetNLogConfigurationFilePath()
{
    var appConfigNLogConfigFile = ConfigurationManager.AppSettings[APP_CONFIG_NLOG_CONFIG_PATH];
    var defaultNLogConfigFile = GetDefaultConfigFile();
    var exeConfigurationFile = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).FilePath;

    if (!_options.LogConfigFilePath.IsEmpty() && File.Exists(_options.LogConfigFilePath))
    {
        return _options.LogConfigFilePath;
    }
    else if (!appConfigNLogConfigFile.IsEmpty() && File.Exists(appConfigNLogConfigFile))
    {
        return appConfigNLogConfigFile;
    }
    else if (File.Exists(defaultNLogConfigFile))
    {
        return defaultNLogConfigFile;
    }
    else if (File.Exists(exeConfigurationFile))
    {
        return exeConfigurationFile;
    }
    else
    {
        return null;
    }
}

private string GetDefaultConfigFile()
{
    var entryAssemblyLocation = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
    var configFilePath = Path.Combine(entryAssemblyLocation, CONFIGURATION_DIRECTORY, NLOG_CONFIG_FILE);
    return configFilePath;
}

private void ApplyDefaultConfigurationIfNeeded(LogFactory nlogFactory)
{
    if(nlogFactory.Configuration == null || !nlogFactory.Configuration.AllTargets.Any())
    {
        nlogFactory.Configuration = GetDefaultLogConfiguration();
    }
}

private LoggingConfiguration GetDefaultLogConfiguration()
{
    var config = new LoggingConfiguration();
    //Create file target and rule to file target
    return config;
}

My question is about configuration loading. I'm doing it like this

var configuration = new XmlLoggingConfiguration(filePath);
var logFactory = new LogFactory();
logFactory.Configuration = configuration;

But I have seen that there are other methods that receive LogFactory in XmlLoggingConfiguration constructor. But debugging them I have seen that the factory configuration is not modified. What is the best way of creating configuration and loading it into factories?

Is there any better way of checking that configuration is loaded correctly than check if there are any targets?

JuanDYB
  • 590
  • 3
  • 9
  • 23

1 Answers1

0

What is the best way of creating configuration and loading it into factories?

   var logFactory = new LogFactory();
   logFactory.LoadConfiguration(filePath);

Actually this method does the same thing as your code, but also it allows to set up the behavior for different corner cases. Here is the source code on GitHub

Is there any better way of checking that configuration is loaded correctly than check if there are any targets?

That is unnecessary. XmlLoggingConfiguration throws exception by default if configuration has some errors. And again you can check it with the source code. This is turned off by constructor argument ignoreErrors that you don't pass, just like logFactory.LoadConfiguration as well

Eugene
  • 169
  • 1
  • 6
  • I think that exceptions are thrown if there are any errors in loading configuration. But if you pass an app.config file without nlog config section not exception is thrown. – JuanDYB May 29 '23 at 06:34