2009-05-25 9 views
0

J'essaie de consigner l'entrée et la sortie d'une méthode particulière dans la base de données. J'aimerais avoir cette information dans des colonnes séparées. Je l'ai étudié la PatternLayout et il semble qu'il ne sert que pour un seul paramètre% des messages, ce qui signifie que si vous faites:log4net: Consignation de deux messages dans une ligne dans la base de données?

log.Debug("This is a message"); 

alors log4net voit « Ceci est un message » que le message à enregistrer. Je veux faire quelque chose comme:

log.Debug(request, response); 

Est-ce possible en utilisant log4net? Gardez à l'esprit que mon but est d'avoir "demande" et "réponse" dans colonnes séparées.

Répondre

3

Votre façon PatternConverter est un pas dans la bonne direction, bien que l'utilisation des propriétés d'entrée et de sortie statiques le rende tout un peu fragile (sécurité du filetage).

L'astuce ici est de réaliser que le paramètre message de logger.Debug (...) est objet et que vous pouvez passer ce que vous voulez.

Vous pouvez définir un type de message personnalisé

public class InputOutput 
{ 
    public string Input {get;set;} 
    public string Output {get;set;} 
} 

puis laisser vos convertisseurs lire soit la propriété

public class InputPatternConverter : PatternConverter 
{ 
    protected override void Convert(System.IO.TextWriter writer, object state) 
    { 
     var msg = ((LoggingEvent)state).MessageObject as InputOutput; 
     if (msg != null) 
      writer.Write(msg.Input); 
    } 
} 

public class OutputPatternConverter : PatternConverter 
{ 
    protected override void Convert(System.IO.TextWriter writer, object state) 
    { 
     var msg = ((LoggingEvent)state).MessageObject as InputOutput; 
     if (msg != null) 
      writer.Write(msg.Output); 
    } 
} 

l'exploitation forestière devient alors beaucoup plus propre

logger.Debug(new InputOutput { Input = ..., Output = ...}); 

votre config serait le même.

Un conseil est cependant de sous-classer PatternLayout et d'ajouter les convertisseurs dans le constructeur de cette classe. De cette façon, vous pouvez également réduire votre configuration. Cela provoquera la perte du jeton% message, vos jetons% input et% output viendront s'ajouter à tous les jetons que PatternLayout prend en charge. Ainsi, vous pouvez effectivement avoir un motif comme celui-ci:

"%date %message %newline%newline %input %newline%newline %output 

Voici une mise en œuvre rapide d'une mise en page de motif personnalisé:

public class InputOutputPatternLayout : PatternLayout 
{ 
    public InputOutputPatternLayout() 
    { 
     AddConverter("input", typeof(InputPatternConverter)); 
     AddConverter("output", typeof(OutputPatternConverter)); 
    } 
} 
+1

Pour la utilisation moins verbeuse, vous pouvez implémenter cela comme une méthode d'extension à l'interface ILogger en prenant les deux paramètres. Ensuite, l'utilisation serait quelque chose comme: logger.Debug (entrée, sortie); –

+1

Une limitation cependant est que vous perdez le paramètre "@message", sauf si vous ajoutez un autre convertisseur de modèle (ou peut-être sous-classe PatterLayout?) Et une autre propriété. Je n'ai pas testé si cela fonctionne, mais serait-il conseillé de remplacer la méthode ToString() pour retourner le @ message (juste pour le rendre plus générique) au lieu d'avoir un convertisseur de modèle séparé? – ilitirit

+0

Oh et juste une correction: "état comme InputOutput" devrait être quelque chose comme "((LoggingEvent) état) .MessageObject comme InputOutput" à la place. – ilitirit

0

Je suis venu avec une façon de le faire en utilisant PatternConverters personnalisés

public class InputPatternConverter : PatternConverter 
{ 
    private static string _input; 

    public static string Input 
    { 
     get { return _input; } 
     set { _input = value; } 
    } 

    protected override void Convert(System.IO.TextWriter writer, object state) 
    { 
     writer.Write(Input); 
    } 
} 

public class OutputPatternConverter : PatternConverter 
{ 
    private static string _output; 

    public static string Output 
    { 
     get { return _output; } 
     set { _output = value; } 
    } 

    protected override void Convert(System.IO.TextWriter writer, object state) 
    { 
     writer.Write(Output); 
    } 
} 

Appender Spécification:

<appender name="ADONetAppender" type="log4net.Appender.AdoNetAppender"> 
    <bufferSize value="1" /> 
    <connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> 
    <connectionString value="data source=servername;initial catalog=database;Integrated Security=SSPI;" /> 
    <commandText value="INSERT INTO RequestLog ([input], [output]) VALUES (@input, @output)" /> 
    <parameter> 
    <parameterName value="@input" /> 
    <dbType value="String" /> 
    <size value="4000" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <converter> 
     <name value="input" /> 
     <type value="InputPatternConverter, ApplicationName" /> 
     </converter> 
     <conversionPattern value="%input" /> 
    </layout> 
    </parameter> 
    <parameter> 
    <parameterName value="@output" /> 
    <dbType value="String" /> 
    <size value="4000" /> 
    <layout type="log4net.Layout.PatternLayout"> 
     <converter> 
     <name value="output" /> 
     <type value="OutputPatternConverter, ApplicationName" /> 
     </converter> 
     <conversionPattern value="%output" /> 
    </layout> 
    </parameter> 
</appender> 

Appelez à l'aide:

InputPatternConverter.Input = inputString; 
OutputPatternConverter.Output = outputString; 

XmlConfigurator.Configure(); 
ILog logger = LogManager.GetLogger(typeof(ApplicationClassName)); 
logger.Debug(""); 
+0

je serais préoccupé threadsafety l'utilisation de ces statics ... –

Questions connexes