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

Мы используем 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 30.01.2009 19:45

Это то, что мне не нравится в log4net. На мой взгляд, фреймворк регистрации должен быть одной из самых надежных частей вашего приложения, но log4net часто кажется немного нестабильным.

UpTheCreek 17.04.2010 19:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
93
2
77 567
13
Перейти к ответу Данный вопрос помечен как решенный

Ответы 13

Ответ принят как подходящий

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

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

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

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

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

Это работает, убедитесь, что при создании файла log4net.config вы установили свойство «Копировать в выходной каталог» на «Всегда копировать».

E. van der Spoel 08.07.2015 11:38

@mitchwheat Совершенно божественно, я весь день боролся с решением на основе Ninject, чтобы делать именно то, что он делает ... спасибо, чувак!

War 27.11.2015 19:10

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

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

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

По этому поводу есть открытый дефект. 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.

Вызов log4net.Config.XmlConfigurator.Configure (); должен решить эту проблему, не читая configSource

Greg Domjan 12.04.2011 00:58

Для меня это ничего не изменило. Я еще не понял, в чем проблема, но постараюсь разобраться.

Don Rolling 30.01.2015 20:10

Важно отметить файл конфигурации log4net как «копировать, если новее». Если файл конфигурации не скопирован в папку bin, он не сработает.

Francisco Goldenstein 09.07.2015 17:03

Это сработало для меня как есть, и я предпочитаю его принятому решению, потому что некоторые из моих библиотек используются в веб-приложении, где ведение журнала настроено в отдельном файле log4net.config и иногда используется в автономном приложении, где ведение журнала настраивается в app.exe.config. Таким образом, все это находится в конфигурации, а не в информации о сборке - я не хочу "жестко закодировать" ее в log4net.config.

Danny 09.04.2020 00:50

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

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

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

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

log4net.Config.XmlConfigurator.Configure(); 

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

Вам не нужно этого делать, если вы используете раствор Mitch Wheat.

Robert Wagner 12.04.2011 02:20

@Robert: Конечно, хотя решение Митча Уита требует жесткого кодирования файла конфигурации вне app.config - я читал, что исходный вопрос был в том, почему не работает configSource, он работает, если следовать этому дополнительному шагу.

Greg Domjan 13.04.2011 02:45

Мне больше нравится этот подход, особенно потому, что я создаю обработчик журнала оболочки, который внутренне использует log4net (который может быть заменен позже), а затем в этом обработчике журнала оболочки я всегда вызываю log4net.Config.XmlConfigurator.Configure (). Таким образом, любой проект со своим собственным app.config может использовать этот обработчик журнала оболочки без необходимости изменять файл Assemblyr.cs.

zheng yu 19.12.2017 15:39

Где мне это назвать?

Yola 17.12.2020 01:48

@Yola вызовите его один раз перед вызовом GetLogger

Greg Domjan 08.01.2021 11:18

Предполагая, что у вас есть внешний файл конфигурации с именем 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());
        }
    }
}

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

<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 в обозревателе решений. Действие сборки - содержимое и копирование в выходной каталог - всегда копировать

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

disklosr 23.01.2017 16:49

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

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

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

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

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

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

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

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

[assembly: log4net.Config.XmlConfigurator]

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

Также можно включить режим отладки для 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.

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

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)]
  1. добавить подписку к AssemblyInfo.cs

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

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

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

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

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

Другие вопросы по теме