2013-04-10 14 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"をハードコードしているので、常に%exceptionをパターンに入れるべきです。 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 [] \" \ "、" \ n "}、StringSplitOptions.None)'に変更しました。 –

+1

あなたのためにうまくいくなら、素晴らしい。私は環境に応じて常に正しいものを返すので、Environment.NewLineをコード内のどこでも使用する傾向があります。 Windowsでは "\ r \ n"を返し、Linux(Mono)では "\ n"を返します。しかし、2つが混在する必要がある場合は、そのソリューションで対処できます。 – Eiver

関連する問題