La configuración de Log4Net en un archivo externo no funciona

91

Estamos usando log4net y queremos especificar su configuración en un archivo de configuración externo (como lo hemos hecho con otras secciones). Para hacer esto, hemos cambiado la sección log4net en App.config a:

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

Y en el archivo Log.Config (mismo directorio que App.config) tenemos:

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

Sin embargo, cuando ejecutamos la aplicación, no se crea ningún archivo de registro (y no se realiza ningún registro). No hay salida de mensajes de error a la consola.

Si volvemos a mover el contenido del archivo Log.config a App.config (reemplazando la primera línea de código anterior), funciona como se esperaba. ¿Alguna idea de por qué no funciona en un archivo externo?

Robert Wagner
fuente
Me encontré con el mismo problema: ¡probablemente seguimos la misma guía (mal guiada)!
Zach Burlingame
14
Esto es lo que no me gusta de log4net. En mi opinión, el marco de registro debería ser uno de los bits más sólidos de su aplicación, pero log4net a menudo parece ser un poco inestable.
UpTheCreek

Respuestas:

113

¿Tiene el siguiente atributo en su AssemblyInfo.csarchivo:

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

y un código como este al comienzo de cada clase que requiera funcionalidad de registro:

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

Tengo una publicación de blog que contiene esta y otra información aquí .

Trigo Mitch
fuente
17
Esto funciona, asegúrese de crear el archivo log4net.config para establecer la propiedad "Copiar al directorio de salida" en "Copiar siempre".
E. van der Spoel
@mitchwheat Absolutamente como Dios, he estado luchando con una solución basada en ninject para hacer exactamente lo que esto hace todo el día ... ¡gracias tío!
Guerra
39

Hay un defecto abierto en este tema. Log4Net no admite el atributo configSource de los elementos de configuración. Para usar una solución de archivo puramente de configuración, use la clave log4net.Config en appSettings.

Paso 1: Incluya la definición de la sección de configuración normal:

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

Paso 2: Use la clave mágica log4net.Config en appSettings.

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

Paso 3: Contribuya con un parche para corregir el manejo de configSource.

Precipitado
fuente
5
Una llamada a log4net.Config.XmlConfigurator.Configure (); debería superar este problema sin leer configSource
Greg Domjan
Esto no cambió nada para mí. Aún no he resuelto el problema, pero intentaré hacer un seguimiento.
Don Rolling
5
Es importante marcar el archivo de configuración log4net como "copiar si es más reciente". Si el archivo de configuración no se copia en la carpeta bin, no funcionará.
Francisco Goldenstein
Esto funcionó para mí tal como está, y lo prefiero a la solución aceptada porque algunas de mis bibliotecas se usan en una aplicación web donde el registro se configura en un log4net.config separado y, a veces, se usa en una aplicación independiente donde el registro está configurado en app.exe.config. De esta manera, todo está en la configuración en lugar de en la información del ensamblaje - No quiero "codificarlo" en log4net.config
Danny
27

El paso que se ha perdido es

log4net.Config.XmlConfigurator.Configure(); 

esto hará que se utilice configSource. Asegúrese de llamarlo una vez antes de llamar a GetLogger ();

Greg Domjan
fuente
No necesita hacer esto si usa la solución de Mitch Wheat.
Robert Wagner
4
@Robert: Claro, aunque la solución de Mitch Wheat requiere codificar el archivo de configuración fuera de app.config. Leí que la pregunta original era por qué configSource no funciona, funciona si se sigue este paso adicional.
Greg Domjan
Me gusta más este enfoque, especialmente porque creo un controlador de registro contenedor que usa internamente log4net (que podría reemplazarse más adelante), luego, en este controlador de registro contenedor, siempre llamo a log4net.Config.XmlConfigurator.Configure (). De esta manera, cualquier proyecto con su propia app.config podría usar este controlador de registro contenedor, sin necesidad de cambiar ensamblador.cs
zheng yu
19

Asegúrese de que su archivo log4net.config tenga las siguientes propiedades:

Acción de compilación: contenido

Copiar al directorio de salida: Copiar siempre

Lewis Moten
fuente
10

O use,

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

o solo,

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

En ambos casos, el archivo Log4Net.config debería estar en el directorio de salida. Puede hacer esto configurando las propiedades del archivo Log4Net.config en el explorador de soluciones. Acción de compilación: contenido y copia en el directorio de salida: copiar siempre

Byju
fuente
no necesita la etiqueta <configSections> para el primer caso
disklosr
2

Cuidado con este problema ...

En mi caso todo estaba configurado correctamente. El problema es que utilicé Web Deploy dentro de Visual Studio 2013 para cargar el sitio en WinHost.com y restableció las ACL en el servidor. Esto, a su vez, revocó todos los permisos sobre carpetas y archivos: log4net no pudo escribir el archivo.

Puedes leer más sobre esto aquí:

Cómo evitar que Web Deploy / MSBuild arruine los permisos del servidor

Le pedí al equipo de soporte que restableciera las ACL y luego log4net comenzó a escupir registros. :)

Leniel Maccaferri
fuente
1

Suponiendo que tenía un archivo de configuración externo llamado log4net.config que se copia en su directorio de implementación, puede configurarlo así:

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

Tuve el mismo problema, además de tener

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

en el proyecto en ejecución, también tenía la siguiente línea en un proyecto de referencia:

[assembly: log4net.Config.XmlConfigurator]

Cuando eliminé esta línea en los proyectos a los que se hace referencia, los registros comienzan a aparecer.

El invitado
fuente
1

También es posible activar un modo de depuración para log4net. Inserte esto en el archivo 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>

y al menos obtendrá mensajes de error, a partir de los cuales puede derivar exactamente qué salió mal. En mi caso, simplemente se olvidó de ajustar Copy to output directorya Copy Always.

waka
fuente
0

@Mitch, resulta que hay un archivo con la declaración [assembly: ...], pero no tenía la propiedad ConfigFile.

Una vez que lo agregué y lo apunté a Log.config, comenzó a funcionar. Pensé que funcionaría como todas las demás secciones de configuración (es decir, AppSettings) y aceptaría archivos de configuración externos sin modificaciones.

No tenemos la segunda declaración que mencionó, ya que la incluimos en un proveedor de registro estático global.

Robert Wagner
fuente
0

En mi caso, recibí este mensaje de error:

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

Y log4net.configel archivo estaba en el proyecto Visual Studio 2017, pero cuando verifiqué el archivo en la bin\Debugcarpeta no pude encontrarlo.

Mi configuración de ensamblaje original era así:

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

Después de un tiempo de investigación, lo cambio a lo siguiente y funciona:

[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"..\..\log4net.config", Watch = true)]
maytham-ɯɐɥʇʎɐɯ
fuente
0
  1. agregar lo siguiente a AssemblyInfo.cs

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

  1. Asegúrese de que log4net.config esté incluido en el proyecto
  2. En propiedades de log4net.config

cambie Copiar al directorio de salida a Copiar si es más reciente

  1. Verifique dos veces el valor de nivel de nivel de registro = "TODOS"
e03050
fuente
0

También vale la pena señalar que en una aplicación web se busca en el directorio raíz, no en la carpeta bin, así que asegúrese de que ahí es donde coloca el archivo de configuración.

Ricardo
fuente