结构化异常日志, 如何做好error日志结构化,便于日志监控过滤.

父文章

    稳定性之监控,报警,定位 架构师该做什么. 偏数据分析视角,智能定位. 2/5/15

为什么要结构化?

 结构化后,维度:能够表征业务. 能够定位代码入口,异常点.

1. 入口来源 链路跟踪和mdc结合

2. logger的特定类方法. logger自带属性

3. 自己打印在内容里规划化. 来源

数据分析角度来看稳定性,维度够多,自动化分析. 另外做好维度的边界剥离, 维度是有从属关系的.

分析问题先从大问题再从小维度.

详见

如何结构化

1. 搞一个类封装日志参数

业务信息:

   1. type(type序号,type名+type值), 通过每个接口的注解获取.(直接法: type序号+type名+参数序号+字段属性,aware接口,) 主type,子type

     通过threadLocal获取,需要业务代码解析后设置进来,但侵入业务代码

  2.  通过上下文,前端传入的业务分类如上,端码,

  3. 业务明确的错误码

结构:  端上场景 + web接口类+foreach(异常类名+异常方法+各层异常code)+forEach(异常具体信息)  (端上维度属于上维度, 如果原因不是端上维度,可能就会导致error分散化,导致雪崩场景的error告警,哪哪都告警. 你也不可能把所有下游维度都采集到,或者最底层的维度采集到,例如redis失败,导致调用下游系统error增加,导致自己内部error增加,也是类雪崩场景. 最终还是要采样分析,分析到最终原因. 但是如果系统能够维度刚好在里面,能够自动根因分析出来,那就更好了.)

    

   强弱依赖下的根因分析

这样就可以方便得过滤一些不想看的code,或者说直接打印Error日志. 监控的时候忽略数量.

   以上,对三要素监控也很重要.

代码信息:

  1. 前端代码信息,页面信息,端trace   

  2. 入口类,方法(rpc框架提供) 或者 自己写filter获取

  3. 外因维度,尽量细化,error的代码异常位置. 类,method,行号. 可以计算整个堆栈的长度作为hashCode值,作为错误类型.

     4.1  class(包含rootClass的最后三个堆栈. 最外层exception的最好三个堆栈.),method无,异常type即行号.\

     4.2  无Exception的类,需要手动输入class,method,异常type

  4. 内因维护,只看业务点,class,method,异常type

   4.1  有Exception 去除最好一个是utils等通用类的rootException位置.可以根据这个维度进行监控统计.

   4.2  无Exception的类,需要手动输入class,method,异常type

 5. logger name. 有上面这些因素,logger name不太重要了.

链路细化发现外因,

链路归一发现内因.

2. 获取causeLine信息的方法.

    

public static String getExceptionCauseLine(Throwable throwable) {

    Throwable root = Throwables.getRootCause(throwable);
    StackTraceElement[] stackTrace = root.getStackTrace();
    if (stackTrace == null || stackTrace.length == 0) {
        return "null";
    } else {
        StackTraceElement element = stackTrace[0];
        String className = element.getClassName();
        int i = className.lastIndexOf(".");
        String simpleClass = "";
        if (i + 1 < className.length()) {
            simpleClass = className.substring(i + 1);
        }
        String line = simpleClass + "." + element.getMethodName()
                + "():" + element.getLineNumber();
        if (!element.getFileName().contains(simpleClass)) {

            line = element.getFileName() + "#" + line;
        }
        return line;
    }
}

附录

传统error打印的常见问题

java的堆栈和日志不是显示在同一行上.

1. 抛堆栈,上层拦截..

2.需要每一层的信息. 那就抓住然后throw 新的,父类放进去. 上下文信息. 一目了然.

例如for循环. 内部通过devUid查询,没有了orgId. 先抛带有devUid, 外部再抓住,加入orgId信息.

1.内部方法参数校验和web入参参数校验要区分

例如有些场景,智能硬件上报属性场景,可能就是获取不到信息.例如ssid.这些场景的校验,就需要使用特定的方法. web接口面向特定场景. 看error日志时可以直接过滤掉.

方法1: 通过堆栈的class和method?

          可能封装的,最底层的都一样. 故要打印自身系统代码的第三层,第二层,第一层

方法2: 通过特定的code来区分?

               比较好的思路,可以避免堆栈打印层数过多. spring的beanValidate就不合适了.需要抛特殊的exception 或者 code .

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值