如果需要使用 Spring Data Redis 的话,直接集成 kitty-spring-cloud-starter-redis 就可以,kitty-spring-cloud-starter-redis 中对 Redis 的命令进行了埋点,可以在 Cat 上直观的查看对应的命令和消耗的时间。
添加对应的 Maven 依赖:
<dependency> <groupId>com.cxytiandi</groupId> <artifactId>kitty-spring-cloud-starter-redis</artifactId> <version>Kitty Version</version> </dependency>直接使用 StringRedisTemplate:
@Autowired private StringRedisTemplate stringRedisTemplate; stringRedisTemplate.opsForValue().set("name", "yinjihuan");Cat 中可以看到 Redis 信息。
![]()
点击 Redis 进去可以看到有哪些命令。
![]()
再进去可以看到命令的详细信息,比如操作的 key 和消耗的时间。
![]()
Kitty 中对 Spring Data Mongodb 做了封装,只对 MongoTemplate 做了埋点。使用时需要依赖 kitty-spring-cloud-starter-mongodb。
<dependency> <groupId>com.cxytiandi</groupId> <artifactId>kitty-spring-cloud-starter-mongodb</artifactId> <version>Kitty Version</version> </dependency>在发生 Mongo 的操作后,Cat 上就可以看到相关的数据了。
![]()
点进去就可以看到是 MongoTemplate 的哪个方法发生了调用。
![]()
再进一步就可以看到具体的 Mongo 参数和消耗的时间。
![]()
还有 Dubbo, Feign,Jetcache,ElasticSearch 等框架的埋点就不细讲了,感兴趣的可以移步 Github 查看代码。
Cat 使用小技巧 埋点工具类如果要对业务方法进行监控,我们一般会用 Transaction 功能,将业务逻辑包含在 Transaction 里面,就能监控这个业务的耗时信息。
埋点的方式也是通过 Cat.newTransaction 来进行,具体可以参考上面 Transaction 介绍时给出的埋点示列。
像这种埋点的方式最好是有一个统一的工具类去做,将埋点的细节封装起来。
public class CatTransactionManager { public static <T> T newTransaction(Supplier<T> function, String type, String name, Map<String, Object> data) { Transaction transaction = Cat.newTransaction(type, name); if (data != null && !data.isEmpty()) { data.forEach(transaction::addData); } try { T result = function.get(); transaction.setStatus(Message.SUCCESS); return result; } catch (Exception e) { Cat.logError(e); if (e.getMessage() != null) { Cat.logEvent(type + "_" + name + "_Error", e.getMessage()); } transaction.setStatus(e); throw e; } finally { transaction.complete(); } } }工具类使用:
public SearchResponse search(SearchRequest searchRequest, RequestOptions options) { Map<String, Object> catData = new HashMap<>(1); catData.put(ElasticSearchConstant.SEARCH_REQUEST, searchRequest.toString()); return CatTransactionManager.newTransaction(() -> { try { return restHighLevelClient.search(searchRequest, options); } catch (IOException e) { throw new RuntimeException(e); } }, ElasticSearchConstant.ES_CAT_TYPE, ElasticSearchConstant.SEARCH, catData); }通过使用工具类,不再需要每个监控的地方都是设置 Transaction 是否 complete,是否成功这些信息了。
注解埋点为了让 Transaction 使用更方便,我们可以自定义注解来做这个事情。比如需要监控下单,支付等核心业务方法,那么就可以使用自定义的 Transaction 注解加在方法上,然后通过 AOP 去统一做监控。
定义注解:
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD, ElementType.TYPE}) public @interface CatTransaction { /** * 类型, 默认为Method * @return */ String type() default ""; /** * 名称, 默认为类名.方法名 * @return */ String name() default ""; /** * 是否保存参数信息到Cat * @return */ boolean isSaveParamToCat() default true; }定义切面:
@Aspect public class CatTransactionAspect { @Around("@annotation(catTransaction)") public Object aroundAdvice(ProceedingJoinPoint joinpoint, CatTransaction catTransaction) throws Throwable { String type = catTransaction.type(); if (StringUtils.isEmpty(type)){ type = CatConstantsExt.METHOD; } String name = catTransaction.name(); if (StringUtils.isEmpty(name)){ name = joinpoint.getSignature().getDeclaringType().getSimpleName() + "." + joinpoint.getSignature().getName(); } Map<String, Object> data = new HashMap<>(1); if (catTransaction.isSaveParamToCat()) { Object[] args = joinpoint.getArgs(); if (args != null) { data.put("params", JsonUtils.toJson(args)); } } return CatTransactionManager.newTransaction(() -> { try { return joinpoint.proceed(); } catch (Throwable throwable) { throw new RuntimeException(throwable); } }, type, name, data); } }注解使用:
@CatTransaction @Override public Page<ArticleIndexBO> searchArticleIndex(ArticleIndexSearchParam param) { } 你可能关心的几个问题 Cat 能做链路跟踪吗?
