当调用XmlConfigurator.Configure()时,log4net才能正常工作。

28
我知道这个问题this 已经 问过 多次 , 但是很不幸,我一直无法让我的日志配置起作用。我肯定是在某个地方犯了非常小的错误。

我有一个.NET 4.5 MVC 4/EF 5的Web应用程序,我正在尝试让日志记录工作。该解决方案有两个项目,一个用于DAO和模型对象,另一个用于网站。 App.Config文件如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="RebuildingTogetherEntities" connectionString="stuff..."/>
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <log4net configSource="Log.config" />
</configuration>

相同的log4net部分也被复制到Web.Config文件中。

我在两个AssemblyInfo.cs文件中添加了以下内容:

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

"

“Copy To Output Directory”对于两个Log.Config文件都设置为true。

我似乎唯一的方法是在第一条日志记录语句运行之前调用XmlConfigurator.Configure(),才能让日志附加到输出文件中。我猜我可以写一个门面来在我第一次获取记录器时执行这个操作,但那感觉不对。

如何在不手动调用XmlConfigurator的情况下初始化记录器?

"

这个问题适用于 https://dev59.com/Mm865IYBdhLWcg3wIa_M 吗? - sgmoore
看起来不是这样...在那种情况下,应用程序关闭之前有来自log4net的消息,但在我的情况下我没有看到那条消息。不过还是谢谢你的建议。 - Brad
1
不确定我是否同意你的逻辑。除非内部记录开启,否则您将看不到log4net消息,如果您的系统没有读取log.config,则可能不会开启内部记录。重要的是,当您执行像GetLogger(...)这样的操作时,系统基本上会执行类似于Attribute.GetCustomAttributes(Assembly.GetCallingAssembly(), typeof(log4net.Config.ConfiguratorAttribute), false) 的操作。因此,如果您在应用程序启动时没有很早地记录日志,那么您的第一个记录器可能会从不继续自定义属性的程序集中初始化。 - sgmoore
11
我喜欢日志框架静默失败的方式。 - user117499
2个回答

35

我遇到了完全相同的问题。正如你正确指出的那样,当在AssemblyInfo.cs中包含该行时,你不需要显式调用XmlConfigurator。但是,当第一次使用log4net的程序集没有那行时,问题就来了。在我的情况下,我正在使用Topshelf.Log4Net NuGet包,而我的应用程序记录的第一条日志就是通过它来完成。

你可以在应用程序早期记录一条日志,或者如果你不需要记录任何内容,就像我所做的那样,在应用程序的入口点添加以下内容:

LogManager.GetLogger(typeof(Program));

很好的答案。我们遇到了同样的问题,由我们的 DI 容器自动创建的一个对象在主应用程序之前输出了一行日志。 - BBoy
真是救命稻草啊。把它放在 global.asax.cs 中,它完美地工作了。为此我实际上花了一整天的时间。 - arviman
1
一个 Program 类通常被用作 C# 应用程序的入口点。不过,你也可以使用来自入口程序集的任何类。 - Matt Cole
1
经过多次谷歌搜索和stackoverflow错误答案后,为什么这还没有被标记为正确答案呢? - Daniel Lobo
2
@ChrisGessler 这不是一种变通方法,而是根据属性文档所指定的——“……在应用程序启动尽可能早的时候进行日志记录调用是必不可少的,并且肯定要在加载和调用任何外部程序集之前完成。” - stuartd
显示剩余4条评论

9

如果您使用以下方式,则无需手动调用XmlConfigurator:

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

然而,您必须将标签添加到所有DLL文件(即所有assambly.cs文件)。


1
应用程序即使添加了这个功能仍然无法记录,非常遗憾。 - Brad
2
您可以启用log4net调试:http://haacked.com/archive/2006/09/27/Log4Net_Troubleshooting.aspx - Peter
2
请问您能否解释一下为什么建议将此属性添加到所有dll而不仅仅是主机dll? - Aleksei Poliakov
1
它将使您能够为每个dll单独配置日志记录,使用不同的配置文件。 - Peter
我猜那个 [assembly] 在 global.aspx 中,我在其他项目中使用它并且 log4net 运行良好,但是我有一个项目无法工作。 - Maximiliano Cesán

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