จะเพิ่มการเยื้องในรายการบันทึกหลายบรรทัดใน 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

มีการรองรับแล้วหรือฉันต้องเขียนส่วนต่อท้ายแบบกำหนดเองหรือเค้าโครงแบบกำหนดเอง


person Eiver    schedule 10.04.2013    source แหล่งที่มา


คำตอบ (1)


ฉันเกลียดที่จะตอบคำถามของตัวเอง แต่เนื่องจากฉันได้พัฒนาคำตอบด้วยตัวเอง ฉันจึงอยากแบ่งปันกับคุณ

ฉันขยาย log4net โซลูชันนี้สืบทอดมาจาก PatternLayout ดังนั้นฟีเจอร์ PatternLayout ทั้งหมดจึงพร้อมใช้งาน นอกจากนี้ยังมีรูปแบบใหม่ %การเยื้อง อีกด้วย หากต้องการรับการบันทึกเหมือนในตัวอย่างด้านบน เพียงใช้:

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

เมื่อจัดรูปแบบข้อยกเว้นรหัส log4net นั้นแปลก (หรือฉันไม่เข้าใจ) ดังนั้นในกรณีนี้ คุณควรใส่ %Exception ในรูปแบบเสมอ เนื่องจากฉันได้ฮาร์ดโค้ดไว้ "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;
        }
    }
}
person Eiver    schedule 18.04.2013
comment
ขอบคุณสำหรับการแบ่งปันสิ่งนี้ เมื่อแยกบรรทัด ฉันเปลี่ยนเป็น value.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None) - person Sean Hall; 23.08.2013
comment
เยี่ยมมากถ้ามันเหมาะกับคุณดีกว่า ฉันมักจะใช้ Environment.NewLine ทุกที่ในโค้ดของฉัน เพราะมันจะส่งกลับสิ่งที่ถูกต้องเสมอขึ้นอยู่กับระบบปฏิบัติการ ภายใต้ Windows มันจะส่งคืน \r\n และภายใต้ Linux (Mono) มันจะส่งคืน \n แต่ถ้าคุณต้องการทั้งสองอย่างผสมกัน โซลูชันของคุณสามารถจัดการกับสิ่งนั้นได้ - person Eiver; 26.08.2013