通用的底层埋点都是怎么做的?

ELK日志采集实践 ELK日志采集设计,核心部分配置,若收集k8s中的日志,可以将日志目录挂载到Ceph或者NFS统一的目录,方便收集和管理。kafka集群 部署、ES、Kibana部署。 阅读详情

点击上方“芋道源码”,选择“设为星标”

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 8:55 更新文章,每天掉亿点点头发...

源码精品专栏

 
  • 方案一,框架自带扩展点

  • 方案二,修改源码

  • 方案三,同名文件覆盖

  • 方案四,切面拦截

  • 方案五,Java Agent

想要在程序里监控数据库的操作耗时,想要在底层框架中自动传递链路跟踪信息,这些需求经常会碰到,特别是在构建基础框架的时候。

核心目标只有一个,那就是在底层封装好,不用上层使用人员关心。今天跟大家聊聊常用的底层扩展埋点方式是怎么处理的。

方案一,框架自带扩展点

如果你使用的框架在设计的时候,就预留了扩展点就很方便了。比如 Mybatis 的拦截器,我们可以在拦截器中对 SQL 进行监控,改写。

比如阿里的 Sentinel 框架,可以通过 SPI 来扩展 Slot,调整编排顺序,新增自定义的 Slot 来实现限流告警等。

开源框架的质量参差不齐,有在早期设计比较好的,留足了各种扩展点,方便使用者。也有一些没有考虑那么全面,导致你在使用的时候需要进行扩展,发现找不到扩展点,对于框架本身没有提供扩展点的场景,请接着看下面。

方案二,修改源码

如果框架没有扩展点,最直接的方式就是修改开源框架的源码来扩展自己想要的功能,通常的做法就是克隆源码到自己的私有仓库中,然后修改、测试、重新打包使用。

像我们之前用了 XXL-JOB 做任务调度,也是修改了某些代码,在界面上扩展了监控通知的配置信息,默认是只支持邮箱,可以扩展出手机、钉钉等。

修改源码不好的点在于需要跟原框架的版本进行对齐,如果不对齐,随便改都没事。不对齐意味着修复了某些 bug 和新增了某些功能,就无法使用了。要对齐,就需要不断的将新版本的代码合并到你自己的分支上。

还有很多公司,就是基于开源的版本,构建了公司内部自己的版本,后续直接就是跟着内部的使用需求去扩展和维护了,不会跟社区的版本进行同步,如果你们有专门的团队去做这件事情,也是一种方式。

方案三,同名文件覆盖

改源码的方式需要经常同步新版本的代码,有的时候往往只想修改某一个类而已,比如对底层的某些操作进行埋点监控,如果框架本身没有提供扩展点的话只能改源码来实现。

其实还有个投机取巧的方式,就是在项目中创建一个跟你要修改的一模一样的类,包名+类目都一样,方法名也一样,方法的实现你可以改。这样就能覆盖 jar 包中的类了,还是跟类加载顺序有关系,先加载你自己定义的。

这样的方式好处在于不用经常去同步新版本的代码,如果你用的框架版本升级了,只要包名和类名不变,你这个覆盖的只是那个类而已,新增的功能和修复的 bug 都不会有影响。

方案四,切面拦截

切面在做很多统一处理的时候非常有用,同样在做底层埋点的场景也适用。

比如我们要对项目中 MongoDB 的所有操作都进行埋点监控,可以修改 MongoDB 的驱动源码,可以创建同名文件进行覆盖,方式有很多种。找到一个合适,又能实现需求的最重要。

以 Spring 中操作 MongoDB 来说明,在 Spring Data MongoDB 中会 MongoTemplate 来操作 MongoDB。最简单的方式就是直接对 MongoTemplate 类进行埋点,这样所有的操作都可以监控起来。

用切面直接切到 MongoTemplate 的所有方法上,然后进行埋点,就很简单了。

@Aspect
public class MongoTemplateAspect {
    @Pointcut("execution(* org.springframework.data.mongodb.core.MongoTemplate.*(..))")
    public void pointcut() {}

    @Around("pointcut()")
    public Object around(final ProceedingJoinPoint pjp) throws Throwable {
        String callMethod = pjp.getSignature().getDeclaringType().getSimpleName() + "." + pjp.getSignature().getName();
        Map<String, Object> data = new HashMap<>();
        data.put("params", JsonUtils.toJson(pjp.getArgs()));
        return CatTransactionManager.newTransaction(() -> {
            try {
                return pjp.proceed();
            } catch (Throwable throwable) {
                throw new RuntimeException(throwable);
            }
        }, "Mongo", callMethod, data);
    }
}

又比如,你还想监控 Redis 相关的,Redis 用的也是跟 Spring 整合的框架,那么也有 RedisTemplate 这个类,同样也可以用切面来实现。

基于 Template 类来埋点,相对比较上层,如果还想在底层一点进行监控,也就是 Connection 这层,Template 里面的操作都是基于 Connection 来实现的。

同样我们可以用切面来替换 Connection 相关的实现,比如可以用切面切到获取 Connection 的方法,然后替换 Connection 的对象为具备埋点监控的对象。


@Aspect
public class RedisAspect {
    @Pointcut("target(org.springframework.data.redis.connection.RedisConnectionFactory)")
    public void connectionFactory() {}

    @Pointcut("execution(org.springframework.data.redis.connection.RedisConnection *.getConnection(..))")
    public void getConnection() {}

    @Pointcut("execution(org.springframework.data.redis.connection.RedisClusterConnection *.getClusterConnection(..))")
    public void getClusterConnection() {}

    @Around("getConnection() && connectionFactory()")
    public Object aroundGetConnection(final ProceedingJoinPoint pjp) throws Throwable {
        RedisConnection connection = (RedisConnection) pjp.proceed();
        return new CatMonitorRedisConnection(connection);
    }

    @Around("getClusterConnection() && connectionFactory()")
    public Object aroundGetClusterConnection(final ProceedingJoinPoint pjp) throws Throwable {
        RedisClusterConnection clusterConnection = (RedisClusterConnection) pjp.proceed();
        return new CatMonitorRedisClusterConnection(clusterConnection);
    }
}

CatMonitorRedisConnection 中对原生的 RedisConnection 做了增强,也不会影响原有的 RedisConnection 的功能。

public class CatMonitorRedisConnection implements RedisConnection {
    private final RedisConnection connection;
    private CatMonitorHelper catMonitorHelper;

    public CatMonitorRedisConnection(RedisConnection connection) {
        this.connection = connection;
        this.catMonitorHelper = new CatMonitorHelper();
    }

    @Override
    public byte[] get(byte[] key) {
        return catMonitorHelper.execute(RedisCommand.GET, key, () -> connection.get(key));
    }
}

方案五,Java Agent

Java Agent 可以在运行期将已经加载的类的字节码进行变更,可以加入我们需要进行监控的代码逻辑。无需对原有代码进行改造,没有侵入性。

在非常多优秀的开源框架中都看到了 Java Agent 的应用,像 APM 框架 SkyWalking,异步传递上下文 transmittable-thread-local 等。

Java Agent 相对其他的方式来说,还是有一定的门槛,毕竟不是日常开发中经常会用到的技术点。如果想了解这种扩展方式,可以看看一些已经用了的开源框架的源码,就知道大概怎么使用了。下面贴一段 transmittable-thread-local 中对线程池进行扩展的代码吧,主要就是利用了 javassist 操作字节码。


try {
  final CtMethod afterExecute = clazz.getDeclaredMethod("afterExecute", new CtClass[]{runnableClass, throwableClass});
  // unwrap runnable if IsAutoWrapper
  String code = "$1 = com.alibaba.ttl.threadpool.agent.internal.transformlet.impl.Utils.unwrapIfIsAutoWrapper($1);";
  logger.info("insert code before method " + signatureOfMethod(afterExecute) + " of class " + afterExecute.getDeclaringClass().getName() + ": " + code);
  afterExecute.insertBefore(code);
  modified = true;
} catch (NotFoundException e) {
  // clazz does not override afterExecute method, do nothing.
}


欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

兄弟,艿一口,点个赞!????

Android 埋点解决方案 Android埋点存在两种方案,一种是全埋点方案,就是埋点全部自动收集数据,无需开发者写代码,实现方案会很复杂,单模块的开发者控制不了逻辑;二是自埋点方案,大部分的埋点数据都是通过开发者自己埋入信息,自由度很高。具体方案应该说适合的才是最好的。 一、全埋点方案 无需Android应用程序开发工程师写代码或者只写少量的代码,就能预先自动收集用户的所有行为数据,然后根据实际的业务分析需求从中筛选出所需行为数据并进行分析。 全埋点采集事件分为4中:(事件名称前面的$符号,指事件是预置事件,与之对应的是自定义事件) 阅读详情

相关推荐

Java 应用实现自定义埋点:使用 OpenTelemetry API

在上面的示例中,我们使用 JaegerGrpcSpanExporter 创建了一个 Jaeger Exporter,并将其配置为 BatchSpanProcessor 的输出。在上面的示例中,我们首先创建了一个名为 “myMethod” 的 Span,然后在关键操作的开始和结束位置插入了代码。完成了前面的步骤后,我们的应用程序就已经集成了 OpenTelemetry,并可以进行自定义埋点了。通过在关键操作的开始和结束位置插入埋点代码,我们可以测量操作的执行时间,并记录自定义属性、事件和异常信息。

DeFunction的博客 763

2w字详解数据湖:概念、特征、架构与案例

点击上方“芋道源码”,选择“设为星标”管她前浪,还是后浪?能浪的浪,才是好浪!每天 10:33更新文章,每天掉亿点点头发...源码精品专栏原创 | Java 2021超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数据库中间件 Sharding-JDBC 和 MyCAT ...

芋艿V 2135

如何设计一个底层埋点?

背景 框架自带扩展点 修改源码 同名文件覆盖 切面拦截 Java Agent

555

Prometheus之JAVA应用埋点监控

目标: jvm监控,应用 网关\ 服务监控(自定义监控指标) springboot 接入: Maven引入: <!--actuator--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- p

fifthangel8080的博客 6746

埋点监控api包

埋点监控api两方包,无具体实现。

PCB设计教程【入门篇】——PCB设计基础-PCB构成与组成

本教程基于B站Expert电子实验室的PCB设计教学的整理,为个人学习记录,旨在帮助PCB设计新手入门。所有内容仅作学习交流使用,无任何商业目的。若涉及侵权,请随时联系,将会立即处理。

2501_91732643的博客 7661

Java实现埋点(自定义注解 + AOP + @Async)

埋点业务尽可能是异步解耦,即对主流程业务无影响。无埋点(全埋点):本篇文章就是采用的无埋点的设计,这个设计方案不会修改原始业务代码,采用自定义注解 + AOP + @Async进行实现。· 可视化埋点:这个就是前端的活了,在页面上设计点击事件,比如:按钮、页面滚动......(我一个java后端不是很了解,大家可以上网搜一下)代码埋点:每一个埋点都需要手动去添加代码,要是更新埋点方案,可能都需要改代码,技术人员的累趴下(成本比较大,而且代码容易堆积)代码埋点、可视化埋点、无埋点(全埋点)

shixiaoyanma的博客 2792

Windows11安装UE4+Airsim

Windows11安装UE4+Airsim

Legendyyy的博客 3744

python 点击埋点_数据埋点怎么做?

数据埋点采集的那些事儿数据采集是数据分析的基础,而埋点是最主要的采集方式。那么数据埋点采集到底都是哪些事呢?我们主要从三个方面来看:什么是埋点,埋点怎么设计,以及埋点的应用。一、数据采集以及常见数据问题1.数据采集做任何事都要有个目的与目标,数据分析也不例外。在开展数据分析之前,我们需要思考为什么要开展数据分析?希望通过这次数据分析解决企业什么问题?数据采集有多种方式,埋点采集是其中非常重要的一部...

weixin_39536728的博客 796

AD从原理图到PCB超详细教程

我在学习AD的时候,看了网上很多教程,但是东西很杂,有很多条理不清而且废话很多,所以相信大家学习的时候也是遇到一样的困难。我就特地写一篇帖子,整理了一下AD从画原理图开始一直到画完PCB文件的所有步骤,一方面是供大家参考学习,另一方面可以方便我自己学习记忆更加深刻。我用的版本是AD16中文版,大家用新的版本AD20或者AD22应该操作都是差不多的。

人生寂寞如雪 18万+

Labview数据存储与读取——TDMS文件的创建与写入

Labview数据存储与读取——TDMS文件的创建与写入 你好,这是我在自学Labview编写软件过程中使用的一些功能。我在存储采集卡数据时,通过阅读大量他人的程序,发现TDM及TDMS文件十分适合波形数据的记录,TDMS文件比TDM文件在存储动态类型数据时读写速度更快,而且TDMS 文件没有容量限制,适合存储数据量庞大的测试数据。 前言少叙,书归正传 这一篇博客,说明一下如何使用基本的TDMS功能实现数据文件的存储。 所需要的控件如上图所示,在程序框图——编程——文件I\O——TDMS 中,写入TDMS

滑板小帅程序开发 2万+

有赞埋点实践

一、前言 大数据应用一般会有采集、加工、存储、计算及可视化这几个环节。其中采集做为源头,在确保全面、准确、及时的前提下,最终加工出来的指标结果才是有价值的。 而埋点作为一种重要的采集手段,可以将用户行为信息转化为数据资产,为产品分析、业务决策、广告推荐等提供可靠的流量数据支持。 在业务需求少的情况下,可以运用一些简单的方法快速采集用户行为。但如果业务线、终端众多,数据需求多样,就需要设...

一个用户增长数据分析师的博客 1957

Prometheus-2.53.1安装

Prometheus+Grafana安装

qlj062127的博客 1788

数据分析之埋点方案

一、前言   大数据应用一般会有采集、加工、存储、计算及可视化这几个环节。其中采集做为源头,在确保全面、准确、及时的前提下,最终加工出来的指标结果才是有价值的。 而埋点作为一种重要的采集手段,可以将用户行为信息转化为数据资产,为产品分析、业务决策、广告推荐等提供可靠的流量数据支持。 在业务需求少的情况下,可以运用一些简单的方法...

jackwang1780的博客 4391

《寻秦OL》.ani动画逆向解析:二进制结构与Unity重实现

动画文件格式是游戏资源逆向的核心入口,其本质是一组按特定规则组织的二进制数据流。理解魔数识别、字节序、字段对齐与差分编码等底层原理,是解析非标准格式的关键前提。技术价值在于绕过黑盒协议,直接从静态客户端提取可验证的原始语义;典型应用场景包括老游戏复刻、美术资产抢救、引擎跨平台迁移及教学级逆向训练。本文以《寻秦OL》的`.ani`文件为实例,深入剖析其C风格结构布局、GB2312中文命名、16位定点数旋转表示及帧主序差分存储机制,并基于C#在Unity中完成从字节流到AnimationClip的端到端重建,覆

weixin_30368981的博客 643

由浅入深的详细解读汽车PDU与BDU

本文详细解读新能源汽车的PDU高压配电单元和BDU电池包断路单元,涉及电气件参数设计、选型、结构设计、电气安全、散热设计、继电器控制与诊断,提供汽车电子知识和技术解析。

让你爱上电路设计 1万+

神策sdk埋点

(5)明确事件的字段:字段其实就是刚刚提到的维度,明确事件字段的话就是比如刚刚有一个按钮点击的事件,那么这个按钮点击有那些必要采的属性,比如按钮名称,按钮当前所在的页面需要采,这就是一些事件字段。首先第一步我们要提供以下文档,比如说之后我们产品迭代的时候可能就是某一个功能点的一些指标,比如新增一个登录注册的一个方式,要去看用这个功能的人数,人数占比等。(6)定义采取规范:采集规范就是我们最后落地下来的埋点文档,就是某一个事件对应的属性,属性类型的规范,最重要的是触发时机的规范。

zxcvb0825的博客 2351

3D点云-CVPR 2020-PF-Net: Point Fractal Network for 3D Point Cloud Completion

是一种专门为三维点云补全设计的深度学习模型。点云补全实际上和图片补全是一个逻辑,都是采用GAN模型的思想来进行补全,在图片补全中,将部分像素点删除并且标记,然后卷积特征提取预测、判别器判别,来训练模型,生成的像素点与原来像素点比较完成模型的训练。而PF-Net就是采用GAN的思想在3D点云上的应用。

404 Not Found 2375

什么是数据埋点?

埋点学习笔记

happylls666的博客 3238

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

金融支付行业埋点治理实践

自定义的埋点事件、事件属性和用户属性,是各产品部门自己维护的,但由于缺乏通用的埋点规范,各部门定义的字段规则不一致,同名不同义、同意不同名等问题频繁发生,导致数据质量很差,尤其是做联合分析时,计算口径经常对不上。

eship2023的博客 1710

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

上一篇: 说几个Java多线程中你可能不知道的点
下一篇: 每个程序员都应该收藏的算法复杂度速查表
公众号-芋道源码
博客等级 码龄10年 1636粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值