2011-08-05 4 views
9

J'ai une application de service qui, au démarrage, lit un fichier XML et démarre un thread pour chaque entrée dans le fichier XML. Chaque thread crée une instance d'une classe de worker qui nécessite un logger pour consigner toute sortie dans un fichier journal spécifique au thread.Connexion à un fichier journal individuel pour chaque thread individuel

Dans les services app.config j'ai les paramètres de configuration de log4net configuré pour utiliser un XML appender et le fichier est spécifié comme chaîne_métacaractères comme indiqué ci-dessous:

<appender name="XmlAppender" type="log4net.Appender.FileAppender"> 
    <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" /> 
    <immediateFlush value="true"/> 
    <appendToFile value="true" /> 
    <layout type="log4net.Layout.SimpleLayout" /> 
</appender> 

Dans un mode de verrouillage de fil pour chaque instance de la classe de travail créée Je reçois le logger en utilisant la méthode log4net.LogManager.GetLogger("MyLogger") et ensuite je règle la propriété threads PatternStrings LogName courante en utilisant ThreadContext.Properties["LogName"] = "Log name prefix".

Tous les fichiers sont créés mais lorsque l'enregistreur est appelé, il enregistre simplement tous les messages dans un fichier apparemment aléatoire.

J'ai cherché pendant un bon moment à essayer de trouver une solution ou des réponses à ce que je fais mal mais je n'ai pas eu de chance.

Est-ce que quelqu'un a une idée de ce qui se passe?

Répondre

12

Je pense avoir résolu le problème. Les étapes sont les suivantes:

  • Créez un individu nommé LoggerRepository sur chaque thread.
  • Définissez la propriété ThreadContexts pour le nom du fichier journal.
  • Utilisez XmlConfiguratior pour configurer le référentiel.
  • Utilisez le LogManager pour obtenir le consignateur nommé (dans le fichier de configuration XML) en utilisant le LoggerRepository nommé pour ce thread.

En retour, je reçois un nouveau logger configuré pointant vers le fichier correspondant pour ce thread.

La configuration XML est le même que celui à l'origine et montré ici pour être complet:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections>  
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net"/> 
    </configSections> 
    <log4net> 
    <logger name="ProductionLogger"> 
     <appender-ref ref="XmlAppender"/>  
     <level value="ALL"/> 
    </logger> 
    <appender name="XmlAppender" type="log4net.Appender.FileAppender"> 
     <file type="log4net.Util.PatternString" value="D:\Temp\Logs\%property{LogName}.log" /> 
     <immediateFlush value="true"/> 
     <appendToFile value="true" /> 
     <layout type="log4net.Layout.SimpleLayout" /> 
    </appender> 
    </log4net> 
</configuration> 

Le code pour créer les enregistreurs est ci-dessous. Chaque fois que ce code est exécuté, il est exécuté dans son propre thread.

ILoggerRepository loggerRepository = LogManager.CreateRepository(logFileName + "Repository"); 
ThreadContext.Properties["LogName"] = logFileName; 
log4net.Config.XmlConfigurator.Configure(loggerRepository); 
ILog logger = LogManager.GetLogger(logFileName + "Repository", "ProductionLogger"); 

Cela semble fonctionner sans problèmes jusqu'à présent. Je vais aller de l'avant avec cette solution pour le moment mais je mettrai à jour ce post si je découvre autre chose.

+1

Un grand merci! J'ai eu le même problème avec le filetage et la connexion dans différents fichiers. J'avais regardé beaucoup de messages et de solutions, mais seulement celui-ci me soutenait. –

+0

Merci beaucoup ... Cette approche a résolu mon problème ... – Emerson

4

La réponse d'Adam a plutôt bien fonctionné pour moi, mais il y en a une que j'aimerais ajouter. Si votre fichier logFileName est susceptible d'être réutilisé dans votre application, vous devez vérifier que le référentiel n'existe pas déjà.

string repoName = String.Format("{0}Repository", logFileName); 

// Check for existing repository 
ILoggerRepository[] allRepos = LogManager.GetAllRepositories(); 
ILoggerRepository repo = allRepos.Where(x => x.Name == repoName).FirstOrDefault(); 

// If repository does not exist, create one, set the logfile name, and configure it 
if (repo == null) 
{ 
    repo = LogManager.CreateRepository(repoName); 
    ThreadContext.Properties[KEY_LOG_FILE] = logFileName; 
    log4net.Config.XmlConfigurator.Configure(repo); 
} 

// Set logger 
ILog logger = LogManager.GetLogger(repoName, logName); 
+1

Vous pouvez directement appeler FirstOrDefault, sans Où, comme ceci: 'allRepos.FirstOrDefault (x => x.Name == repoName);' –

Questions connexes