2009-05-25 11 views
0

Ich versuche, die Eingabe und Ausgabe einer bestimmten Methode in der Datenbank zu protokollieren. Ich hätte gerne diese Informationen in separaten Spalten. Ich habe die Patternuntersucht und es scheint, dass es nur für ein einzelnen% Nachrichtenparameter sorgt, dass das heißt, wenn Sie tun:log4net: Zwei Nachrichten in einer Zeile in der Datenbank protokollieren?

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

dann sieht log4net „Dies ist eine Nachricht“, wie die Nachricht protokolliert werden. Ich möchte etwas tun wie:

Ist dies mit log4net möglich? Denken Sie daran, dass mein Ziel ist, "Anfrage" und "Antwort" in separate Spalten zu haben.

Antwort

3

Ihr PatternConverter Weg ist ein Schritt in die richtige Richtung, obwohl die Verwendung der statischen Eingabe- und Ausgabeeigenschaften dies ermöglicht alles etwas wackelig (thread-sicher).

Der Trick hier ist zu erkennen, dass der Nachrichtenparameter auf logger.Debug (...) ist Objekt und das Sie können übergeben, was auch immer Sie möchten.

Sie können eine benutzerdefinierte Nachrichtentyp

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

definieren und dann lassen Sie Ihre Konverter lesen entweder Eigentum

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); 
    } 
} 

die Protokollierung dann viel sauberer wird

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

Ihre Konfiguration wäre das Gleiche.

Ein Tipp ist jedoch, die PatternLayout Unterklasse und die Konverter im Konstruktor dieser Klasse hinzuzufügen. Auf diese Weise können Sie auch Ihre Konfiguration verkleinern. Dies wird nicht verursachen Sie das% Nachrichtentoken verlieren, Ihre% Eingabe und% Ausgabetoken werden zusätzlich zu allen Token, die PatternLayout unterstützt. So könnte man eigentlich ein Muster wie dieses:

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

Hier ist eine schnelle Implementierung eines benutzerdefinierten Musterlayout:

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

Um die Verwendung weniger ausführlich, Sie könnten dies als eine Erweiterungsmethode für die ILogger-Schnittstelle unter Verwendung der beiden Parameter implementieren. Dann wäre die Verwendung so etwas wie: logger.Debug (Eingabe, Ausgabe); –

+1

Eine Einschränkung besteht jedoch darin, dass Sie den Parameter "@message" verlieren, es sei denn, Sie fügen einen weiteren Musterkonverter (oder möglicherweise eine Unterklasse von PatterLayout?) Und eine andere Eigenschaft hinzu. Ich habe nicht getestet, ob das funktioniert, aber wäre es ratsam, die ToString() -Methode zu überschreiben, um die @Message zurückzugeben (nur um es generischer zu machen), anstatt einen separaten Musterkonverter zu haben? – ilitirit

+0

Oh und nur eine Korrektur: "State als InputOutput" sollte etwas wie "((LoggingEvent) Zustand) .MessageObject als InputOutput" stattdessen sein. – ilitirit

0

Ich habe mit einer Art und Weise kommen diese Gewohnheit PatternConverters

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 Spezifikation verwenden zu tun:

es
<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> 

Rufen Sie mit:

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

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

ich threadsafety betroffen sein würde, diese Statik mit ... –

Verwandte Themen