web-dev-qa-db-fra.com

Mettre à jour le nom de fichier cible NLog au moment de l'exécution

Dans mon application, je travaille sur plusieurs milliers de documents par jour. Je voudrais, dans certains cas, quelques journaux, un journal par document. Ensuite, j'aimerais que, pour une cible spécifique, modifie le nom de fichier de sortie (et uniquement le nom de fichier) à l'exécution.

Sur le Web, j'ai trouvé comment créer une cible en me programmant. J'aimerais simplement mettre à jour un nom de fichier en le programmant. J'ai essayé le code ci-dessous. L'erreur que je reçois est "LayoutRender est introuvable" logDirectory ".

Une idée ?

Merci,

var target = (FileTarget)LogManager.Configuration.FindTargetByName("logfile");
target.FileName = "${logDirectory}/file2.txt";

LoggingConfiguration config = new LoggingConfiguration();
var asyncFileTarget = new AsyncTargetWrapper(target);
config.AddTarget("logfile", asyncFileTarget);

LogManager.Configuration = config;

Le fichier de configuration est:

  <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <variable name="logDirectory" value="C:/MyLogs"/>
    <targets>
      <target name="logfile" xsi:type="File" layout="${date:format=dd/MM/yyyy HH\:mm\:ss.fff}|${level}|${stacktrace}|${message}" fileName="${logDirectory}/file.txt" />
    </targets>

    <rules>
      <logger name="*" minlevel="Info" writeTo="logfile" />
    </rules>    
  </nlog>
16
Kris-I

Essayez la méthode ReconfigExistingLoggers:

var target = (FileTarget)LogManager.Configuration.FindTargetByName("logfile");
target.FileName = "${logDirectory}/file2.txt";
LogManager.ReconfigExistingLoggers();

Comme écrit dans docs:

Boucle à travers tous les enregistreurs précédemment renvoyés par GetLogger. et recalcule leur liste de cibles et de filtres. Utile après avoir modifié le configuration par programme pour s’assurer que tous les enregistreurs ont été correctement configuré.

MODIFIER:

Essayez d’utiliser le rendu de présentation personnalisé: Le fichier de configuration NLog pour obtenir les valeurs des paramètres de configuration depuis un fichier web.config

19
Tony

Tony's la solution ne semble pas fonctionner si vous utilisez NLog Async (<targets async="true">). J'ai dû utiliser la cible wrapper pour obtenir mon FileTarget, sinon je reçois beaucoup d'erreurs. J'utilise NLog 2.1.

if (LogManager.Configuration != null && LogManager.Configuration.ConfiguredNamedTargets.Count != 0)
{
    Target target = LogManager.Configuration.FindTargetByName("yourFileName");
    if (target == null)
    {
        throw new Exception("Could not find target named: " + "file");
    }

    FileTarget fileTarget = null;
    WrapperTargetBase wrapperTarget = target as WrapperTargetBase;

    // Unwrap the target if necessary.
    if (wrapperTarget == null)
    {
        fileTarget = target as FileTarget;
    }
    else
    {
        fileTarget = wrapperTarget.WrappedTarget as FileTarget;
    }

    if (fileTarget == null)
    {
        throw new Exception("Could not get a FileTarget from " + target.GetType());
    }

    fileTarget.FileName = "SetFileNameHere";
    LogManager.ReconfigExistingLoggers();
}

Cela ne change pas non plus le fichier de configuration, mais simplement la valeur d'exécution. Donc, j'édite aussi manuellement le fichier de configuration à ma nouvelle valeur en utilisant le code ci-dessous:

var nlogConfigFile = "NLog.config";
var xdoc = XDocument.Load(nlogConfigFile);
var ns = xdoc.Root.GetDefaultNamespace();
var fTarget = xdoc.Descendants(ns + "target")
         .FirstOrDefault(t => (string)t.Attribute("name") == "yourFileName");
fTarget.SetAttributeValue("fileName", "SetFileNameHere");
xdoc.Save(nlogConfigFile);
3
Baddack

Si vous n'avez pas besoin de changer LogDirectory au moment de l'exécution, procédez comme suit:

target.FileName = "${var:logDirectory}\\file2.txt");

Si vous avez besoin de modifier le logDirectory au moment de l'exécution, utilisez le GDC:

https://github.com/NLog/NLog/wiki/Gdc-layout-renderer

NLog.GlobalDiagnosticsContext.Set("logDirectory","C:\Temp\");

Ensuite, vous pouvez utiliser la disposition suivante:

target.FileName = "${gdc:item=logDirectory}\\file2.txt";
2
Rolf Kristensen

L'erreur est due au fait que NLog ne sait rien du nom de clé "logDirectory". Vous pouvez le mettre en œuvre vous-même (lisez les instructions ici ) ou utilisez celles prédéfinies de ici .

Ensuite, vous pouvez utiliser les instructions de ici pour modifier les cibles NLog en cours d’exécution.

1
kravasb

J'ai écrit une réponse qui correspond à votre question aussi .

Au lieu d'essayer de réécrire la configuration, vous feriez mieux de créer simplement une configuration vous permettant de choisir dynamiquement le nom de fichier souhaité.


Un exemple adapté à votre cas d'utilisation:

Logger myLog = LogManager.GetLogger(name);
LogLevel level = LogLevel.Error;
string message = "This is an error message!";

Vous transformez cette information en un objet LogEventInfo:

LogEventInfo logEvent = new LogEventInfo(level , myLog.Name, message);

Vous pouvez ensuite ajouter des propriétés à cet événement (les index de chaîne sont libres de choisir): 

logEvent.Properties["CustomFileName"] = "mycustomfilename";

Et puis vous écrivez dans le journal:

myLog.Log(logEvent);

La chose intéressante ici est que dans votre configuration NLog, vous pouvez utiliser cette propriété personnalisée dans tout champ que la documentation Nlog appelle une valeur "Layout"

Vous utilisez ${event-properties:item=CustomFileName} dans la présentation pour accéder à la propriété. Par exemple:

<target xsi:type="File" 
        name="file" 
        fileName="${basedir}/logs/${event-properties:item=CustomFileName}.log"
        layout="${message}" />

Suivant l'exemple posté, ce message sera consigné dans le fichier mycustomfilename.log. Cela vous permet de changer dynamiquement votre fichier cible à votre guise en définissant la valeur logEvent.Properties["CustomFileName"] avec le nom de fichier que vous souhaitez utiliser.

Notez que vous pouvez l'optimiser davantage et que, par exemple, vous ne pouvez choisir qu'une partie du nom de fichier.

L'avantage supplémentaire est que vous n'avez besoin que de une cible et d'une règle dans votre fichier de configuration pour que cela fonctionne.

0
Flater

Pour ceux qui sont bloqués là-dessus, j'ai finalement trouvé une solution. J'essayais de mettre à jour certains paramètres de cible syslog au moment de l'exécution et rien ne fonctionnait. La simple mise à jour de la configuration ne fonctionne pas, vous devez réinitialiser l'objet Configuration, ce qui est aussi simple que cela:

LogManager.Configuration = LogManager.Configuration;

Cela provoque un événement interne à déclencher et à utiliser réellement la configuration mise à jour.

0
Mark