Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Log4Net in a separate configuration file

I need to configure log4net for a new project. All works perfectly fine, when I hold all my information in the App.config file. I want to put the configuration of log4net in a separate configuration file (take App1.config)

Here is my app.config working perfectly :

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
  </configSections>
  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
      </layout>
    </appender>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="C:\Logs\MylogText.txt"/>
      <appendToFile value="true"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
      </layout>
    </appender>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="C:\Logs\RollinglogText.txt"/>
      <appendToFile value="true"/>
      <rollingStyle value="Size"/>
      <maximumFileSize value="10MB"/>
      <maxSizeRollBackups value="5"/>
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
      </layout>
    </appender>
    <root>
      <level value="DEBUG" />
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="FileAppender"/>
      <appender-ref ref="RollingFileAppender"/>
    </root>
  </log4net>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
</configuration>

I removed everything except the <startup> element from my app.config and put this in my app1.config :

  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
      </layout>
    </appender>
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
      <file value="C:\Logs\MylogText.txt"/>
      <appendToFile value="true"/>
      <lockingModel type="log4net.Appender.FileAppender+MinimalLock"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
      </layout>
    </appender>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="C:\Logs\RollinglogText.txt"/>
      <appendToFile value="true"/>
      <rollingStyle value="Size"/>
      <maximumFileSize value="10MB"/>
      <maxSizeRollBackups value="5"/>
      <staticLogFileName value="true"/>
      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date{ABSOLUTE} [%logger] %level - %message%newline%exception"/>
      </layout>
    </appender>

    <root>
      <level value="DEBUG" />
      <appender-ref ref="ConsoleAppender"/>
      <appender-ref ref="FileAppender"/>
      <appender-ref ref="RollingFileAppender"/>
    </root>
  </log4net>

In my Program.cs class, I call the configuration with the assembly like that :

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "App1.config", Watch = true)]

But there is no log in my files when I use App1.config.

like image 759
Xavier W. Avatar asked Oct 01 '15 16:10

Xavier W.


People also ask

Where do I put log4net in web config?

Add log4net in config file config and enter the following details. Add a class Log. cs in the Utilities folder. Now, in the constructor of this class, instantiate logs for monitoring and debugger loggers.

How do I use multiple Appenders in log4net?

You can't log to separate appenders - you need to configure different loggers, and attach the appropriate appender to each one. Then log different messages to the different loggers.

Does log4net need XML?

It's probably an XML documentation file, which contains the XML comments on all of the members in the log4net project. It's not at all necessary for installation, so you can delete it if you want.


1 Answers

Use the following as a template:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <configSections>    
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
  </configSections>

  <log4net configSource="log4net.config"/>

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
  </startup>

</configuration>

And place your log4net config in log4net config e.g.

<log4net>
    <!-- Configuration -->
</log4net>

If you want to watch for changes in the file you can do so with the following class (call LoggingConfigurator.ConfigureLogging()):

public static class LoggingConfigurator
{
    private const string DebugLoggingConfiguration = @"log4net.debug.config";

    /// <summary>
    /// Configures the logging.
    /// </summary>
    /// <exception cref="System.Configuration.ConfigurationErrorsException">Thrown if the logging configuration does not exist.</exception>
    [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Console.WriteLine(System.String)")]
    [SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Console.WriteLine(System.String,System.Object)")]
    public static void ConfigureLogging()
    {
        try
        {
            string path = GetLogConfigurationPath();

            var fileInfo = new FileInfo(path);

            if (fileInfo.Exists)
            {
                log4net.Config.XmlConfigurator.ConfigureAndWatch(fileInfo);
                Console.WriteLine("Loaded logging configuration from: {0}", path);
            }
            else
            {
                var message = "Logging configuration does not exist: " + path;
                Console.WriteLine(message);
                throw new ConfigurationErrorsException(message);
            }
        }
        catch (ConfigurationErrorsException ex)
        {
            Console.WriteLine("log4net is not configured:\n{0}", ex);
        }
    }

    /// <summary>
    /// Gets the path to the logging configuration file.
    /// </summary>
    /// <returns>The path to the log configuration file.</returns>
    private static string GetLogConfigurationPath()
    {
        var path = GetPathFromAppConfig();
        var directory = Path.GetDirectoryName(path);

        if (directory != null)
        {
            var debugPath = Path.Combine(directory, DebugLoggingConfiguration);
            if (File.Exists(debugPath))
            {
                return debugPath;
            }
        }

        return path;
    }

    /// <summary>
    /// Gets the log4net configuration path file from the app.config.
    /// </summary>
    /// <returns>The path to the log4net configuration file if found, otherwise <c>null</c>.</returns>
    private static string GetPathFromAppConfig()
    {
        string appConfigPath;

        var xml = LoadAppConfig(out appConfigPath);
        var logSectionNode = GetSection(xml, "Log4NetConfigurationSectionHandler");

        if (logSectionNode == null || logSectionNode.Attributes == null)
        {
            return appConfigPath;
        }

        var attribute = logSectionNode.Attributes["configSource"];

        if (attribute == null || string.IsNullOrEmpty(attribute.Value))
        {
            return appConfigPath;
        }

        // Otherwise return the path to the actual log4net config file.
        return ToAbsolutePath(attribute.Value, appConfigPath);
    }

    /// <summary>
    /// Gets the node for a configurations section from an application configuration.
    /// </summary>
    /// <param name="configuration">The <see cref="XmlDocument"/> representing the application configuration.</param>
    /// <param name="type">The section type.</param>
    /// <returns>The node for the section.</returns>
    /// <exception cref="ArgumentNullException"><paramref name="configuration"/> is <c>null</c>.</exception>
    /// <exception cref="ArgumentNullException"><paramref name="type"/> is <c>null</c>.</exception>
    /// <exception cref="ArgumentException"><paramref name="type"/> is an empty string.</exception>
    /// <exception cref="ConfigurationErrorsException">The section could not be found in the application configuration.</exception>
    private static XmlNode GetSection(XmlDocument configuration, string type)
    {
        if (configuration == null)
        {
            throw new ArgumentNullException("configuration");
        }

        if (type == null)
        {
            throw new ArgumentNullException("type");
        }

        if (type.Length == 0)
        {
            throw new ArgumentException("'type' cannot be an empty string.");
        }

        // Get the name of the section from the type
        const string configSectionFormat = @"/configuration/configSections/section[contains(@type,'{0}')]/@name";

        var configSectionPath = string.Format(CultureInfo.InvariantCulture, configSectionFormat, type);
        var configSectionNode = configuration.SelectSingleNode(configSectionPath);

        if (configSectionNode == null)
        {
            throw new ConfigurationErrorsException("App.config does not have a section with a type attribute containing: " + type);
        }

        // Get the section from the name discovered above
        var sectionName = configSectionNode.Value;
        var sectionNode = configuration.SelectSingleNode(@"/configuration/" + sectionName);

        if (sectionNode == null)
        {
            throw new ConfigurationErrorsException("Section not found in app.config: " + sectionName);
        }

        return sectionNode;
    }

    /// <summary>
    /// Loads the application configuration.
    /// </summary>
    /// <param name="appConfigPath">The path to the application configuration.</param>
    /// <returns>The loaded application configuration as an <see cref="XmlDocument"/>.</returns>
    /// <exception cref="ConfigurationErrorsException">The application configuration could not be loaded.</exception>
    private static XmlDocument LoadAppConfig(out string appConfigPath)
    {
        try
        {
            var xml = new XmlDocument();
            appConfigPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
            xml.Load(appConfigPath);
            return xml;
        }
        catch (Exception ex)
        {
            throw new ConfigurationErrorsException("Could not load app.config.", ex);
        }
    }

    /// <summary>
    /// Converts a path to an absolute path.
    /// </summary>
    /// <param name="path">The path (can be absolute or relative).</param>
    /// <param name="basePath">The base path (used for resolving absolute path).</param>
    /// <returns>The absolute path</returns>
    /// <exception cref="ArgumentException"><paramref name="basePath"/> does not contain a directory.</exception>
    private static string ToAbsolutePath(string path, string basePath)
    {
        if (Path.IsPathRooted(path))
        {
            return path;
        }

        var directory = Path.GetDirectoryName(basePath);

        if (directory == null)
        {
            throw new ArgumentException("'basePath' does not contain a directory.", "basePath");
        }

        return Path.GetFullPath(Path.Combine(directory, path));
    }
}
like image 158
Ananke Avatar answered Oct 26 '22 16:10

Ananke