How to add indentation to multi-line log entry in log4net?

前端 未结 1 1667
我寻月下人不归
我寻月下人不归 2021-01-02 21:34

I am aware of this question and I agree with the answer, but can I do the following with log4net?

Instead of having:

2013-04-09 12:54:47.093 INFO Mai         


        
相关标签:
1条回答
  • 2021-01-02 21:48

    I hate to answer my own questions, but since I have developed the answer myself, I wanted to share it with you.

    I extended log4net. The solution inherits from PatternLayout, so all PatternLayout features are available. In addition a new pattern %indentation is available. To get the logging like in the example above simply use:

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

    When formatting exceptions log4net code is quirky (or I don't understand it). So in this case you should always put %exception in the pattern, because I hardcoded "IgnoresException = false". With IgnoresException = true, log4net completely ignores any formatting and you loose indentation.

    Use code below to extend 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;
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题