使用程序集属性进行的Log4net配置未加载配置文件。

34

我有一个名为Log4net.config的文件位于我的bin目录下:

<?xml version="1.0" encoding="utf-8" ?>
<log4net xmlns="urn:log4net">
    <appender name="FileAppender" type="log4net.Appender.FileAppender">
        <param name="file" value="MyLogFile.log"/>
        <param name="appendToFile" value="false"/>
        <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%date (%logger) [%5level] - %message" />
        </layout>
    </appender>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
        <layout type="log4net.Layout.PatternLayout">
            <param name="ConversionPattern" value="%date (%logger) [%5level] - %message" />
        </layout>
    </appender>
    <root>
        <level value="DEBUG" />
        <appender-ref ref="FileAppender" />
        <appender-ref ref="ConsoleAppender"/>
    </root>
    <logger name="NHibernate" additivity="false">
        <level value="WARN"/>
    </logger>
</log4net>

以下是我在AssemblyInfo.cs文件中的代码:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyTitle("My Project")]
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "Log4net.config", Watch = true)]

当我运行程序时,我会得到以下的log4net调试输出:

log4net: log4net assembly [log4net, Version=1.2.10.0, Culture=neutral, PublicKeyToken=1b44e1d426115821]. Loaded from [D:\Data\Projects\Active\Clients\MyProject\src\MyProject.Importer\bin\Debug\log4net.dll]. (.NET Runtime [4.0.30319.1] on Microsoft Windows NT 6.1.7600.0)
log4net: DefaultRepositorySelector: defaultRepositoryType [log4net.Repository.Hierarchy.Hierarchy]
log4net: DefaultRepositorySelector: Creating repository for assembly [MyCompany.Framework, Version=2.1.72.0, Culture=neutral, PublicKeyToken=null]
log4net: DefaultRepositorySelector: Assembly [MyCompany.Framework, Version=2.1.72.0, Culture=neutral, PublicKeyToken=null] Loaded From [D:\Data\Projects\Active\Clients\MyProject\src\MyProject.Importer\bin\Debug\MyCompany.Framework.dll]
log4net: DefaultRepositorySelector: Assembly [MyCompany.Framework, Version=2.1.72.0, Culture=neutral, PublicKeyToken=null] does not have a RepositoryAttribute specified.
log4net: DefaultRepositorySelector: Assembly [MyCompany.Framework, Version=2.1.72.0, Culture=neutral, PublicKeyToken=null] using repository [log4net-default-repository] and repository type [log4net.Repository.Hierarchy.Hierarchy]
log4net: DefaultRepositorySelector: Creating repository [log4net-default-repository] using type [log4net.Repository.Hierarchy.Hierarchy]
The thread 'vshost.RunParkingWindow' (0xd30) has exited with code 0 (0x0).
The thread '<No Name>' (0x15d0) has exited with code 0 (0x0).
log4net: Hierarchy: Shutdown called on Hierarchy [log4net-default-repository]

Log4net已经加载,但似乎没有处理我的配置文件。当我在AssemblyInfo.cs中注释掉属性并在程序初始化期间运行以下代码时,它可以按预期工作:

var log4netConfig = "Log4net.config";
var log4netInfo = new FileInfo(log4netConfig);
log4net.Config.XmlConfigurator.ConfigureAndWatch(log4netInfo);

我做错了什么?我想从AssemblyInfo.cs中加载。

7个回答

43

我也对使用这种引导log4net的方法遇到了困难。 文档 表示,如果您使用配置属性,必须调用log4net以允许其读取属性。对LogManager.GetLogger的简单调用将导致调用程序集上的属性被读取和处理。因此,在应用程序启动尽可能早的时候(肯定在加载并调用任何外部程序集之前),必须进行日志记录调用。

尝试在启动应用程序的同一类中(例如program.cs,app.xaml等)放置一个logger。例如

private static readonly ILog Log = LogManager.GetLogger(typeof(Program));

为了好玩,可以进行任何一次对日志的调用(即使是被过滤或者从附加程序中被排除的调用,它也应该会强制log4net评估你的存储库/层次结构)。

static Program()
{
    Log.Debug("Application loaded.");
}

3
一如既往,请检查内部的log4net调试输出 <log4net debug="true" /> - Anthony Mastrean
对于一个 Web 服务应用程序,它应该放在哪里? - oliverdejohnson
@oliverdejohnson 请查看http://logging.apache.org/log4net/release/faq.html,了解如何启用log4net内部调试。该页面展示了如何设置调试和跟踪侦听器。 - Jeff Martin
还有一个不太为人所知的问题,我无法理解的是,他们决定只有在使用Debug构建时,log4net的XmlConfiguratorAttribute才能正常工作。如果您计划进行发布构建(在某个时候肯定会这样做),则必须在应用程序启动期间使用ConfigureAndWatch方法。 - Tom Lint
@TomLint 我刚刚测试了使用属性的方式,并且在发布版本中它正在加载配置文件(2.0.6),但是出于某种原因,只有在本地才能正常工作。当我将代码部署到Azure WebJob 后,当构建发布版本时就无法工作了。你有关于这个行为的文档来源吗? - martinoss

7

最终我找到了简单的解决方案,你可以在那里得到帮助。

  1. Global.asax in start function

     protected void Application_Start()
     {
       log4net.Config.XmlConfigurator.Configure();
     }
    
  2. In any of the class where use logging at class level

添加命名空间

using log4net;

在类级别上添加这行代码。
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
  1. use log function in any of the action call

    log.Error("test error q111..");
    
  2. configuration

    <configuration>
    <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net " />
    </configSection>
    <log4net debug="true">
    
    <!--AdoNet appender is use for write log file into sql server-->
    <appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
      <bufferSize value="1" />
      <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      <connectionString value="Data Source=DESKTOP-NLH31FH; Initial Catalog=SmallBizDb;Integrated Security=true" providerName="System.Data.SqlClient" />
      <commandText value="INSERT INTO [dbo].[Logs] ([Date],[Thread],[Level],[Logger],[Message],[Exception]) VALUES (@logdate,@thread, @loglevel, @logger, @message, @exception)" />
      <parameter>
        <parameterName value="@logdate" />
        <dbType value="DateTime" />
        <layout type="log4net.Layout.RawTimeStampLayout" />
      </parameter>
      <parameter>
        <parameterName value="@thread" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%thread" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@loglevel" />
        <dbType value="String" />
        <size value="50" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%level" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@logger" />
        <dbType value="String" />
        <size value="255" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%logger" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@message" />
        <dbType value="String" />
        <size value="4000" />
        <layout type="log4net.Layout.PatternLayout">
          <conversionPattern value="%message" />
        </layout>
      </parameter>
      <parameter>
        <parameterName value="@exception" />
        <dbType value="String" />
        <size value="2000" />
        <layout type="log4net.Layout.ExceptionLayout" />
      </parameter>
    </appender>
    <!--Add appender which you want to use, You can add more then one appender . Like if you want save log both plain text or sql server ,Add both appender.-->
    
    <root>
      <level value="Debug" />
      <!--<appender-ref ref="RollingLogFileAppender" />-->
      <!--Enable this line if you want write log file into plain text file-->
      <appender-ref ref="AdoNetAppender" />
      <!--Enable this line if you want write log file into sql server-->
    
    </root>
    
    </log4net>
    
    <appSettings>
    <add key="log4net.Internal.Debug" value="true"/>
    </appSettings>
    </configuration>
    

它可能对所有人有所帮助,且易于使用。谢谢。


4

我在Global.asax.cs文件的Application_Start()方法中使用了log4net.Config.XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/Web.config")));,这样我就不需要在其他地方重复执行该命令。


4
我通过在有问题的程序集的 AssemblyInfo.cs 文件中添加 RepositoryAttribute 来解决了这个问题。
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: RepositoryAttribute("Your.Namespace.Here")]

1
我尝试了上述方法,现在log4net在为程序集创建仓库时不再报错,但它仍然无法将日志写入文件。在创建仓库后,它只是关闭了程序集。有任何想法吗? - meghana

1
我正在使用Web.Config部分来配置Logger并手动记录事件,从global.asax引导Logger。
static ILog logger = LogManager.GetLogger(<LoggerName>);

protected void Application_Start()
{
   log4net.Config.XmlConfigurator.Configure(); 
}

尝试从global.asax引导它。

0

我在使用log4Net和Windows服务。我尝试了其他答案中提到的所有可能的选项。

对我来说,另一个服务实例仍然在运行,我不得不从任务管理器中结束它。之后,问题得到了解决。


-1
var log4NetPath = Server.MapPath("~/log4net.config");

FileInfo fileInfo = new FileInfo(log4NetPath);

XmlConfigurator.ConfigureAndWatch(fileInfo);

2
你需要添加一些说明文来解释这段代码的作用。它已经被标记并显示在“低质量帖子”审核队列中,因此有被删除的风险。 - sideshowbarker

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接