如果需要使用 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 和消耗的时间。
MongoDB 埋点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 能做链路跟踪吗?