草庐IT

c# - Log4Net 在单独的配置文件中

coder 2024-05-21 原文

我需要为一个新项目配置 log4net。当我将所有信息保存在 App.config 文件中时,一切正常。我想把log4net的配置放在一个单独的配置文件中(拿App1.config)

这是我的 app.config 完美运行:

<?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>

我删除了除 <startup> 之外的所有内容从我的 app.config 元素并将其放入我的 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>

在我的 Program.cs 类中,我用这样的程序集调用配置:

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

但是当我使用 App1.config 时,我的文件中没有日志。

最佳答案

使用以下作为模板:

<?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>

并将您的 log4net 配置放在 log4net 配置中,例如

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

如果您想查看文件中的更改,可以使用以下类(调用 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));
    }
}

关于c# - Log4Net 在单独的配置文件中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32892021/

有关c# - Log4Net 在单独的配置文件中的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  3. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

  4. Ruby Sinatra 配置用于生产和开发 - 2

    我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm

  5. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  6. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  7. ruby - Net::HTTP 获取源代码和状态 - 2

    我目前正在使用以下方法获取页面的源代码:Net::HTTP.get(URI.parse(page.url))我还想获取HTTP状态,而无需发出第二个请求。有没有办法用另一种方法做到这一点?我一直在查看文档,但似乎找不到我要找的东西。 最佳答案 在我看来,除非您需要一些真正的低级访问或控制,否则最好使用Ruby的内置Open::URI模块:require'open-uri'io=open('http://www.example.org/')#=>#body=io.read[0,50]#=>"["200","OK"]io.base_ur

  8. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  9. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  10. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

随机推荐