Конфигурация Log4Net во внешнем файле не работает

91

Мы используем log4net и хотим указать его конфигурацию во внешнем файле конфигурации (как мы это делали с другими разделами). Для этого мы изменили раздел log4net в App.config на:

...
<section name="log4net" 
     type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
...
<log4net configSource="Log.config" />
...

И в файле Log.Config (тот же каталог, что и App.config) у нас есть:

<log4net>
  <appender name="General" type="log4net.Appender.FileAppender">
    <file value="myapp.log" />
    <layout type="log4net.Layout.SimpleLayout" />
  </appender>
  <root>
    <appender-ref ref="General" />
  </root>
</log4net>

Однако при запуске приложения файл журнала не создается (и журнал не ведется). На консоль не выводятся сообщения об ошибках.

Если мы переместим содержимое файла Log.config обратно в App.config (заменив первую строку кода выше), он будет работать должным образом. Есть идеи, почему он не работает во внешнем файле?

Роберт Вагнер
источник
Я столкнулся с той же проблемой - мы, вероятно, следовали одному и тому же (неверному) руководству!
Zach Burlingame
14
Это то, что мне не нравится в log4net. На мой взгляд, фреймворк регистрации должен быть одной из самых надежных частей вашего приложения, но log4net часто кажется немного нестабильным.
UpTheCreek

Ответы:

113

Есть ли в вашем AssemblyInfo.csфайле следующий атрибут :

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

и код, подобный этому, в начале каждого класса, который требует функции ведения журнала:

private static readonly ILog log = 
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

У меня есть сообщение в блоге, содержащее эту и другую информацию здесь .

Митч Уит
источник
17
Это работает, убедитесь, что при создании файла log4net.config вы установили свойство «Копировать в выходной каталог» на «Всегда копировать».
Э. ван дер Споэль
@mitchwheat Совершенно верно, я боролся с решением на основе ниндзя, чтобы делать именно то, что он делает весь день ... спасибо, чувак!
War
39

В этом вопросе есть открытый недочет . Log4Net не поддерживает атрибут configSource элементов конфигурации. Чтобы использовать решение только с файлом конфигурации, используйте ключ log4net.Config в appSettings.

Шаг 1. Включите определение раздела нормальной конфигурации:

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

Шаг 2: Используйте волшебный ключ log4net.Config в appSettings.

<appSettings>
      <add key="log4net.Config" value="log4net.simple.config" />
</appSettings>

Шаг 3: Внесите патч для исправления обработки configSource.

Осадный
источник
5
Вызов log4net.Config.XmlConfigurator.Configure (); должен решить эту проблему, не читая configSource
Грег Домжан,
Для меня это ничего не изменило. Я еще не выяснил, в чем проблема, но постараюсь разобраться.
Дон Роллинг,
5
Важно отметить файл конфигурации log4net как «копировать, если новее». Если файл конфигурации не скопирован в папку bin, он не сработает.
Франсиско Гольденштейн,
Это сработало для меня как есть, и я предпочитаю его принятому решению, потому что некоторые из моих библиотек используются в веб-приложении, где ведение журнала настраивается в отдельном файле log4net.config и иногда используется в автономном приложении, где ведение журнала настраивается в app.exe.config. Таким образом, это все в конфигурации, а не в информации о сборке - я не хочу «жестко закодировать» ее в log4net.config
Дэнни,
27

Пропущенный шаг -

log4net.Config.XmlConfigurator.Configure(); 

это приведет к использованию configSource. Обязательно вызовите его один раз перед вызовом GetLogger ();

Грег Домьян
источник
Вам не нужно этого делать, если вы используете раствор Mitch Wheat.
Роберт Вагнер,
4
@Robert: Конечно, хотя решение Митча Уита требует жесткого кодирования файла конфигурации вне app.config - я читал, что исходный вопрос был в том, почему не работает configSource, он работает, если следовать этому дополнительному шагу.
Грег Домьян,
Мне больше нравится этот подход, особенно потому, что я создаю обработчик журнала оболочки, который внутренне использует log4net (который может быть заменен позже), а затем в этом обработчике журнала оболочки я всегда вызываю log4net.Config.XmlConfigurator.Configure (). Таким образом, любой проект со своим собственным app.config может использовать этот обработчик журнала оболочки без необходимости изменять
zheng yu
19

Убедитесь, что ваш файл log4net.config имеет следующие свойства:

Действие сборки: контент

Копировать в выходной каталог: копировать всегда

Льюис Мотен
источник
10

Либо используйте,

<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/>
</configSections>
<appSettings>
<add key="log4net.Config" value="Log4Net.config" />
</appSettings>

или просто,

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo("Log4Net.config"));

В обоих случаях файл Log4Net.config должен находиться в каталоге вывода. Вы можете сделать это, установив свойства файла Log4Net.config в обозревателе решений. Действие сборки - содержимое и копирование в выходной каталог - всегда копировать

Byju
источник
вам не нужен тег <configSections> для первого случая
disklosr
2

Остерегайтесь этой проблемы ...

В моем случае все было настроено правильно. Проблема в том, что я использовал Web Deploy внутри Visual Studio 2013 для загрузки сайта на WinHost.com и сбросил списки управления доступом на сервере. Это, в свою очередь, аннулировало все права доступа к папкам и файлам - log4net не смог записать файл.

Вы можете прочитать больше об этом здесь:

Как запретить Web Deploy / MSBuild испортить разрешения сервера

Я попросил техподдержку сбросить ACL, а затем log4net начал выдавать логи. :)

Лениэль Маккаферри
источник
1

Предполагая, что у вас есть внешний файл конфигурации с именем log4net.config, который копируется в каталог развертывания, вы можете настроить его следующим образом:

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Reflection;

using log4net;

namespace MyAppNamespace {
    static class Program {
        //declare it as static and public so all classes in the project can access it
        //like so: Program.log.Error("got an error");
        public static readonly log4net.ILog log = log4net.LogManager.GetLogger(typeof(Program));

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main() {
             //configure it to use external file
            log4net.Config.XmlConfigurator.Configure(new Uri(Application.StartupPath + "\\log4net.config"));
            //use it
            log.Debug("#############   STARING APPLICATION    #################");


            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new FormMain());
        }
    }
}
JJ_Coder4Hire
источник
1

У меня была такая же проблема, кроме того, что

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net")]

в работающем проекте у меня также была следующая строка в эталонном проекте:

[assembly: log4net.Config.XmlConfigurator]

Когда я удалил эту строку в упомянутых проектах, журналы начали появляться.

Гость
источник
1

Также можно включить режим отладки для log4net. Вставьте это в файл App.config:

 <appSettings>
      <add key="log4net.Internal.Debug" value="true"/>
 </appSettings>
 <system.diagnostics>
      <trace autoflush="true">
      <listeners>
           <add
             name="textWriterTraceListener"
             type="System.Diagnostics.TextWriterTraceListener"
             initializeData="link\to\your\file.log" />
      </listeners>
      </trace>
 </system.diagnostics>

и вы, по крайней мере, будете получать сообщения об ошибках, из которых сможете понять, что именно пошло не так. В моем случае я просто забыл установить Copy to output directoryна Copy Always.

Waka
источник
0

@Mitch, оказывается есть файл с объявлением [assembly: ...], но у него не было свойства ConfigFile.

Как только я добавил его и указал на Log.config, он начал работать. Я бы подумал, что он будет работать, как и все другие разделы конфигурации (например, AppSettings), и принимать внешние файлы конфигурации без каких-либо изменений.

У нас нет второго утверждения, о котором вы упомянули, поскольку мы оборачиваем его в глобальный поставщик статических журналов.

Роберт Вагнер
источник
0

В моем случае я получил это сообщение об ошибке:

log4net: config file [C:\........\bin\Debug\log4net.config] not found.

И log4net.configфайл был в проекте Visual Studio 2017, но когда я проверил файл вbin\Debug папке, я не смог его найти.

Моя первоначальная установка сборки была такой:

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

После некоторого времени исследования я меняю его на следующее, и оно работает:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"..\..\log4net.config", Watch = true)]
Maytham-ɯɐɥʇʎɐɯ
источник
0
  1. добавить следующее в AssemblyInfo.cs

[сборка: log4net.Config.XmlConfigurator (ConfigFile = "Log4Net.config")]

  1. Убедитесь, что log4net.config включен в проект
  2. В свойствах log4net.config

измените Копировать в выходной каталог на Копировать, если новее

  1. Дважды проверьте значение уровня уровня журнала = "ВСЕ"
e03050
источник
0

Также стоит отметить, что в веб-приложении он ищет в корневом каталоге, а не в папке bin, поэтому убедитесь, что вы поместили туда файл конфигурации.

Ричард
источник