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?


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 .


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.


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 ();


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


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


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. :)


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());
        }
    }
}

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


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.


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.


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

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”

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.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.