Konfiguracja Log4Net w zewnętrznym pliku nie działa

91

Używamy log4net i chcemy określić jego konfigurację w zewnętrznym pliku konfiguracyjnym (tak jak to zrobiliśmy z innymi sekcjami). Aby to zrobić, zmieniliśmy sekcję log4net w pliku App.config na:

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

A w pliku Log.Config (w tym samym katalogu co App.config) mamy:

<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>

Jednak po uruchomieniu aplikacji nie jest tworzony plik dziennika (ani rejestrowanie nie jest wykonywane). Na konsoli nie są wyświetlane żadne komunikaty o błędach.

Jeśli przeniesiemy zawartość pliku Log.config z powrotem do pliku App.config (zastępując pierwszą linię kodu powyżej), będzie działać zgodnie z oczekiwaniami. Masz jakiś pomysł, dlaczego nie działa w zewnętrznym pliku?

Robert Wagner
źródło
Napotkałem ten sam problem - prawdopodobnie postępowaliśmy zgodnie z tym samym (błędnym) przewodnikiem!
Zach Burlingame,
14
To jest to, czego nie lubię w log4net. Platforma rejestrowania powinna być moim zdaniem jedną z najbardziej solidnych części Twojej aplikacji - ale log4net często wydaje się być nieco niestabilny.
UpTheCreek

Odpowiedzi:

113

Czy masz następujący atrybut w swoim AssemblyInfo.cs pliku:

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

i taki kod na początku każdej klasy, który wymaga funkcji logowania:

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

Mam post na blogu zawierający te i inne informacje tutaj .

Mitch Wheat
źródło
17
To działa, upewnij się, że tworzysz plik log4net.config, aby ustawić właściwość „Kopiuj do katalogu wyjściowego” na „Zawsze kopiuj”.
E. van der Spoel
@mitchwheat Absolutnie boskie, walczyłem z rozwiązaniem opartym na ninject, aby robić dokładnie to, co robi to cały dzień ... dzięki stary!
Wojna
39

W tej kwestii istnieje otwarta usterka . Log4Net nie obsługuje atrybutu configSource elementów konfiguracji. Aby użyć rozwiązania opartego wyłącznie na plikach konfiguracyjnych, należy użyć klucza log4net.Config w pliku appSettings.

Krok 1: Uwzględnij definicję sekcji normalnej konfiguracji:

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

Krok 2: Użyj magicznego klucza log4net.Config w appSettings.

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

Krok 3: Prześlij poprawkę, aby naprawić obsługę configSource.

Stromy
źródło
5
Wywołanie log4net.Config.XmlConfigurator.Configure (); powinien ominąć ten problem, nie czytając configSource
Greg Domjan
To nic mnie nie zmieniło. Nie udało mi się jeszcze rozwiązać problemu, ale postaram się kontynuować.
Don Rolling
5
Ważne jest, aby oznaczyć plik konfiguracyjny log4net jako „kopiuj, jeśli nowszy”. Jeśli plik konfiguracyjny nie zostanie skopiowany do folderu bin, to nie zadziała.
Francisco Goldenstein,
To zadziałało tak jak jest i wolę to od zaakceptowanego rozwiązania, ponieważ niektóre z moich bibliotek są używane w aplikacji internetowej, w której rejestrowanie jest konfigurowane w osobnym pliku log4net.config i czasami używane w autonomicznej aplikacji, w której rejestrowanie jest skonfigurowany w app.exe.config. W ten sposób wszystko jest w konfiguracji, a nie w informacjach o assemblerze - nie chcę "na stałe kodować" tego do log4net.config
Danny
27

Krok, który został pominięty, to

log4net.Config.XmlConfigurator.Configure(); 

spowoduje to użycie configSource. Upewnij się, że wywołałeś to raz przed wywołaniem GetLogger ();

Greg Domjan
źródło
Nie musisz tego robić, jeśli używasz roztworu Mitcha Wheata.
Robert Wagner
4
@Robert: Jasne, chociaż rozwiązanie Mitcha Wheata wymaga twardego zakodowania pliku konfiguracyjnego poza app.config - przeczytałem pierwotne pytanie, dlaczego configSource nie działa, działa, jeśli wykonasz ten dodatkowy krok.
Greg Domjan,
Bardziej podoba mi się to podejście, szczególnie dlatego, że tworzę program obsługi dziennika opakowującego, który wewnętrznie używa log4net (który można później zastąpić), a następnie w tym programie obsługi dziennika opakowania wywołuję alwasy log4net.Config.XmlConfigurator.Configure (). W ten sposób każdy projekt z własną aplikacją app.config może używać tego modułu obsługi dziennika otoki, bez konieczności zmiany assembler.cs
zheng yu
19

Upewnij się, że plik log4net.config ma ustawione następujące właściwości:

Tworzenie akcji: zawartość

Kopiuj do katalogu wyjściowego: Kopiuj zawsze

Lewis Moten
źródło
10

Albo użyj,

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

Lub tylko,

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

W obu przypadkach plik Log4Net.config powinien znajdować się w katalogu wyjściowym. Możesz to zrobić, ustawiając właściwości pliku Log4Net.config w eksploratorze rozwiązań. Tworzenie akcji - zawartość i kopiowanie do katalogu wyjściowego - zawsze kopiuj

Byju
źródło
nie potrzebujesz tagu <configSections> dla pierwszego przypadku
disklosr
2

Uważaj na ten problem ...

W moim przypadku wszystko zostało skonfigurowane poprawnie. Problem polega na tym, że użyłem Web Deploy w programie Visual Studio 2013, aby przesłać witrynę do WinHost.com i zresetować listy ACL na serwerze. To z kolei cofnęło wszelkie uprawnienia do folderów i plików - log4net nie mógł zapisać pliku.

Więcej na ten temat przeczytasz tutaj:

Jak zatrzymać Web Deploy / MSBuild przed zepsuciem uprawnień serwera

Poprosiłem tamtejszy zespół pomocy o zresetowanie list ACL, a następnie log4net zaczął pluć logami. :)

Leniel Maccaferri
źródło
1

Zakładając, że masz zewnętrzny plik konfiguracyjny o nazwie log4net.config, który jest kopiowany do katalogu wdrażania, możesz go skonfigurować w następujący sposób:

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
źródło
1

Oprócz tego miałem ten sam problem

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

w bieżącym projekcie miałem również następujący wiersz w projekcie referencyjnym:

[assembly: log4net.Config.XmlConfigurator]

Kiedy usunąłem tę linię w projektach, do których istnieją odniesienia, dzienniki zaczynają się pojawiać.

Gość
źródło
1

Możliwe jest również włączenie trybu debugowania dla log4net. Wstaw to do pliku 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>

i przynajmniej otrzymasz komunikaty o błędach, z których możesz wywnioskować, co dokładnie poszło nie tak. W moim przypadku po prostu zapomniał ustawić Copy to output directorysię Copy Always.

waka
źródło
0

@Mitch, Okazuje się, że istnieje plik z deklaracją [assembly: ...], ale nie ma on właściwości ConfigFile.

Gdy dodałem go i wskazałem na Log.config, zaczął działać. Pomyślałbym, że będzie działać jak wszystkie inne sekcje konfiguracyjne (tj. AppSettings) i akceptować zewnętrzne pliki konfiguracyjne bez modyfikacji.

Nie mamy drugiego oświadczenia, o którym wspomniałeś, ponieważ opakowujemy go w globalnego dostawcę dziennika statycznego.

Robert Wagner
źródło
0

W moim przypadku otrzymałem ten komunikat o błędzie:

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

I log4net.configplik był w Visual Studio 2017 projektu, ale gdy sprawdziłem plikbin\Debug folderze, nie mogłem go znaleźć.

Moja oryginalna konfiguracja zespołu wyglądała następująco:

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

Po pewnym czasie badań zmieniam to na następujące i działa:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"..\..\log4net.config", Watch = true)]
maytham-ɯɐɥʇʎɐɯ
źródło
0
  1. dodaj następujące elementy do AssemblyInfo.cs

[zespół: log4net.Config.XmlConfigurator (ConfigFile = "Log4Net.config")]

  1. Upewnij się, że plik log4net.config jest uwzględniony w projekcie
  2. We właściwościach log4net.config

zmień Copy to Output Dirctory na Copy, jeśli jest nowsza

  1. Wartość poziomu dziennika podwójnego sprawdzenia = „ALL”
e03050
źródło
0

Warto również zauważyć, że w aplikacji internetowej wygląda to w katalogu głównym, a nie w folderze bin, więc upewnij się, że tam umieściłeś plik konfiguracyjny.

Richard
źródło