导航

05-002 Logging 之 ConsoleLogger

Posted on 2015-03-17 18:21  DotNet1010  阅读(371)  评论(0)    收藏  举报

写具体Log信息的是实现接口 IConsole LogConsole

    public interface IConsole
    {
        ConsoleColor BackgroundColor { get; set; }
        ConsoleColor ForegroundColor { get; set; }
        void WriteLine(string format, params object[] args);
    }

 WriteLine 的具体实现:

    public class LogConsole : IConsole
    {
        public void WriteLine(string format, params object[] args)
        {
            System.Console.Error.WriteLine(format, args);
        }
    }

 这里为什么要用 Console.Error 而不用标准的 Console.Out 呢?

我的理解为:当用户设置Console.Out 的时候 不影响 Console.Error:  使得程序更加的灵活,更改Console.Error 的情况极少。   参考下面的代码:

        try {
            writer = new StreamWriter(args[1]);
            Console.SetOut(writer);
            Console.SetIn(new StreamReader(args[0]));
        }
        catch(IOException e) {
            TextWriter errorWriter = Console.Error;
            errorWriter.WriteLine(e.Message);       
        }

 ConsoleLogger 的构造函数中有个参数 : Func<string, LogLevel, bool> filter

这个参数主要用来判断是否启用了某一等级的日志 参考下面的代码:

        public bool IsEnabled(LogLevel logLevel)
        {
            return _filter(_name, logLevel);
        }

 具体的 filter 例子如: (category, logLevel) => logLevel >= LogLevel.Verbose; 当错误等级大于 Verbose 才记录日志。

SetConsoleColor 方法根据不同的日志等级 设置不用的前后背景色:

                case LogLevel.Critical:
                    Console.BackgroundColor = ConsoleColor.Red;
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
                case LogLevel.Error:
                    Console.ForegroundColor = ConsoleColor.Red;
                    break;
                case LogLevel.Warning:
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    break;
                case LogLevel.Information:
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
                case LogLevel.Verbose:
                default:
                    Console.ForegroundColor = ConsoleColor.Gray;
                    break;

 在调用此方法前:前后背景色会进行初始化:所以后面的几个不设置背景色:

                var originalForegroundColor = Console.ForegroundColor;  // save current colors
                var originalBackgroundColor = Console.BackgroundColor;
                var severity = logLevel.ToString().ToUpperInvariant();
                SetConsoleColor(logLevel);

 再看方法:FormatLoggerStructure(StringBuilder builder, ILoggerStructure structure, int level, bool bullet)

  structure  首先执行   if (structure.Message != null) { builder.Append(structure.Message);}

  然后判断 Values       if (values == null){   return;  }

  foreach (var kvp in values)  // kvp KeyValuePair<stirng,object>
 {

              这里的object 可以是 IEnumerable 则循环遍历

                                可以是 ILoggerStructure 则递归调用

                                否则:  builder.Append(kvp.Key) .Append(": ").Append(kvp.Value);

 }

  level  表示前面会输出 level * 2 - 1 个空格。

  bullet 是否多输出一个短横“-”;

public IDisposable BeginScope(object state)  {     return null;  } 

  最后看一下Write方法:

 public void Write(LogLevel logLevel, int eventId, object state, Exception exception, Func<object, Exception, string> formatter)

最终记录日志的代码为:  WriteLine("[{0}:{1}] {2}", severity, _name, message);

其中 severity=logLevel.ToString().ToUpperInvariant();

       _name 是构造函数中的名字。

       message 的内容与 state exception formattter 有关。

看源码发现 这里面 eventId 没有用到.

首先 如果  state 是 ILoggerStructure 并且 !=null.   message = builder.ToString(); 这里的builder 是 FormatLoggerStructure 中的builder.

               if (exception != null) {   message += Environment.NewLine + exception;}

 不是 ILoggerStructure 的情况:

            else if (formatter != null)
            {
                message = formatter(state, exception); // 调用方传递的 formatter
            }
            else
            {
                message = LogFormatter.Formatter(state, exception);     //系统提供的  state+ 换行 + e.ToString()
            }

 最后 : WriteLine("[{0}:{1}] {2}", severity, _name, message);