Comment utiliser log4net avec dependency injections

J’essaie de comprendre quel est le bon choix et l’utilisation de log4net avec un cadre d’dependency injection.

Log4Net utilise l’interface ILog mais exige que je l’appelle

LogManager.GetLogger(Reflection.MethodBase.GetCurrentMethod().DeclaringType) 

dans chaque classe ou méthode où je dois enregistrer des informations. Cela semble aller à l’encontre des principes de l’IoC et m’associe à l’utilisation de Log4Net.

Dois-je en quelque sorte mettre une autre couche d’abstraction quelque part?

De plus, je dois enregistrer les propriétés personnalisées comme le nom d’utilisateur actuel, comme ceci:

 log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName; 

Comment puis-je encapsuler cela afin de ne pas avoir à me souvenir de le faire à chaque fois et de toujours conserver la méthode en cours d’enregistrement? devrais-je faire quelque chose comme ceci ou suis-je totalement absent de la marque?

 public static class Logger { public static void LogException(Type declaringType, ssortingng message, Exception ex) { log4net.ThreadContext.Properties["userName"] = ApplicationCache.CurrentUserName; ILog log = LogManager.GetLogger(declaringType); log.Error(message, ex); } } 

Je pense que vous ne voyez pas la forêt pour les arbres ici. ILog et LogManager sont une façade légère équivalant presque à 1: 1 à la journalisation Apache commons, et ne couplent pas réellement votre code au rest de log4net.


J’ai aussi constaté que presque toujours, quand quelqu’un crée un wrapper MyCompanyLogger autour de log4net, il manque mal le point et perd des capacités importantes et utiles du framework, perd des informations utiles, perd les gains de performances possibles même avec l’interface ILog simplifiée. Ou tout ce qui précède. En d’autres termes, enrouler log4net pour éviter le couplage est un anti-pattern .

Si vous ressentez le besoin de l’injecter, rendez votre instance de journalisation accessible via une propriété pour activer l’injection, mais créez une instance par défaut à l’ancienne.

Comme pour inclure l’état contextuel dans chaque message de journal, vous devez append une propriété globale dont ToSsortingng() résout ce que vous recherchez. Par exemple, pour la taille de segment de mémoire actuelle:

 public class TotalMemoryProperty { public override ssortingng ToSsortingng() { return GC.GetTotalMemory(false).ToSsortingng(); } } 

Ensuite, pour le twigr au démarrage:

 GlobalContext.Properties["TotalMemory"] = new TotalMemoryProperty(); 

Comment je l’ai fait était de créer ma propre interface, et une classe implémentait cette interface qui utilisait Log4Net et injectait cette classe. De cette façon, vous n’êtes pas lié à Log4Net … vous pouvez simplement créer une autre classe pour un nouveau logger et injecter cette classe.

Si vous êtes vraiment soucieux d’avoir plusieurs enregistreurs, vous pouvez toujours déclarer un enregistreur global et l’appeler pour tous vos besoins de journalisation. L’inconvénient de ceci est que vous perdez la capacité intégrée d’identifier la classe à l’origine du journal, mais vous pouvez également injecter votre propre message personnalisé dans le journal pour identifier la classe.

Cela dépend de la robustesse de la journalisation. Vous pouvez aussi simplement mettre l’enregistreur dans la classe principale et laisser toutes les exceptions non gérées s’y coller pour la journalisation.

Une autre façon de le faire serait de câbler la séquence d’enregistrement du conteneur d’interface log4net ILog comme ceci: (en utilisant Castle dans un contexte ASP.NET ci-dessous à titre d’exemple)

 container.Register(Component.For().LifeStyle .PerWebRequest.UsingFactoryMethod(() => LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType))); 

et juste injecter des constructeurs quand vous en avez besoin.