Мы используем 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 (заменив первую строку кода выше), он будет работать, как ожидалось. Есть идеи, почему он не работает во внешнем файле?
Это то, что мне не нравится в log4net. На мой взгляд, фреймворк регистрации должен быть одной из самых надежных частей вашего приложения, но log4net часто кажется немного нестабильным.





Есть ли в вашем файле 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 вы установили свойство «Копировать в выходной каталог» на «Всегда копировать».
@mitchwheat Совершенно божественно, я весь день боролся с решением на основе Ninject, чтобы делать именно то, что он делает ... спасибо, чувак!
@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
Для меня это ничего не изменило. Я еще не понял, в чем проблема, но постараюсь разобраться.
Важно отметить файл конфигурации log4net как «копировать, если новее». Если файл конфигурации не скопирован в папку bin, он не сработает.
Это сработало для меня как есть, и я предпочитаю его принятому решению, потому что некоторые из моих библиотек используются в веб-приложении, где ведение журнала настроено в отдельном файле log4net.config и иногда используется в автономном приложении, где ведение журнала настраивается в app.exe.config. Таким образом, все это находится в конфигурации, а не в информации о сборке - я не хочу "жестко закодировать" ее в log4net.config.
Убедитесь, что ваш файл log4net.config имеет следующие свойства:
Действие сборки: контент
Копировать в выходной каталог: копировать всегда
Пропущенный шаг -
log4net.Config.XmlConfigurator.Configure();
это приведет к использованию configSource. Обязательно вызовите его один раз перед вызовом GetLogger ();
Вам не нужно этого делать, если вы используете раствор Mitch Wheat.
@Robert: Конечно, хотя решение Митча Уита требует жесткого кодирования файла конфигурации вне app.config - я читал, что исходный вопрос был в том, почему не работает configSource, он работает, если следовать этому дополнительному шагу.
Мне больше нравится этот подход, особенно потому, что я создаю обработчик журнала оболочки, который внутренне использует log4net (который может быть заменен позже), а затем в этом обработчике журнала оболочки я всегда вызываю log4net.Config.XmlConfigurator.Configure (). Таким образом, любой проект со своим собственным app.config может использовать этот обработчик журнала оболочки без необходимости изменять файл Assemblyr.cs.
Где мне это назвать?
@Yola вызовите его один раз перед вызовом GetLogger
Предполагая, что у вас есть внешний файл конфигурации с именем 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> для первого случая
Остерегайтесь этой проблемы ...
В моем случае все было настроено правильно. Проблема в том, что я использовал 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)]
[сборка: log4net.Config.XmlConfigurator (ConfigFile = "Log4Net.config")]
измените Копировать в выходной каталог на Копировать, если новее
Также стоит отметить, что в веб-приложении он ищет в корневом каталоге, а не в папке bin, поэтому убедитесь, что вы поместили туда файл конфигурации.
Я столкнулся с той же проблемой - мы, вероятно, следовали одному и тому же (неверному) руководству!