Configurar un destino de log alternativo en caso de fallo con NLog

por May 31, 2020Desarrollo de Software0 Comentarios

Cuando hacemos log en una aplicación lógicamente no queremos perdernos ningún mensaje de log, y esto puede ocurrir, puede fallar el log de una aplicación. A continuación vamos a configurar NLog con un destino alternativo de log en caso de fallo.

Imaginemos que estamos guardando los mensajes de log en bases de datos y hay algún mensaje que excede la longitud de un campo, o simplemente que la base de datos deja de funcionar. Lo ideal sería poder guardar igualmente esos mensajes de log, por ejemplo en un fichero de texto.

Crear Target de log alternativo en caso de fallo con NLog

NLog tiene un Target especial llamado FallbackGroup, sirve para tener un destino de log altervativo (o varios) en caso de fallo.

Es un destino o target con varios a su vez en su interior ordenados según lo que queramos. En este caso el primer destino sería la base de datos y el alternativo el fichero csv colocado en segundo lugar.

Con el parámetro returnToFirstOnSuccess se indica volver al primer destino cuando logra hacer log correcto con uno de ellos. El comportamiento en caso de fallo sería el siguiente.

  1. Falla un mensaje de log con la base de datos.
  2. Se intenta en segundo lugar con el target de fichero csv.
  3. Si va bien, los siguientes mensajes de log se intentarán de nuevo con la base de datos.
<targets>
  <target xsi:type="FallbackGroup" name="all" returnToFirstOnSuccess="true">
    <!-- First Target Database -->
    <target name="Database" xsi:type="Database" keepConnection="false"
        dbProvider="Oracle.ManagedDataAccess.Client.OracleConnection, Oracle.ManagedDataAccess"
        connectionString="User Id=nombre;Password=pass;Data Source=IP:Port/orcl" commandType="Text">
      <commandText>
        INSERT INTO TABLE_LOG
        (DATE_, APP, VERSION, MESSAGE) VALUES(:date_time, :app_, :app_version, :message)
      </commandText>
      <parameter name="date_time" layout="${date:format=dd/MM/yyyy HH\:mm\:ss,fff}" />
      <parameter name="app_" layout="${AppName}" />
      <parameter name="app_version" layout="${assembly-version}" />
      <parameter name="message" layout="${message}" />
    </target>
      
    <!-- Second Target if fails -->
    <target name="csvFile" xsi:type="File" encoding="utf-8"
        fileName="${basedir}/logs/csvLog.csv"
        archiveFileName="${basedir}/logs/csvLog.{#}.csv"
        archiveAboveSize="4000000"
        archiveNumbering="DateAndSequence"
        archiveDateFormat="yyyyMMdd">
      <layout xsi:type="CsvLayout" delimiter="Semicolon" withHeader="true">
        <column name="DateTime" layout="${longdate}" />
        <column name="App" layout="${AppName}" />
        <column name="Version" layout="${assembly-version}" />
        <column name="Message" layout="${message}" />
      </layout>
    </target>
  </target>
</targets>

Cómo usar el Target configurado

Dado el que el Target que hemos configurado va identificado con un nombre como un Target normal de NLog para usarlo simplemente hay que hacer referencia a su nombre en la sección rules del fichero xml de NLog.

<rules>
  <logger name="*" minlevel="Trace" writeTo="all" />
</rules>

Espero que os sea de utilidad la guía, es muy útil tener destinos alternativos para los mensajes de log, de esta manera evitaremos al máximo perdernos mensajes importantes de log.