zoukankan      html  css  js  c++  java
  • 使用chrome控制台作为日志查看器

    很多时候,我们需要查看日志的实时输出,这个时候往往只能选择控制台。我这里的日志框架是serilog,它有一个好处是控制台输出时可以高亮的形式显示其参数结构信息,如下图所示

    但也存在许多不方便的地方:

    • 清屏不方便
    • 回看历史不方便
    • 日志过滤不方便
    • 消息不便复制出来保持
    • 复杂的消息不便查看

    因此我也一直在找一个更理想的日志查看器,找了许多现成的日志查看器,都不甚理想。要是自己写一个的话,结构化日志的输出也是比较麻烦的,工作量太大。

    最后将目标选定在了Chrome控制台上,找了一下chrome 控制台的语法,发现其可以高亮显示结构化数据。

    并且还能展开,查看十分方便

    另外,chrome控制台还自带许多特性:

    • 支持清屏
    • 支持显示时间(不需要日志信息中携带)
    • 支持类似日志自动分组

    在输出样式上也是异常强大

    • 支持不同日志级别的样式
    • 支持日志分组
    • 支持对象结构化输出
    • 支持自定义样式
    • 支持输出为表格

    简直是日志输出利器,因此就打算使用Chrome console作为实时日志查看器了。

    架构

    既然打算将chrome console作为日志输出,就得考虑实现方式了,一个简单的架构如下:

    1. 程序输出日志时,将日志序列化为json格式,通过websocket发送到日志服务器(web服务器)
    2. 查看日志时,通过浏览器打开日志服务器提供日志的查看页面。
    3. 客户端打开页面时,通过js脚本订阅日志服务器的日志,并解析日志,调用想用的指令输出到控制台

    由于有了日志服务器,日志的输出成了订阅式的了,也可以非常方便的做日志过滤输出了。

    序列化日志

    要实现这个日志框架,第一步就是要将日志信息序列化成json格式,以Serilog为例,由于Serilog框架本身就提供了日志的结构化信息,实现起来是非常方便的。参照serilog文档自定义一个Sink即可,如下是一个简单的实现 

     1 public class JsonSink : ILogEventSink
     2 {
     3     private readonly IFormatProvider _formatProvider;
     4  
     5     public JsonSink(IFormatProvider formatProvider)
     6     {
     7         _formatProvider = formatProvider;
     8     }
     9  
    10     public void Emit(LogEvent logEvent)
    11     {
    12         var tokens   = logEvent.MessageTemplate.Tokens.Select(getFormat);
    13         var template = string.Join("", tokens);
    14  
    15         var paras = logEvent.Properties.Values.Select(getPara).ToArray();
    16  
    17         var level = logEvent.Level.ToString();
    18         var log = new
    19         {
    20             level,
    21             template,
    22             paras,
    23         };
    24  
    25         var text = JsonConvert.SerializeObject(log, Formatting.Indented);
    26         File.WriteAllText(@"r:log.json", text);
    27  
    28         string getFormat(object token)
    29         {
    30             if (token is PropertyToken p)
    31                 return "%o";
    32             else
    33                 return token.ToString();
    34         }
    35  
    36         object getPara(LogEventPropertyValue v)
    37         {
    38             return JsonConvert.DeserializeObject(v.ToString());
    39         }
    40     }
    41 }
    View Code

    这里需要实现的是Emit函数,可以通过LogEvent对象获取到结构化的信息,这里需要将它序列化成一个json对象,从而能被chrome js脚本解析。

    一般来说,对于一个结构化的日志,主要需要包括如下几个参数: 告警级别、时间、消息模板、参数。这里简化起见,就没有加入时间了。另外,为了方便chrome console输出,将其模板转换了一下,转成了chrome console可以直接支持的消息模板。

    需要注意的是,由于chrome console的输出模板和seriallog的消息模板不完全一致,我这里的算法还比较简陋,丧失了参数的名称信息,因此对输入还是有些限制的,那就是:

    1. 参数只能使用一次
    2. 参数的顺序必须和模板的顺序一致

    由于大部分的日志是遵循这个限制的,以后再优化算法。对于如下日志记录。

    var position  = new { Latitude = 25, Longitude = 134 };
    var elapsedMs = 34;

    Log.Information("Processed {@Position} in {Elapsed} ms.", position, elapsedMs);

    输出的json如下(这里我是将其保存到文件了,实际实现应该是发送到日志服务器):

    {
        "level""Information",
        "template""Processed %o in %o ms.",
        "paras": [
            {
                "Latitude": 25,
                "Longitude": 134
            },
            34
        ]
    }

    Chrome中输出

    由于篇幅所限,这里不考虑数据如何发布和订阅的,仅仅介绍下chrome console中输出相关功能。

    在chrome中输出需要靠js来实现,一个简单的实现如下:

    var log = {
        "level""Information",
        "template""Processed %o in %o ms.",
        "paras": [{
            "Latitude": 25,
            "Longitude": 134
        }, 34]
    };

    var fn = console.log;
    var logPara = [log.template].concat(log.paras);

    fn.apply(thislogPara);

     这里日志信息中携带了级别、消息模板、参数三部分信息,需要和控制台api相对应。主要的难点在于由于参数是动态的,需要js函数动态参数的调用。代码比较简单,除掉上面的日志消息,就三行代码,就不多介绍了。

    小结

    这里已经给出了将chrome输出为日志查看器的主要技术,还差日志服务器部分没有给出。后续有空整理后再给一个完整的开源实现。主要涉及到相关技术如下(部分可能需要翻墙):

  • 相关阅读:
    POJ 1887 Testing the CATCHER
    HDU 3374 String Problem
    HDU 2609 How many
    POJ 1509 Glass Beads
    POJ 1458 Common Subsequence
    POJ 1159 Palindrome
    POJ 1056 IMMEDIATE DECODABILITY
    POJ 3080 Blue Jeans
    POJ 1200 Crazy Search
    软件体系结构的艺术阅读笔记1
  • 原文地址:https://www.cnblogs.com/TianFang/p/9439311.html
Copyright © 2011-2022 走看看