Iniciar sesión en varios archivos usando NLog

Estoy usando NLog para fines de registro.

Mi código es el siguiente:

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

  <!-- make sure to set 'Copy To Output Directory' option for this file -->
  <!-- go to http://nlog-project.org/wiki/Configuration_file for more information -->

  <targets>
    <target
      name="logfile"
      xsi:type="File"
      layout="${message}"
      fileName="${basedir}../Data/debugLog1.txt"
      archiveAboveSize ="5000000"
      maxArchiveFiles="2"/>
  </targets>

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

estoy registrando datos debugLog1.txt. Ahora, desde otra ubicación en el proyecto, también quiero registrar datos, pero estos datos son de otro tipo, así que quiero hacer una debugLog2.txt y registrar datos en él. ¿Cómo puedo modificar mi código anterior para hacerlo?

preguntado el 03 de diciembre de 13 a las 13:12

6 Respuestas

Creo que necesitas definir otro registrador.

<logger name="SpecialLogger" minlevel="Trace" writeTo="logfile2" />

Para iniciar sesión:

var logger = LogManager.GetLogger("SpecialLogger");

respondido 09 nov., 20:00

¿Cómo se puede definir programáticamente? - Giox

@glox vea mi respuesta a continuación... Tuve la misma situación y desarrollé una solución... - inspirado digitalmente

Si desea un archivo separado para registrar información de otra parte de su programa, puede agregar un registrador y otro objetivo.

Por ejemplo, si tiene un programa que está completando dos tareas diferentes y desea registrar esas tareas por separado, puede hacer lo siguiente

<targets>
  <target
    name="task1File"
    xsi:type="File"
    layout="${message}"
    fileName="${basedir}../Data/debugLog1.txt"
    archiveAboveSize ="5000000"
    maxArchiveFiles="2"/>
  <target
    name="task2File"
    xsi:type="File"
    layout="${message}"
    fileName="${basedir}../Data/debugLog2.txt"
    archiveAboveSize ="5000000"
    maxArchiveFiles="2"/>
</targets>

<rules>
  <logger name="task1Logger" minlevel="Trace" writeTo="task1File" />
  <logger name="task2Logger" minlevel="Trace" writeTo="task2File" />
</rules>

Luego, en su programa, acceda a ellos con:

var task1Logger = NLog.LogManager.GetLogger("task1Logger")
var task2Logger = NLog.LogManager.GetLogger("task2Logger")

respondido 09 nov., 20:00

¿Alguna forma sensata de hacer esto usando la interfaz ILogger? - yungdeiza

Tuve una situación similar en la que tuve que generar archivos de registro aleatorios para casos especiales y esto es lo que creé.

Llamé al siguiente código para crear tres archivos.

Llamador

    var log1 = NLogAdapter.CreateCustomLogger("CustomLog1");
    var log2 = NLogAdapter.CreateCustomLogger("CustomLog2");
    var log3 = NLogAdapter.CreateCustomLogger("CustomLog3");
    log1.Error("Error1");
    log2.Error("Error2");
    log3.Error("Error3");

Resultados:

enter image description here

NOTA: ESTE ENFOQUE RESUELVE EL PROBLEMA de "los mismos registros de errores escritos en varios archivos". Cada instancia creada por estos métodos estará completamente aislada de otras instancias sin escritura cruzada de entradas de registro.

Código fuente:

        /// <summary>
    /// Create Custom Logger using parameters passed.
    /// </summary>
    /// <param name="name">Name of file.</param>
    /// <param name="LogEntryLayout">Give "" if you want just message. If omited will switch to full log paramaters.</param>
    /// <param name="logFileLayout">Filename only. No extension or file paths accepted.</param>
    /// <param name="absoluteFilePath">If you want to save the log file to different path thatn application default log path, specify the path here.</param>
    /// <returns>New instance of NLog logger completly isolated from default instance if any</returns>
    public static Logger CreateCustomLogger(string name = "CustomLog",
        string LogEntryLayout = "${ date:format=dd.MM.yyyy HH\\:mm\\:ss.fff} thread[${threadid}] ${logger} (${level:uppercase=true}): ${message}. ${exception:format=ToString}",
        string logFileLayout = "logs/{0}.${{shortdate}}.log",
        string absoluteFilePath = "")
    {
        var factory = new LogFactory();
        var target = new FileTarget();
        target.Name = name;
        if (absoluteFilePath == "")
            target.FileName = string.Format(logFileLayout, name);
        else
            target.FileName = string.Format(absoluteFilePath + "//" +logFileLayout, name);
        if (LogEntryLayout == "") //if user specifes "" then use default layout.
            target.Layout = "${message}. ${exception:format=ToString}";
        else
            target.Layout = LogEntryLayout;
        var defaultconfig = LogManager.Configuration;
        var config = new LoggingConfiguration();
        config.AddTarget(name, target);

        var ruleInfo = new LoggingRule("*", NLog.LogLevel.Trace, target);

        config.LoggingRules.Add(ruleInfo);

        factory.Configuration = config;

        return factory.GetCurrentClassLogger();
    }

    /// <summary>
    /// Create Custom Logger using a seperate configuration file.
    /// </summary>
    /// <param name="name">Name of file.</param>
    /// <returns>New instance of NLog logger completly isolated from default instance if any</returns>
    public static Logger CreateCustomLoggerFromConfig(string configname)
    {
        var factory = new LogFactory(new XmlLoggingConfiguration(configname));
        return factory.GetCurrentClassLogger();
    }

Respondido el 18 de junio de 20 a las 20:06

Tenga en cuenta que podría usar renderizadores de diseño en el nombre del archivo (incluso renderizadores de diseño personalizado) y entonces esto también creará múltiples archivos:

 <target
      name="logfile"
      xsi:type="File"
      layout="${message}"
      fileName="${basedir}../Data/${level}.txt" 
      ...
   />

En este ejemplo, es un archivo de registro para cada nivel de registro (fatal, error, advertencia, información, depuración, seguimiento)

Respondido el 23 de junio de 19 a las 22:06

Si aún desea poder usar el conveniente método GetCurrentClassLogger, puede filtrar los mensajes de registro para ir al destino correcto usando los espacios de nombres en su proyecto como filtro.

Digamos que tiene espacios de nombres que comienzan con fooA y espacios de nombres que comienzan con fooB. Entonces su archivo NLog.config se vería así:

<targets>
   <target name="fooAlog" 
           xsi:type="File" 
           fileName="${basedir}/logs/fooA.log" />
   <target name="fooBlog" 
           xsi:type="File" 
           fileName="${basedir}/logs/fooB.log" />
</targets>

<rules>
    <logger name="fooA.*" minlevel="Trace" writeTo="fooAlog" />
    <logger name="fooB.*" minlevel="Trace" writeTo="fooBlog" />
</rules>

Y en su código, simplemente agregue un registrador en cada clase que desee registrar:

private static Logger logger = LogManager.GetCurrentClassLogger();

Siempre que sus espacios de nombres sean coherentes, los mensajes de registro se filtrarán al archivo correcto y obtendrá una pequeña etiqueta de clase agradable en sus mensajes de registro para indicarle dónde ocurrió el evento de registro.

respondido 09 nov., 20:00

No entiendo, ¿cómo puede el nlog saber a qué archivo apuntar? Los espacios de nombres de los que habla son el espacio de nombres de destino del archivo de registro, no el espacio de nombres de su programa @Randyshirts - datboydozy

Aquí hay un ejemplo más complejo para cuando desea tener un archivo de registro por subproceso (para procesos en segundo plano, por ejemplo):

  1. Agregue esta línea al comienzo del hilo que desea iniciar sesión en un archivo separado:

    MappedDiagnosticsLogicalContext.Set("BackgroundProcess", true);
    
    public void StartRetryMechanism()
    {
        BackgroundTaskManager.Run(() =>
        {
            Start();
        });            
    }
    
    private void Start()
    {
            MappedDiagnosticsLogicalContext.Set("BackgroundProcess", true);
            ...
    }
    
  2. Luego, en la configuración de NLog, puede filtrar en la variable "BackgroundProcess":

    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true">
      <targets>
        <target name="file" xsi:type="File" layout="${longdate} ${level} ${logger} ${threadid} ${message} ${exception:format=tostring}" fileName="${basedir}/logs/Application.log" keepFileOpen="false" encoding="iso-8859-2" archiveFileName="${basedir}/logs/Application_${shortdate}.{##}.log" archiveNumbering="Sequence" archiveEvery="Day" archiveAboveSize="10857600" maxArchiveFiles="3" />
      </targets>
      <targets>
        <target name="backgroundProcessFile" xsi:type="File" layout="${longdate} ${level} ${logger} ${threadid} ${message} ${exception:format=tostring}" fileName="${basedir}/logs/BackgroundProcess.log" keepFileOpen="false" encoding="iso-8859-2" archiveFileName="${basedir}/logs/BackgroundProcess_${shortdate}.{##}.log" archiveNumbering="Sequence" archiveEvery="Day" archiveAboveSize="10857600" maxArchiveFiles="3" />
      </targets>
      <rules>
        <logger name="*" minlevel="Trace" writeTo="backgroundProcessFile">
          <filters>
            <when condition="'${mdlc:item=BackgroundProcess}' != true" action="Ignore" />
          </filters>
        </logger>
        <logger name="*" minlevel="Trace" writeTo="file">
          <filters>
            <when condition="'${mdlc:item=BackgroundProcess}' == true" action="Ignore" />
          </filters>
        </logger>
      </rules>
    </nlog>
    

respondido 09 nov., 20:00

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.