Bagaimana cara menambahkan lekukan ke entri log multi-baris di log4net?

Saya mengetahui pertanyaan ini dan saya setuju dengan jawabannya, tapi bisakah saya melakukan hal berikut dengan log4net?

Daripada memiliki:

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

Bolehkah saya mau:

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

Apakah sudah didukung atau apakah saya perlu menulis tambahan khusus atau tata letak khusus?


person Eiver    schedule 10.04.2013    source sumber


Jawaban (1)


Saya benci menjawab pertanyaan saya sendiri, tetapi karena saya sendiri yang mengembangkan jawabannya, saya ingin membaginya dengan Anda.

Saya memperluas log4net. Solusinya mewarisi dari PatternLayout, sehingga semua fitur PatternLayout tersedia. Selain itu, pola baru %indentasi juga tersedia. Untuk mendapatkan logging seperti pada contoh di atas cukup gunakan:

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

Saat memformat pengecualian, kode log4net unik (atau saya tidak memahaminya). Jadi dalam hal ini Anda harus selalu memasukkan %pengecualian ke dalam pola, karena saya melakukan hardcode "IgnoresException = false". Dengan IgnoresException = true, log4net sepenuhnya mengabaikan pemformatan apa pun dan Anda kehilangan lekukan.

Gunakan kode di bawah ini untuk memperluas 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;
        }
    }
}
person Eiver    schedule 18.04.2013
comment
Terima kasih telah berbagi ini. Saat memisahkan garis, saya mengubahnya menjadi value.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None). - person Sean Hall; 23.08.2013
comment
Bagus, jika itu lebih bermanfaat bagi Anda. Saya cenderung menggunakan Environment.NewLine di mana saja dalam kode saya, karena selalu mengembalikan hal yang benar tergantung pada OS. Di Windows ia akan mengembalikan \r\n dan di Linux (Mono) ia akan mengembalikan \n. Namun jika Anda membutuhkan perpaduan keduanya, maka solusi Anda dapat mengatasinya. - person Eiver; 26.08.2013