美文网首页
动态日志实践

动态日志实践

作者: 轻微 | 来源:发表于2018-05-03 14:38 被阅读221次

博客地址: dim.red
项目开源: DynamicLog

背景

当线上问题出现的时候. 往往需要之前的埋点进行问题定位. 但是埋点个数是有限的. 现有的埋点往往不够排查出具体的问题. 所以我们需要一个更灵活的埋点方案. 要求是可以动态的输出任何方法的入参和出参.

原理

拦截原有的业务方法的入口和出口.

原本:

public class O {
    private static final String TAG = "O";
    public int method1(int i) {
        Log.d(TAG, "method1() called with: i = [" + i + "]");
        return i * i;
    }
}

处理后:

public class O {
    private static final String TAG = "O";
    public static volatile MethodMonitor s_Monitor_1;

    public int method1(int i) {
        //方法开始
        int methodId = 11;
        Point point = null;
        if (s_Monitor_1 != null && s_Monitor_1.hotMethodEnter(methodId)) {
            point = new Point();
            point.setThisObject(this);
            Object[] var2 = new Object[0];
            point.setArg(var2);
            s_Monitor_1.methodEnter(point);
        }

        //原有方法执行
        Log.d(TAG, "method1() called with: i = [" + i + "]");
        int result = i * i;

        //方法结束
        if (s_Monitor_1 != null && s_Monitor_1.hotMethodReturn(0)) {
            if (point == null) {
                point = new Point();
                point.setThisObject(this);
                Object[] var3 = new Object[0];
                point.setArg(var3);
            }

            point.setReturnObject((Integer)result);
            s_Monitor_1.methodReturn(point, methodId);
        }

        return result;
    }
}

做法:
为所有的 class 分配一个静态的 s_Monitor_1 对象. 同时为 class 下所有的方法分配一个独有的 methodId . 当 s_Monitor_1 对象不为空, methodId 匹配即命中规则.

编译过程过程:

编译过程

插件

Monitor Plugin
在编译期间进行字节码注入. 同时生成 monitorMapping.txt 用来描述方法和 methodId 的映射关系.

注: 在字节码过程中我们发现有些方法是不需要注入的. 比如 abstract , 桥接方法 和 access$方法.

服务端可以通过 mapping.txt 找到混淆以后的类名,再通过 monitorMapping.txt 获取到 methodId 两则组合成命令往客户端发送.

尾巴

是用热修复的思想来做做动态日志.

相关文章

网友评论

      本文标题:动态日志实践

      本文链接:https://www.haomeiwen.com/subject/qdfglftx.html