Forma correcta de usar log4net (nomenclatura del registrador)

83

Hay dos formas de configurar y utilizar log4net. El primero es cuando puedo configurar mi propio appender y registrador asociado:

<!-- language: xml -->

<appender name="myLogAppender" type="log4net.Appender.RollingFileAppender" >
    <file value="Logs\myLog.log" />
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %level - %message%n" />
    </layout>
</appender>

<logger name="myLog">
    <level value="All"></level>
    <appender-ref ref="myLogAppender" />
</logger>

Y luego, cuando quiero escribir algo en el registro, puedo hacer lo siguiente:

ILog log = LogManager.GetLogger("myLog");
log.Info("message");

Otra forma de usarlo es configurar root para que sea tan detallado como desee:

<!-- language: xml -->

<root>
    <level value="Error" />
    <appender-ref ref="myLogAppender" />
</root>

Y en este caso puedo registrar mensajes como este:

ILog log = LogManager.GetLogger(typeof(Bar));
log.Info("message");

Los beneficios del segundo enfoque es que puede habilitar o deshabilitar algunos mensajes sobre la marcha. Pero el problema es que estoy desarrollando en EPiServer CMS y tiene su propio sistema de registro que usa log4net y si habilito el registro de información en el nivel raíz, se escribirán muchos registros del sistema.

¿Cómo se usa log4net? Cada parte de un sistema escribe en su propio registrador, o todo está escrito en el registrador predeterminado, y la configuración decide qué hacer a continuación.

Astuto
fuente

Respuestas:

96

Con respecto a cómo registra los mensajes dentro del código, optaría por el segundo enfoque:

ILog log = LogManager.GetLogger(typeof(Bar));
log.Info("message");

Donde los mensajes enviados al registro anterior serán 'nombrados' usando el tipo completamente calificado Bar, por ejemplo

MyNamespace.Foo.Bar [INFO] message

La ventaja de este enfoque es que es el estándar de facto para organizar el registro, también le permite filtrar sus mensajes de registro por espacio de nombres. Por ejemplo, puede especificar que desea registrar el mensaje de nivel INFO, pero elevar el nivel de registro Barespecíficamente a DEBUG:

<log4net>
    <!-- appenders go here -->
    <root>
        <level value="INFO" />
        <appender-ref ref="myLogAppender" />
    </root>

    <logger name="MyNamespace.Foo.Bar">
        <level value="DEBUG" />
    </logger>
</log4net>

La capacidad de filtrar su registro a través del nombre es una característica poderosa de log4net, si simplemente registra todos sus mensajes "myLog", ¡pierde gran parte de este poder!

Con respecto al EPiServer CMS, debería poder utilizar el enfoque anterior para especificar un nivel de registro diferente para el CMS y su propio código.

Para leer más, aquí hay un artículo de proyecto de código que escribí sobre el registro:

ColinE
fuente
5
Incluso puede excluir del registro parte de los espacios de nombres de clases para reducir el ruido en los registros utilizando PatternLayout logging.apache.org/log4net/release/sdk/… "Por ejemplo, para el nombre del registrador" abc ", el patrón% logger {2} salida "bc". "
AlfeG
7
registro de ILog de solo lectura estático privado = LogManager.GetLogger (System.Reflection.MethodBase.GetCurrentMethod (). DeclaringType);
Casper Leon Nielsen
¿Por qué el segundo enfoque es mejor que el primero? El nombre de la clase es estático, y si lo cambia, también tendrá que actualizar el nombre en el registrador, ¿tiene algún sentido provocar una llamada de reflexión solo para obtener el nombre de la clase?
MeTitus
1
@CasperLeonNielsen ¿Puedes explicar en qué se diferencia de eso this.GetType()?
ErikE
2
@ErikE this.GetType () no estará disponible al definir una propiedad estática, o en una clase estática, o fuera de un constructor.
dhochee
11

Mi respuesta puede llegar tarde, pero creo que puede ayudar a los novatos. No verá los registros ejecutados a menos que los cambios se realicen como se indica a continuación.

2 Los archivos deben modificarse al implementar Log4net.


  1. Agregue la referencia de log4net.dll en el proyecto.
  2. app.config
  3. Archivo de clase donde implementará Logs.

Dentro de [ app.config ]:

Primero, en 'configSections', debe agregar el siguiente fragmento de código;

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

Luego, en el bloque de 'configuración', debe escribir el fragmento de código a continuación (este fragmento de código está personalizado según mis necesidades, pero funciona a la perfección).

<log4net debug="true">
    <logger name="log">
      <level value="All"></level>
      <appender-ref ref="RollingLogFileAppender" />
    </logger>

    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
      <file value="log.txt" />
      <appendToFile value="true" />
      <rollingStyle value="Composite" />
      <maxSizeRollBackups value="1" />
      <maximumFileSize value="1MB" />
      <staticLogFileName value="true" />

      <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date %C.%M [%line] %-5level - %message %newline %exception %newline" />
      </layout>
    </appender>
</log4net>

Clase de llamada interna :

Dentro de la clase donde va a usar este log4net, debe declarar el siguiente fragmento de código.

 ILog log = LogManager.GetLogger("log");

Ahora, está listo el registro de llamadas donde quiera en esa misma clase. A continuación se muestra uno de los métodos que puede llamar mientras realiza operaciones.

log.Error("message");
Ankur Soni
fuente
No necesitas hacer ILogun miembro de instancia, ¿verdad? He hecho la misma pregunta con más detalle aquí, pero tal vez pueda obtener su opinión.
Minh Tran
5

En lugar de nombrar mi clase de invocación, comencé a usar lo siguiente:

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

De esta manera, puedo usar la misma línea de código en cada clase que usa log4net sin tener que recordar cambiar el código cuando copio y pego. Alternativamente, podría crear una clase de registro y hacer que todas las demás clases heredaran de mi clase de registro.

Agente RhoShambo
fuente
0

La desventaja del segundo enfoque es un gran repositorio con registradores creados. Estos registradores hacen lo mismo si la raíz está definida y los registradores de clases no están definidos. El escenario estándar en el sistema de producción está utilizando pocos registradores dedicados al grupo de clase. Lo siento por mi ingles.

usuario1785960
fuente