Comment ouvrir une session dans le bon contexte, avec de pool de threads threads à l'aide de log4net?
Je suis en train d'essayer de trouver un moyen pour se connecter contexte utile à partir d'un tas de fils. Le problème est que beaucoup de code est traité sur les Événements qui sont arrivés par pool de threads les threads (pour autant que je puisse dire) de sorte que leurs noms ne sont pas en relation avec n'importe quel contexte. Le problème peut être démontré avec le code suivant:
class Program
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
static void Main(string[] args)
{
new Thread(TestThis).Start("ThreadA");
new Thread(TestThis).Start("ThreadB");
Console.ReadLine();
}
private static void TestThis(object name)
{
var nameStr = (string)name;
Thread.CurrentThread.Name = nameStr;
log4net.ThreadContext.Properties["ThreadContext"] = nameStr;
log4net.LogicalThreadContext.Properties["LogicalThreadContext"] = nameStr;
log.Debug("From Thread itself");
ThreadPool.QueueUserWorkItem(x => log.Debug("From threadpool Thread: " + nameStr));
}
}
La Conversion motif:
%date [%thread] %-5level %logger [%property] - %message%newline
La sortie est de la sorte:
2010-05-21 15:08:02,357 [ThreadA] DEBUG LogicalContextTest.Program [{LogicalThreadContext=ThreadA, log4net:HostName=xxx, ThreadContext=ThreadA}] - From Thread itself
2010-05-21 15:08:02,357 [ThreadB] DEBUG LogicalContextTest.Program [{LogicalThreadContext=ThreadB, log4net:HostName=xxx, ThreadContext=ThreadB}] - From Thread itself
2010-05-21 15:08:02,404 [7] DEBUG LogicalContextTest.Program [{log4net:HostName=xxx}] - From threadpool Thread: ThreadA
2010-05-21 15:08:02,420 [16] DEBUG LogicalContextTest.Program [{log4net:HostName=xxx}] - From threadpool Thread: ThreadB
Comme vous pouvez le voir les deux dernières lignes n'ont pas de Noms d'informations utiles pour distinguer les 2 fils, autre que d'ajouter manuellement le nom du message (qui je veux éviter). Comment puis-je obtenir le Nom/Contexte dans le journal pour le pool de threads les threads sans ajouter au message à chaque appel ou qui ont besoin pour définir la propriété de nouveau à chaque rappel.
- D'autres Me - (en Ajoutant ce commentaire en espérant que vous recevrez une notification soit dans mon long commentaire ci-dessous) s'il vous Plaît voir mon commentaire/question à réponse pour votre 4 Nov 2010 commentaire de la réponse par @TskTsk
Vous devez vous connecter pour publier un commentaire.
Les informations de contexte dans log4net est par fil, de sorte que chaque fois que vous démarrez un nouveau fil de discussion, vous devez ajouter vos informations de contexte pour elle. Vous pouvez utiliser les propriétés, ou vous pouvez utiliser la NDC. Le NDC est par thread trop, donc vous devez toujours avoir à l'ajouter à chaque contexte du thread à un certain point, qui pourrait ou pourrait ne pas être ce que vous cherchez. Il serait vous faire économiser de l'ajouter au message en lui-même bien que. Dans votre exemple, il serait quelque chose comme ceci:
Voici un lien vers le documentation de la SDN.
Dans l'ensemble, l'effet est similaire à l'aide des propriétés, tout comme ce que vous avez dans votre exemple. La seule différence est que la SDN peuvent être empilées de sorte que chaque fois que vous poussez une valeur sur la pile, il obtiendra concaténés pour les messages. Il prend également en charge l'instruction d'utilisation, ce qui le rend plus propre code.
De mon pov, la seule possibilité serait de changer le fil de la création à l'intérieur de l'modules car sinon vous ne pouvez pas ajouter de tout contexte.
Si vous pouvez changer le code, vous devez créer une classe qui héritera du Système utilisé.Le filetage de la classe (p. ex. Fil dans votre exemple) et appelle la super-classe et ajouter de l'exploitation forestière contexte.
Il y a quelques autres trucs possible, mais ce serait un propre approche, sans magouilles.
Une option est plutôt que d'un seul statique enregistreur exemple, vous pourriez créer une pour chaque thread par marquage avec le ThreadStatic de l'attribut et de l'initialisation dans une propriété de lecture. Ensuite, vous pouvez ajouter votre contexte de l'enregistreur, et il sera appliqué à chaque entrée de journal une fois que le contexte est défini.
Cependant, si vous souhaitez toujours avoir le problème d'obtenir le contexte défini au sein de chaque thread. Pour cela, je recommande abstraction de la création de votre bûcherons. Utiliser une méthode de fabrique et nécessitent un appel à CreateLogger() pour récupérer une instance de l'enregistreur. Au sein de l'usine, l'utilisation ThreadStatic et définir la ThreadContext la propriété quand un enregistreur est initialisé.
Il nécessite un peu de modification de code, mais pas une tonne.
Plus élaborée option est d'utiliser un AOP (Aspect Oriented Programming) cadre comme LinFu afin d'injecter votre enregistrement souhaité comportement à l'extérieur.
ThreadStatic