【问题标题】:How to add indentation to multi-line log entry in log4net?如何为 log4net 中的多行日志条目添加缩进?
【发布时间】:2013-04-10 13:33:28
【问题描述】:

我知道this question 并且我同意这个答案,但是我可以使用 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

是否已经支持或者我需要编写自定义附加程序或自定义布局?

【问题讨论】:

    标签: log4net multiline


    【解决方案1】:

    我讨厌回答自己的问题,但由于我自己开发了答案,所以我想与你分享。

    我扩展了 log4net。该解决方案继承自 PatternLayout,因此所有 PatternLayout 功能都可用。此外,还提供了一种新模式 %indentation。要获得上例中的日志记录,只需使用:

    <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;
            }
        }
    }
    

    【讨论】:

    • 感谢分享。分割线的时候,我改成value.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None)
    • 太好了,如果它更适合您。我倾向于在我的代码中到处使用 Environment.NewLine,因为它总是根据操作系统返回正确的东西。在 Windows 下它将返回“\r\n”,在 Linux (Mono) 下它将返回“\n”。但是,如果您需要将两者混合使用,那么您的解决方案可以解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-21
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多