文章目录

  • Code

Code

public class JdbcCommonCollects extends AbstractByteTransformCollect implements ICollect {public static  JdbcCommonCollects INSTANCE;private ApmContext context;public JdbcCommonCollects(ApmContext context, Instrumentation instrumentation) {super(instrumentation);INSTANCE=this;this.context=context;}private final static String[] connection_agent_methods = new String[]{"prepareStatement"};private final static String[] prepared_statement_methods = new String[]{"execute", "executeUpdate", "executeQuery"};private static final String beginSrc;private static final String endSrc;private static final String errorSrc;static {// connectbeginSrc = "com.artisan.collects.JdbcCommonCollects inst=com.artisan.collects.JdbcCommonCollects.INSTANCE;";errorSrc = "inst.error(null,e);";endSrc = "result=inst.proxyConnection((java.sql.Connection)result);";}public JdbcStatistics begin(String className, String method) {JdbcStatistics jdbcStat = new JdbcStatistics();jdbcStat.begin=System.currentTimeMillis();jdbcStat.setModelType("jdbc");return jdbcStat;}public void end(JdbcStatistics stat) {JdbcStatistics jdbcStat= (JdbcStatistics) stat;jdbcStat.end=System.currentTimeMillis();jdbcStat.useTime =jdbcStat.end-jdbcStat.begin;if (jdbcStat.jdbcUrl != null) {jdbcStat.databaseName = getDbName(jdbcStat.jdbcUrl);}this.context.submitCollectResult(stat);}public void error(JdbcStatistics stat, Throwable throwable) {if (stat != null) {stat.error = throwable.getMessage();stat.errorType = throwable.getClass().getName();if (throwable instanceof InvocationTargetException) {stat.errorType = ((InvocationTargetException) throwable).getTargetException().getClass().getName();stat.error = ((InvocationTargetException) throwable).getTargetException().getMessage();}}}public void sendStatistics(JdbcStatistics stat) {}public Connection proxyConnection(final Connection connection) {Object c = Proxy.newProxyInstance(JdbcCommonCollects.class.getClassLoader(), new Class[]{Connection.class}, new ConnectionHandler(connection));return (Connection) c;}public PreparedStatement proxyPreparedStatement(final PreparedStatement statement, JdbcStatistics jdbcStat) {Object c = Proxy.newProxyInstance(JdbcCommonCollects.class.getClassLoader(), new Class[]{PreparedStatement.class}, new PreparedStatementHandler(statement, jdbcStat));return (PreparedStatement) c;}public byte[] transform(ClassLoader loader, String className) throws Exception {// System.out.println("JDBC className:" + className);// 如果更換數據庫,需要替換改類  這裡目前僅適配了MySQLif (!className.equals("com.mysql.cj.jdbc.NonRegisteringDriver")) {return null;}CtClass ctclass = super.toCtClass(loader, className);AgentByteBuild byteLoade = new AgentByteBuild(className, loader, ctclass);CtMethod connectMethod = ctclass.getMethod("connect", "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;");
//      connectMethod.getMethodInfo().getDescriptor();AgentByteBuild.MethodSrcBuild build = new AgentByteBuild.MethodSrcBuild();build.setBeginSrc(beginSrc);build.setErrorSrc(errorSrc);build.setEndSrc(endSrc);byteLoade.updateMethod(connectMethod, build);return byteLoade.toBytecote();}/*** connection 代理处理*/public class ConnectionHandler implements InvocationHandler {private final Connection connection;private ConnectionHandler(Connection connection) {this.connection = connection;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {boolean isTargetMethod = false;for (String agentm : connection_agent_methods) {if (agentm.equals(method.getName())) {isTargetMethod = true;}}Object result = null;JdbcStatistics jdbcStat = null;try {if (isTargetMethod) { // 获取PreparedStatement 开始统计jdbcStat = (JdbcStatistics) JdbcCommonCollects.this.begin(null, null);jdbcStat.jdbcUrl = connection.getMetaData().getURL();jdbcStat.sql = (String) args[0];}result = method.invoke(connection, args);// 代理 PreparedStatementif (isTargetMethod && result instanceof PreparedStatement) {PreparedStatement ps = (PreparedStatement) result;result = proxyPreparedStatement(ps, jdbcStat);}} catch (Throwable e) {JdbcCommonCollects.this.error(jdbcStat, e);JdbcCommonCollects.this.end(jdbcStat);throw e;}return result;}}/*** PreparedStatement 代理处理*/public class PreparedStatementHandler implements InvocationHandler {private final PreparedStatement statement;private final JdbcStatistics jdbcStat;public PreparedStatementHandler(PreparedStatement statement, JdbcStatistics jdbcStat) {this.statement = statement;this.jdbcStat = jdbcStat;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("++++++++++++++++++++++++++++++++++++++++++++");boolean isTargetMethod = false;for (String agentm : prepared_statement_methods) {if (agentm.equals(method.getName())) {isTargetMethod = true;break;}}Object result = null;try {// SQL的參數 輸出  TODO  只能输出一个,后面的会把前面的参数覆盖掉if (args != null ){List<JdbcStatistics.ParamValues> paramValues = SplitUtils.split2Parts(args, 2);jdbcStat.setParams(paramValues);//System.out.println("KKKKKKK:" + JsonWriter.objectToJson(jdbcStat));}result = method.invoke(statement, args);} catch (Throwable e) {if (isTargetMethod) {JdbcCommonCollects.this.error(jdbcStat, e);}throw e;} finally {if (isTargetMethod) {JdbcCommonCollects.this.end(jdbcStat);}}return result;}}private static String getDbName(String url) {int index = url.indexOf("?"); //$NON-NLS-1$if (index != -1) {String paramString = url.substring(index + 1, url.length());url = url.substring(0, index);}String dbName = url.substring(url.lastIndexOf("/") + 1);return dbName;}}

APM - 零侵入监控JDBC服务相关推荐

  1. APM - 零侵入监控Http服务

    文章目录 Pre HTTP采集入口 Code Pre APM - 零侵入监控Service服务 HTTP采集入口 DispacherServlet .doServer() ? @Control ? j ...

  2. APM - 零侵入监控Service服务

    文章目录 需求 采集方案 采集目标 模型设计 Code 需求 通常情况下,如果我们没有系统内部的调用情况,比如我们这里重点聚焦的Service层的接口性能指标 ,比如 调用次数.Avg执行时间.Min ...

  3. 微服务下的APM全链路监控

    https://opentalk.upyun.com/333.html 2017 年 10 月 29 日,又拍云 Open Talk 联合 Spring Cloud 中国社区成功举办了"进击 ...

  4. APM终端用户体验监控分析(下)

    一.前言 APM 终端用户体验监控分析(上)从 APM 终端用户产品特性.使用建议.以及从真实用户体验和模拟性能监控两方面入手给大家进行了简单的分享. 本文为下篇,将给大家介绍几种新的 APM 终端用 ...

  5. RSA创新沙盒盘点|BastionZero——零信任基础设施访问服务

    RSAConference2022将于旧金山时间6月6日召开.大会的Innovation Sandbox(沙盒)大赛作为"安全圈的奥斯卡",每年都备受瞩目,成为全球网络安全行业技术 ...

  6. 零依赖监控解决方案:TDengine+Grafana落地实施

    小 T 导读:随着 TDengine 这款时序数据库(Time Series Database)在各个领域应用的越来越广泛,很多用户选择将 Grafana 与 TDengine 配合使用,以可视化的方 ...

  7. 怎样监视java内存的实际使用量_几个命令教你如何监控 Node 服务的内存情况

    本文收录于 GitHub 山月行博客: shfshanyue/blog,内含我在实际工作中碰到的问题.关于业务的思考及在全栈方向上的学习 前端工程化系列 Node进阶系列 刚开始,先抛出一个问题: 你 ...

  8. 听说你不知道如何监控 Node 服务的内存?

    这是 「山月七八月原创计划」 中的「第一篇」文章,简述了如何监控 Node 服务的内存. 我将在接下来的时间完成 Node 系列及 GraphQL 系列的创作 刚开始,先抛出一个问题: ❝ 你知道你们 ...

  9. shell监控MySQL服务是否正常

    监控MySQL服务是否正常,通常的思路为:检查3306端口是否启动,ps查看mysqld进程是否启动,命令行登录mysql执行语句返回结果, [root@hujiali1 ~]#  netstat - ...

最新文章

  1. 第十四篇:有概率的上下文无关语法Probabilistic Context-Free Grammar
  2. 深度学习的相似度计算 向量之间的相似程度计算 Q K V的注意力权重
  3. opencv jni Android 实例笔记
  4. 随机生成10元素数组并找出最大元素(Java)
  5. jax-rs jax-ws_JAX-RS 2.x与Spring MVC:返回对象列表的XML表示
  6. vs2019配置OpenGL
  7. PowerBI功能发布时间线
  8. 基于Volley框架的图片渐变显示alpha动画
  9. UnitySendMessage
  10. XML To Linq 读取Sharepoint列表中的附件列信息
  11. X window 概念及原理图
  12. Shell脚本学习指南(一)——基本概念
  13. 【Java】JavaSocket编程开发聊天室-总览与部分客户端界面
  14. 基本的常见的锁的介绍
  15. 拆弹实验-phase_4
  16. [ur_driver-2] process has died
  17. 《这!就是街舞》,好综艺还是好生意?
  18. 鲍尔.爱迪斯生前在图论中未完成的问题
  19. 线程池监控和动态配置
  20. 2023年社交平台研究报告

热门文章

  1. pip安装更新、第三方库对应的python解释器版本、pip安装第三方库,压缩包离线安装,pycharm快捷安装及pycharm中terminal的使用,timeout超时报错
  2. C++ close()关闭文件方法详解
  3. CMake的几种Include
  4. C++继承时的名字遮蔽(二)
  5. c++ const 常指针
  6. Leetcode 剑指 Offer 03. 数组中重复的数字 (每日一题 20210614)
  7. GNN笔记:图信号处理(Graph Signal Processing)
  8. 2个字节能存多少个16进制_LabVIEW高级编程技巧:如何从内存字节流中恢复原始数据...
  9. 新手入门深度学习 | 2-2:结构化数据建模流程示例
  10. 【android-tips】如何在android应用中插入百度广告(附源码)