2013-04-10 8 views
6

Ich bin bewusst von this question und ich stimme der Antwort zu, aber kann ich Folgendes mit log4net tun?Wie fügt man mehrzeiligen Protokolleintrag in log4net Einrückung hinzu?

Anstelle von:

2013-04-09 12:54:47.093 INFO Main: Line 1 Line 1 Line 1 
Line 2 Line 2 Line 2 
Line 3 Line 3 Line 3 
2013-04-09 12:54:47.093 INFO Main: Line 1 Line 1 Line 1 
Line 2 Line 2 Line 2 
Line 3 Line 3 Line 3 

Kann ich:

2013-04-09 12:54:47.093 INFO Main: Line 1 Line 1 Line 1 
            Line 2 Line 2 Line 2 
            Line 3 Line 3 Line 3 
2013-04-09 12:54:47.093 INFO Main: Line 1 Line 1 Line 1 
            Line 2 Line 2 Line 2 
            Line 3 Line 3 Line 3 

Ist es bereits unterstützt oder brauche ich einen benutzerdefinierten appender oder ein benutzerdefiniertes Layout zu schreiben?

Antwort

12

Ich hasse es, meine eigenen Fragen zu beantworten, aber da ich die Antwort selbst entwickelt habe, wollte ich es mit dir teilen.

Ich erweiterte log4net. Die Lösung erbt von PatternLayout, sodass alle PatternLayout-Funktionen verfügbar sind. Zusätzlich ist ein neues Muster % Einrückung verfügbar. Um die Protokollierung wie im Beispiel oben zu erhalten einfach verwenden:

<conversionPattern value="%date - %indentation%message%newline%exception"/> 

Wenn Ausnahmen Formatierung log4net Code ist etwas eigenartig (oder ich verstehe es nicht). In diesem Fall sollten Sie immer% Ausnahme in das Muster einfügen, weil ich "IgnoresException = false" fest codiert habe. Mit IgnoresException = true ignoriert log4net jegliche Formatierung und Sie verlieren die Einrückung.

Benutzen Sie den Code unten log4net zu verlängern:

/// <summary> 
/// Converts %indentation to string 
/// </summary> 
public class IndentationPatternConverter : PatternConverter 
{ 
    protected override void Convert(TextWriter writer, object state) 
    { 
     // do nothing - %indentation is used for indentation, so nothing should be written 
    } 
} 

public class IndentationPatternLayout : PatternLayout 
{ 
    private PatternConverter m_head; 

    public override void Format(TextWriter writer, LoggingEvent loggingEvent) 
    { 
     if (writer == null) 
     { 
      throw new ArgumentNullException("writer"); 
     } 
     if (loggingEvent == null) 
     { 
      throw new ArgumentNullException("loggingEvent"); 
     } 

     PatternConverter c = m_head; 

     IndentationWriter indentationWriter = new IndentationWriter(writer); 
     // loop through the chain of pattern converters 
     while (c != null) 
     { 
      if (c is IndentationPatternConverter) 
      { 
       indentationWriter.SetIndentation(); 
      } 
      c.Format(indentationWriter, loggingEvent); 
      c = c.Next; 
     } 
     indentationWriter.Finish(); 
    } 

    override public void ActivateOptions() 
    { 
     PatternParser patternParser = CreatePatternParser(ConversionPattern); 

     ConverterInfo converterInfo = new ConverterInfo() 
     { 
      Name = "indentation", 
      Type = typeof(IndentationPatternConverter) 
     }; 

     patternParser.PatternConverters.Add("indentation", converterInfo); 
     m_head = patternParser.Parse(); 

     PatternConverter curConverter = m_head; 
     this.IgnoresException = false; 
    } 
} 

public class IndentationWriter : TextWriter 
{ 
    TextWriter writer; 
    int indentation = 0; 
    List<string> lines = new List<string>(); 

    public IndentationWriter(TextWriter writer) 
    { 
     this.writer = writer; 
    } 
    public override Encoding Encoding 
    { 
     get { return writer.Encoding; } 
    } 

    public override void Write(string value) 
    { 
     string[] values = value.Split(new string[] { Environment.NewLine }, StringSplitOptions.None); 
     for (int i = 0; i < values.Length; i++) 
     { 
      if (i > 0) values[i] = Environment.NewLine + values[i]; 
     } 
     lines.AddRange(values); 
    } 

    public void Finish() 
    { 
     for (int i = 0; i < lines.Count; i++) 
     { 
      string line = lines[i]; 
      if (i < lines.Count - 1) line = lines[i].Replace(Environment.NewLine, Environment.NewLine + new string(' ', indentation)); 
      writer.Write(line); 
     } 
     lines.Clear(); 
    } 
    public override void WriteLine(string value) 
    { 
     this.Write(value + Environment.NewLine); 
    } 

    public void SetIndentation() 
    { 
     foreach (string line in lines) 
     { 
      indentation += line.Length; 
     } 
    } 
} 
+1

Vielen Dank für diese teilen. Beim Aufteilen der Zeilen habe ich es in 'value.Split (new string [] {" \ r \ n "," \ n "}, StringSplitOptions.None)' geändert. –

+1

Großartig, wenn es für dich besser funktioniert. Ich neige dazu, Environment.NewLine überall in meinem Code zu verwenden, da es abhängig vom Betriebssystem immer die richtige Sache zurückgibt. Unter Windows gibt es "\ r \ n" zurück und unter Linux (Mono) gibt es "\ n" zurück. Aber wenn Sie eine Mischung aus beidem brauchen, kann Ihre Lösung damit umgehen. – Eiver

Verwandte Themen