A configuração do Log4Net no arquivo externo não funciona


92

Estamos usando log4net e queremos especificar sua configuração em um arquivo de configuração externo (como fizemos com outras seções). Para fazer isso, alteramos a seção log4net no App.config para:

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

E no arquivo Log.Config (mesmo diretório do App.config) temos:

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

No entanto, quando executamos o aplicativo, nenhum arquivo de log é criado (e nenhum registro é feito). Não há saída de mensagens de erro para o console.

Se movermos o conteúdo do arquivo Log.config de volta para o App.config (substituindo a primeira linha de código acima), ele funcionará conforme o esperado. Alguma ideia de porque não está funcionando em um arquivo externo?


Tive o mesmo problema - provavelmente seguimos o mesmo guia (mal orientado)!
Zach Burlingame

14
Isso é o que eu não gosto no log4net. A estrutura de registro deve ser uma das partes mais sólidas do seu aplicativo, na minha opinião - mas o log4net frequentemente parece um pouco instável.
UpTheCreek

Respostas:


112

Você tem o seguinte atributo em seu AssemblyInfo.csarquivo:

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

e código como este no início de cada classe que requer funcionalidade de registro:

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

Eu tenho uma postagem no blog contendo essas e outras informações aqui .


17
Isso funciona, certifique-se de criar o arquivo log4net.config para definir a propriedade "Copiar para diretório de saída" em "Copiar sempre".
E. van der Spoel

@mitchwheat Absolutamente tipo deus, tenho lutado com uma solução baseada em ninjeitos para fazer exatamente o que isso faz o dia todo ... obrigado cara!
Guerra

39

Há um defeito aberto neste problema. Log4Net não suporta o atributo configSource de elementos de configuração. Para usar uma solução de arquivo de configuração puramente, você usa a chave log4net.Config em appSettings.

Etapa 1: inclua a definição da seção de configuração normal:

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

Etapa 2: Use a chave mágica log4net.Config em appSettings.

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

Etapa 3: contribuir com um patch para corrigir o manuseio do configSource.


5
Uma chamada para log4net.Config.XmlConfigurator.Configure (); deve superar esse problema sem ler configSource
Greg Domjan

Isso não mudou nada para mim. Ainda não descobri o problema, mas tentarei fazer o acompanhamento.
Don Rolling

5
É importante marcar o arquivo de configuração log4net como "copiar se mais recente". Se o arquivo de configuração não for copiado para a pasta bin, não vai funcionar.
Francisco Goldenstein

Isso funcionou para mim no estado em que se encontra, e eu prefiro a solução aceita porque algumas de minhas bibliotecas são usadas em um aplicativo da web onde o registro é configurado em um log4net.config separado e às vezes usado em um aplicativo independente onde o registro é configurado em app.exe.config. Desta forma, está tudo na configuração em vez de nas informações do assembly - não quero "hard-code" para log4net.config
Danny

27

A etapa que foi perdida é

log4net.Config.XmlConfigurator.Configure(); 

isso fará com que o configSource seja usado. Certifique-se de chamá-lo uma vez antes de chamar GetLogger ();


Você não precisa fazer isso se usar a solução de Mitch Wheat.
Robert Wagner,

4
@Robert: Claro, embora a solução de Mitch Wheat exija a codificação do arquivo de configuração fora do app.config - eu li que a pergunta original era por que o configSource não funciona, ele funciona se essa etapa extra for seguida.
Greg Domjan,

Eu gosto mais dessa abordagem, especialmente porque eu crio um manipulador de log de invólucro que usa log4net internamente (que pode ser substituído posteriormente), então neste manipulador de log de invólucro eu sempre chamo log4net.Config.XmlConfigurator.Configure (). Desta forma, qualquer projeto com seu próprio app.config poderia usar este manipulador de log de wrapper, sem a necessidade de alterar assembler.cs
zheng yu

19

Certifique-se de que seu arquivo log4net.config esteja definido com as seguintes propriedades:

Criar ação: conteúdo

Copiar para o diretório de saída: Copiar sempre


10

Ou use,

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

ou apenas,

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

Em ambos os casos, o arquivo, Log4Net.config, deve estar lá no diretório de saída. Você pode fazer isso definindo as propriedades do arquivo Log4Net.config no Solution Explorer. Build Action - Conteúdo e Copiar para o Diretório de Saída - Copiar sempre


você não precisa da tag <configSections> para o primeiro caso
disklosr

2

Cuidado com este problema ...

No meu caso tudo foi configurado corretamente. O problema é que usei o Web Deploy dentro do Visual Studio 2013 para carregar o site para WinHost.com e ele redefiniu as ACLs no servidor. Isso, por sua vez, revogou todas as permissões em pastas e arquivos - log4net não pôde gravar o arquivo.

Você pode ler mais sobre isso aqui:

Como impedir que o Web Deploy / MSBuild atrapalhe as permissões do servidor

Pedi à equipe de suporte local para redefinir as ACLs e então o log4net começou a cuspir logs. :)


1

Supondo que você tenha um arquivo de configuração externo chamado log4net.config que é copiado para o diretório de implantação, você pode configurá-lo da seguinte forma:

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

Tive o mesmo problema, além de ter

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

no projeto em execução, também tive a seguinte linha em um projeto de referência:

[assembly: log4net.Config.XmlConfigurator]

Ao remover esta linha nos projetos referenciados, os logs começam a aparecer.


1

Também é possível ativar o modo de depuração para log4net. Insira isso no arquivo 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>

e você pelo menos obterá mensagens de erro, das quais poderá derivar o que exatamente deu errado. No meu caso, simplesmente esqueci de definir Copy to output directorycomo Copy Always.


0

@Mitch, Acontece que existe um arquivo com a declaração [assembly: ...], mas não tinha a propriedade ConfigFile.

Depois de adicioná-lo e apontá-lo para Log.config, ele começou a funcionar. Eu teria pensado que funcionaria como todas as outras seções de configuração (ou seja, AppSettings) e aceitaria arquivos de configuração externos sem modificação.

Não temos a segunda instrução que você mencionou, pois a envolvemos em um provedor de log estático global.


0

No meu caso, recebi esta mensagem de erro:

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

E log4net.configo arquivo estava no projeto Visual Studio 2017, mas quando verifiquei o arquivo na bin\Debugpasta não consegui encontrar.

Minha configuração de montagem original era assim:

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

Depois de algum tempo de pesquisa, mudo para o seguinte e funciona:

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

0
  1. adicione o seguinte a AssemblyInfo.cs

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

  1. Certifique-se de que log4net.config esteja incluído no projeto
  2. Nas propriedades de log4net.config

altere Copiar para diretório de saída para copiar se mais recente

  1. Verifique novamente o valor do nível de registro = "ALL"

0

Também vale a pena apontar que em um aplicativo da web ele procura no diretório raiz, não na pasta bin, então certifique-se de que é onde você colocou o arquivo de configuração.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.