2013-04-10 43 views
6

我知道this question,我同意答案,但我可以使用log4net執行以下操作嗎?如何將縮進添加到log4net中的多行日誌條目中?

而是具有:

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 

我可得:

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 

是它已經支持或者我需要編寫一個定製的附加器或自定義佈局?

回答

12

我不想回答我自己的問題,但自從我自己開發了答案後,我想與您分享。

我擴展了log4net。該解決方案繼承自PatternLayout,因此所有PatternLayout功能都可用。此外還有一個新的模式%縮進可用。要獲取日誌就像上面的例子簡單地使用:

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

格式化例外log4net的代碼是古怪的(或者我不明白)。所以在這種情況下,您應該始終在模式中放置%異常,因爲我硬編碼了「IgnoresException = false」。如果IgnoresException = true,log4net會完全忽略任何格式,並且會導致縮進。

使用下面的代碼來擴展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

感謝分享此。在分割線條時,我將它改爲'value.Split(new string [] {「\ r \ n」,「\ n」},StringSplitOptions.None)'。 – 2013-08-23 14:02:15

+1

太好了,如果它對你更好。我傾向於在我的代碼中使用Environment.NewLine,因爲它總是根據操作系統返回正確的東西。在Windows下,它將返回「\ r \ n」,在Linux(單聲道)下它將返回「\ n」。但是如果你需要這兩者的混合,那麼你的解決方案可以解決這個問題。 – Eiver 2013-08-25 20:44:04

相關問題