背景:

Cat Java 客户端支持 JDK 1.6 及以上版本。

1.客户端集成CAT

1.添加依赖

  • maven项目 在pom.xml 中引入如下内容:
        <dependency><groupId>com.dianping.cat</groupId><artifactId>cat-client</artifactId><version>3.0.0</version></dependency>
  • 非maven项目 直接引入jar包

如果没有使用maven管理依赖,可以直接复制 jar/cat-client-3.0.0.jar 到项目 WEB_INF/lib 路径下。jar包下载地址:

https://github.com/dianping/cat/blob/master/lib/java/jar/cat-client-3.0.0.jar

2.添加过滤器

  • springboot项目(WebConfig.java)
package com.gdie.cat.config;import com.dianping.cat.servlet.CatFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;/*** @Description TODO* @Author jiuwei* @Date Created in 下午11:53 2020/4/2* @Version 1.0*/
@Configuration
public class WebConfig implements WebMvcConfigurer {/*** cat的埋点过滤器* * @return*/@Beanpublic FilterRegistrationBean catFilter() {FilterRegistrationBean registration = new FilterRegistrationBean();CatFilter filter = new CatFilter();registration.setFilter(filter);registration.addUrlPatterns("/*");registration.setName("cat-filter");registration.setOrder(1);return registration;}}
  • springmvc项目(web.xml)
 <filter><filter-name>cat-filter</filter-name><filter-class>com.dianping.cat.servlet.CatFilter</filter-class></filter><filter-mapping><filter-name>cat-filter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

3.配置/data/appdatas/cat/client.xml

vi /data/appdatas/cat/client.xml
        内容如下:

     <?xml version="1.0" encoding="utf-8"?><config mode="client"><servers><server ip="192.168.1.102" port="2280" http-port="8080"/></servers></config>

4.在项目中创建app.properties

然后你需要在你的项目中创建 src/main/resources/META-INF/app.properties 文件, 并添加如下内容:

app.name={appKey}
  • 说明
  1. appkey 只能包含英文字母 (a-z, A-Z)、数字 (0-9)、下划线 (_) 和中划线 (-)。
  2. 现在java的cat client会自动懒加载,已经没有必要手动初始化客户端。

查看cat是否有监控到集成的客户端。

2.mybatis集成CAT

1.引入拦截器

将CatMybatisPlugin.java 放到任意SpringBoot 能扫描到的package下面

package com.gdie.cat.plugin;import com.dianping.cat.Cat;
import com.dianping.cat.message.Message;
import com.dianping.cat.message.Transaction;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.mybatis.spring.transaction.SpringManagedTransaction;
import org.springframework.util.ReflectionUtils;import javax.sql.DataSource;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.DateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;/*** @Description 对MyBatis进行拦截,添加Cat监控* @Author jiuwei* @Date Created in 下午11:53 2020/4/2* @Version 1.0*/
@Intercepts({@Signature(method = "query", type = Executor.class, args = {MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class}),@Signature(method = "update", type = Executor.class, args = {MappedStatement.class, Object.class})
})
public class CatMybatisPlugin implements Interceptor {private static Log logger = LogFactory.getLog(CatMybatisPlugin.class);//缓存,提高性能private static final Map<String, String> sqlURLCache = new ConcurrentHashMap<String, String>(256);private static final String EMPTY_CONNECTION = "jdbc:mysql://unknown:3306/%s?useUnicode=true";private Executor target;// druid 数据源的类名称private static final String DruidDataSourceClassName = "com.alibaba.druid.pool.DruidDataSource";// dbcp 数据源的类名称private static final String DBCPBasicDataSourceClassName = "org.apache.commons.dbcp.BasicDataSource";// dbcp2 数据源的类名称private static final String DBCP2BasicDataSourceClassName = "org.apache.commons.dbcp2.BasicDataSource";// c3p0 数据源的类名称private static final String C3P0ComboPooledDataSourceClassName = "com.mchange.v2.c3p0.ComboPooledDataSource";// HikariCP 数据源的类名称private static final String HikariCPDataSourceClassName = "com.zaxxer.hikari.HikariDataSource";// BoneCP 数据源的类名称private static final String BoneCPDataSourceClassName = "com.jolbox.bonecp.BoneCPDataSource";@Overridepublic Object intercept(Invocation invocation) throws Throwable {MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];//得到类名,方法String[] strArr = mappedStatement.getId().split("\\.");String methodName = strArr[strArr.length - 2] + "." + strArr[strArr.length - 1];Transaction t = Cat.newTransaction("SQL", methodName);//得到sql语句Object parameter = null;if (invocation.getArgs().length > 1) {parameter = invocation.getArgs()[1];}BoundSql boundSql = mappedStatement.getBoundSql(parameter);Configuration configuration = mappedStatement.getConfiguration();String sql = showSql(configuration, boundSql);//获取SQL类型SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();Cat.logEvent("SQL.Method", sqlCommandType.name().toLowerCase(), Message.SUCCESS, sql);String s = this.getSQLDatabase();Cat.logEvent("SQL.Database", s);Object returnObj = null;try {returnObj = invocation.proceed();t.setStatus(Transaction.SUCCESS);} catch (Exception e) {Cat.logError(e);} finally {t.complete();}return returnObj;}private DataSource getDataSource() {org.apache.ibatis.transaction.Transaction transaction = this.target.getTransaction();if (transaction == null) {logger.error(String.format("Could not find transaction on target [%s]", this.target));return null;}if (transaction instanceof SpringManagedTransaction) {String fieldName = "dataSource";Field field = ReflectionUtils.findField(transaction.getClass(), fieldName, DataSource.class);if (field == null) {logger.error(String.format("Could not find field [%s] of type [%s] on target [%s]",fieldName, DataSource.class, this.target));return null;}ReflectionUtils.makeAccessible(field);DataSource dataSource = (DataSource) ReflectionUtils.getField(field, transaction);return dataSource;}logger.error(String.format("---the transaction is not SpringManagedTransaction:%s", transaction.getClass().toString()));return null;}/*** 重写 getSqlURL 方法** @author fanlychie (https://github.com/fanlychie)*/private String getSqlURL() {// 客户端使用的数据源DataSource dataSource = this.getDataSource();if (dataSource != null) {// 处理常见的数据源switch (dataSource.getClass().getName()) {// druidcase DruidDataSourceClassName:return getDataSourceSqlURL(dataSource, DruidDataSourceClassName, "getUrl");// dbcpcase DBCPBasicDataSourceClassName:return getDataSourceSqlURL(dataSource, DBCPBasicDataSourceClassName, "getUrl");// dbcp2case DBCP2BasicDataSourceClassName:return getDataSourceSqlURL(dataSource, DBCP2BasicDataSourceClassName, "getUrl");// c3p0case C3P0ComboPooledDataSourceClassName:return getDataSourceSqlURL(dataSource, C3P0ComboPooledDataSourceClassName, "getJdbcUrl");// HikariCPcase HikariCPDataSourceClassName:return getDataSourceSqlURL(dataSource, HikariCPDataSourceClassName, "getJdbcUrl");// BoneCPcase BoneCPDataSourceClassName:return getDataSourceSqlURL(dataSource, BoneCPDataSourceClassName, "getJdbcUrl");}}return null;}/*** 获取数据源的SQL地址** @param dataSource                 数据源* @param runtimeDataSourceClassName 运行时真实的数据源的类名称* @param sqlURLMethodName           获取SQL地址的方法名称* @author fanlychie (https://github.com/fanlychie)*/private String getDataSourceSqlURL(DataSource dataSource, String runtimeDataSourceClassName, String sqlURLMethodName) {Class<?> dataSourceClass = null;try {dataSourceClass = Class.forName(runtimeDataSourceClassName);} catch (ClassNotFoundException e) {}Method sqlURLMethod = ReflectionUtils.findMethod(dataSourceClass, sqlURLMethodName);return (String) ReflectionUtils.invokeMethod(sqlURLMethod, dataSource);}private String getSQLDatabase() {
//        String dbName = RouteDataSourceContext.getRouteKey();String dbName = null; //根据设置的多数据源修改此处,获取dbnameif (dbName == null) {dbName = "DEFAULT";}String url = CatMybatisPlugin.sqlURLCache.get(dbName);if (url != null) {return url;}url = this.getSqlURL();//目前监控只支持mysql ,其余数据库需要各自修改监控服务端if (url == null) {url = String.format(EMPTY_CONNECTION, dbName);}CatMybatisPlugin.sqlURLCache.put(dbName, url);return url;}/*** 解析sql语句** @param configuration* @param boundSql* @return*/public String showSql(Configuration configuration, BoundSql boundSql) {Object parameterObject = boundSql.getParameterObject();List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();String sql = boundSql.getSql().replaceAll("[\\s]+", " ");if (parameterMappings.size() > 0 && parameterObject != null) {TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(parameterObject)));} else {MetaObject metaObject = configuration.newMetaObject(parameterObject);for (ParameterMapping parameterMapping : parameterMappings) {String propertyName = parameterMapping.getProperty();if (metaObject.hasGetter(propertyName)) {Object obj = metaObject.getValue(propertyName);sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));} else if (boundSql.hasAdditionalParameter(propertyName)) {Object obj = boundSql.getAdditionalParameter(propertyName);sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));}}}}return sql;}/*** 参数解析** @param obj* @return*/private String getParameterValue(Object obj) {String value = null;if (obj instanceof String) {value = "'" + obj.toString() + "'";} else if (obj instanceof Date) {DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);value = "'" + formatter.format(new Date()) + "'";} else {if (obj != null) {value = obj.toString();} else {value = "";}}return value;}@Overridepublic Object plugin(Object target) {if (target instanceof Executor) {this.target = (Executor) target;return Plugin.wrap(target, this);}return target;}@Overridepublic void setProperties(Properties properties) {}}

2.数据源配置

package com.gdie.cat.config;import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.gdie.cat.plugin.CatMybatisPlugin;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;/*** @Description 单数据源配置* @Author jiuwei* @Date Created in 下午11:53 2020/4/2* @Version 1.0*/
@Configuration
@EnableTransactionManagement
@MapperScan(basePackages = {"**.mapper"})
public class SingleDataSourceConfig {/*** mybatisplus的全局配置** @return*/@Beanpublic GlobalConfig globalConfiguration() {GlobalConfig conf = new GlobalConfig();return conf;}/*** 分页插件** @return*/@Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor page = new PaginationInterceptor();page.setDialectType("mysql");// 指定数据库类型return page;}@Beanpublic CatMybatisPlugin catMybatisPlugin() {return new CatMybatisPlugin();}
}

在cat上就可以调用接口时sql的情况

美团CAT客户端集成相关推荐

  1. 美团CAT客户端接入方式

    接着CAT服务端安装部署之后,下一步就是考虑客户端应用如何接入CAT的问题了.在这里我们以一个最简单的demo应用(hello world类型)来讲解接入步骤: 很重要的步骤 这里假设你部署服务端跟你 ...

  2. 美团CAT客户端(windows版)接入指南

    背景 我使用cat时,接入的项目既有传统项目又有springboot项目,所以我两种类型的项目介绍一下不同的地方 1.在项目的 pom.xml 中引入如下内容: maven项目 <depende ...

  3. React Native在美团外卖客户端的实践

    MRN简介 MRN(Meituan React Native) 是基于开源的React Native框架改造并完善而成的一套动态化方案,在开发体验上基本能与原生RN保持一致,同时从业务需求的角度满足从 ...

  4. 2000万日订单背后:美团外卖客户端高可用建设体系

    https://blog.csdn.net/MeituanTech/article/details/80534636 背景 美团外卖从2013年11月开始起步,经过数年的高速发展,一直在不断地刷新着记 ...

  5. ASP.NET Core分布式项目实战(客户端集成IdentityServer)--学习笔记

    任务9:客户端集成IdentityServer 新建 API 项目 dotnet new webapi --name ClientCredentialApi 控制器添加验证 using Microso ...

  6. 美团外卖客户端高可用建设体系

    背景 美团外卖从2013年11月开始起步,经过数年的高速发展,一直在不断地刷新着记录.2018年5月19日,日订单量峰值突破2000万单,已经成为全球规模最大的外卖平台.业务的快速发展对系统稳定性提出 ...

  7. CAT客户端架构设计

    1.点评Cat报表.消息类型简介 2.CAT客户端架构设计 3.CAT服务端设计 4.CAT埋点实战 客户端架构设计 客户端方面主要使用ThreadLocal存储本节点消息,保证线程安全 如上图,客户 ...

  8. android客户端集成微信登录

    客户端集成微信登录 1.WXEntryActivity public class WXEntryActivity extends WeCareActivity implements IWXAPIEve ...

  9. 美团cat,修改默认admin登录密码

    美团cat,修改admin密码方式 1.按照如下路径,打开SessionManager类,cat-home下,com.dianping.cat.system.page.login.service.Se ...

最新文章

  1. 2022-2028年全球与中国人字拖市场研究及前瞻分析报告
  2. 【每日一算法】种花问题
  3. 转 CentOS下php安装mcrypt扩展
  4. 使用Prometheus监控Linux系统各项指标
  5. 【OS】进程同步概念
  6. css3 shapes是什么意思,如何在Web中使用CSS Shapes
  7. OpenCV+MFC显示图像
  8. Hadoop——Yarn(4)
  9. Java容器工具类Arrays
  10. Atitit 获取多媒体mp3 mp4 m4a元数据 G:\桌面安装\paidashi\bin\ffprobe.exe ffprobe -i 1.flv -print_format json -sh
  11. hdu 1754 I hate it (线段树)
  12. 简历推荐_5位AI产品经理
  13. mac电脑chrome截长图
  14. HTML5录制音频文件
  15. 查看创建数据库的sql语句
  16. 怎么制作一个蒙版效果
  17. 三十七、缓存注解@Cacheable、@CacheEvict、@CachePut详解
  18. Linux模拟试题及答案(全)
  19. 关于“W: Possible missing firmware /lib/firmware/rtl_nic/rtl8168d-1.fw for module r8169”问题的解决
  20. 6.stm32 低功耗设计--总结

热门文章

  1. JDK的下载与安装(详细版)
  2. 安创安全OA——小程序
  3. 学习SEO第一天[笔记不易]
  4. C# winform表格datagridview行高自动设置问题
  5. Ubantu18.04 安装qq
  6. 实体店收银系统怎么做管理和营销?
  7. Linux设备模型之platform设备
  8. 锤子手机T1发布:售价3000元起 7月初上市
  9. AD转换精度提高方法
  10. 详版大数据报告_如何制作大数据报告