2013-04-10 9 views
6

Sono a conoscenza di this question e sono d'accordo con la risposta, ma posso fare quanto segue con log4net?Come aggiungere il rientro alla voce di registro multilinea in log4net?

Invece di avere:

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 

Posso avere:

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 

E 'già sostenuto o devo scrivere un appender personalizzato o un layout personalizzato?

risposta

12

Detesto rispondere alle mie domande, ma poiché ho sviluppato la risposta da solo, ho voluto condividerlo con voi.

Ho esteso log4net. La soluzione eredita da PatternLayout, quindi tutte le funzionalità di PatternLayout sono disponibili. Inoltre è disponibile un nuovo motivo indentazione. Per ottenere la registrazione, come nell'esempio di cui sopra è sufficiente utilizzare:

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

Al termine della formattazione eccezioni codice log4net è eccentrico (o io non lo capisco). Quindi in questo caso dovresti sempre inserire% exception nel pattern, perché ho hardcoded "IgnoresException = false". Con IgnoresException = true, log4net ignora completamente qualsiasi formattazione e perdi il rientro.

Usa codice sottostante per estendere 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

Grazie per aver condiviso questo. Quando ho diviso le righe, l'ho cambiato in 'value.Split (nuova stringa [] {" \ r \ n "," \ n "}, StringSplitOptions.None)'. –

+1

Ottimo, se funziona meglio per te. Tendo ad usare Environment.NewLine ovunque nel mio codice, perché restituisce sempre la cosa corretta a seconda del sistema operativo. Sotto Windows restituirà "\ r \ n" e sotto Linux (Mono) restituirà "\ n". Ma se hai bisogno di un mix dei due, allora la tua soluzione può occuparsene. – Eiver

Problemi correlati