2013-04-10 14 views
6

Jestem świadomy this question i zgadzam się z odpowiedzią, ale czy mogę wykonać następujące czynności z log4net?Jak dodać wcięcie do wpisu dziennika wieloliniowego w log4net?

Zamiast:

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 

mogę mieć:

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 

Czy to już obsługiwane lub muszę napisać niestandardowy appender lub niestandardowy układ?

Odpowiedz

12

Nienawidzę odpowiadać na własne pytania, ale ponieważ sam opracowałem odpowiedź, chciałem się nią z wami podzielić.

Rozszerzyłem log4net. Rozwiązanie dziedziczy po PatternLayout, więc wszystkie funkcje PatternLayout są dostępne. Ponadto dostępny jest nowy wzór % wcięcia. Aby uzyskać rejestrację jak w powyższym przykładzie po prostu użyć:

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

Podczas formatowania wyjątki kod log4net jest dziwaczna (albo ja nie rozumiem). Tak więc w tym przypadku zawsze powinieneś umieścić% wyjątku we wzorcu, ponieważ zakodowałem "IgnoresException = false". Z IgnoresException = true, log4net całkowicie ignoruje wszelkie formatowanie i tracisz wcięcia.

skorzystać z poniższego kodu, aby przedłużyć log4net:

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

Dziękujemy za udostępnienie tego. Kiedy dzieliłem linie, zmieniłem je na 'value.Split (nowy ciąg [] {" \ r \ n "," \ n "}, StringSplitOptions.None). –

+1

Świetnie, jeśli to działa lepiej dla Ciebie. Używam Environment.NewLine wszędzie w moim kodzie, ponieważ zawsze zwraca właściwą rzecz w zależności od systemu operacyjnego. W Windowsie zwróci "\ r \ n" i pod Linuxem (Mono) zwróci "\ n". Ale jeśli potrzebujesz połączenia dwóch, twoje rozwiązanie może sobie z tym poradzić. – Eiver

Powiązane problemy