├── .gitignore
├── .settings
├── org.eclipse.wst.jsdt.ui.superType.name
├── org.eclipse.wst.validation.prefs
├── org.eclipse.wst.jsdt.ui.superType.container
├── org.eclipse.core.resources.prefs
├── org.eclipse.m2e.core.prefs
├── org.eclipse.wst.common.project.facet.core.xml
├── org.eclipse.jdt.core.prefs
├── .jsdtscope
└── org.eclipse.wst.common.component
├── README.md
├── src
└── main
│ ├── webapp
│ ├── index.jsp
│ └── WEB-INF
│ │ └── web.xml
│ ├── resources
│ └── META-INF
│ │ └── dubbo
│ │ ├── com.alibaba.dubbo.registry.RegistryFactory
│ │ └── com.alibaba.dubbo.rpc.Filter
│ └── java
│ └── net
│ └── tomjerry
│ └── catmonitor
│ ├── datasource
│ ├── RoutingDataSource.java
│ ├── DataSourceHolder.java
│ ├── DataSource.java
│ ├── AnnotationDataSourceAspect.java
│ └── DataSourceAspectUtil.java
│ ├── common
│ ├── CatContext.java
│ └── CatConstants.java
│ ├── util
│ ├── ThreadHelper.java
│ ├── cache
│ │ ├── CatRedisClient.java
│ │ └── RedisClient.java
│ └── http
│ │ ├── CatCrossHttpClientProxy.java
│ │ └── HttpClientProxy.java
│ ├── dubbospi
│ ├── AppNameAppendFilter.java
│ ├── registry
│ │ └── CatRegistryFactoryWrapper.java
│ └── DubboCatCrossFilter.java
│ ├── filter
│ └── HttpCatCrossFliter.java
│ └── mybatisext
│ └── CatMybatisPlugin.java
├── target
├── classes
│ ├── META-INF
│ │ └── dubbo
│ │ │ ├── com.alibaba.dubbo.registry.RegistryFactory
│ │ │ └── com.alibaba.dubbo.rpc.Filter
│ └── net
│ │ └── tomjerry
│ │ └── catmonitor
│ │ ├── common
│ │ ├── CatConstants.class
│ │ └── CatContext.class
│ │ ├── util
│ │ ├── ThreadHelper.class
│ │ ├── cache
│ │ │ ├── RedisClient$1.class
│ │ │ ├── RedisClient$2.class
│ │ │ ├── RedisClient$3.class
│ │ │ ├── RedisClient$4.class
│ │ │ ├── RedisClient.class
│ │ │ ├── CatRedisClient.class
│ │ │ ├── RedisClient$JedisCallback.class
│ │ │ ├── CatRedisClient$CatJedisCallback.class
│ │ │ └── RedisClient$SharedRedisCallback.class
│ │ └── http
│ │ │ ├── HttpClientProxy.class
│ │ │ ├── CatCrossHttpClientProxy.class
│ │ │ └── HttpClientProxy$StringResponseHandler.class
│ │ ├── datasource
│ │ ├── DataSource.class
│ │ ├── DataSourceHolder.class
│ │ ├── RoutingDataSource.class
│ │ ├── DataSourceAspectUtil.class
│ │ ├── DataSourceAspectUtil$1.class
│ │ └── AnnotationDataSourceAspect.class
│ │ ├── filter
│ │ └── HttpCatCrossFliter.class
│ │ ├── dubbospi
│ │ ├── AppNameAppendFilter.class
│ │ ├── DubboCatCrossFilter.class
│ │ └── registry
│ │ │ ├── CatRegistryFactoryWrapper.class
│ │ │ └── CatRegistryFactoryWrapper$RegistryWrapper.class
│ │ └── mybatisext
│ │ └── CatMybatisPlugin.class
└── m2e-wtp
│ └── web-resources
│ └── META-INF
│ ├── MANIFEST.MF
│ └── maven
│ └── net.tomjerry
│ └── cat-monitor
│ ├── pom.properties
│ └── pom.xml
├── .classpath
├── .project
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.name:
--------------------------------------------------------------------------------
1 | Window
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # cat-monitor
2 | 提供基于大众点评CAT监控的扩展,主要是跨服务的消息树(dubbo、http方式)、Cache以及DB监控等
3 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.validation.prefs:
--------------------------------------------------------------------------------
1 | disabled=06target
2 | eclipse.preferences.version=1
3 |
--------------------------------------------------------------------------------
/src/main/webapp/index.jsp:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World!
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.jsdt.ui.superType.container:
--------------------------------------------------------------------------------
1 | org.eclipse.wst.jsdt.launching.baseBrowserLibrary
--------------------------------------------------------------------------------
/.settings/org.eclipse.core.resources.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | encoding/=UTF-8
3 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.m2e.core.prefs:
--------------------------------------------------------------------------------
1 | activeProfiles=
2 | eclipse.preferences.version=1
3 | resolveWorkspaceProjects=true
4 | version=1
5 |
--------------------------------------------------------------------------------
/target/classes/META-INF/dubbo/com.alibaba.dubbo.registry.RegistryFactory:
--------------------------------------------------------------------------------
1 | catRegistryFactoryWrapper=net.tomjerry.catmonitor.registry.CatRegistryFactoryWrapper
--------------------------------------------------------------------------------
/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.registry.RegistryFactory:
--------------------------------------------------------------------------------
1 | catRegistryFactoryWrapper=net.tomjerry.catmonitor.dubbospi.registry.CatRegistryFactoryWrapper
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Build-Jdk: 1.7.0_79
3 | Built-By: lenovo
4 | Created-By: Maven Integration for Eclipse
5 |
6 |
--------------------------------------------------------------------------------
/target/classes/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter:
--------------------------------------------------------------------------------
1 | dubboCatFilter=net.tomjerry.catmonitor.dubbospi.DubboCatFilter
2 | appnameAppend=net.tomjerry.catmonitor.AppNameAppendFilter
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/common/CatConstants.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/common/CatConstants.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/common/CatContext.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/common/CatContext.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/ThreadHelper.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/ThreadHelper.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/datasource/DataSource.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/datasource/DataSource.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$1.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$2.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$2.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$3.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$3.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$4.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$4.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/filter/HttpCatCrossFliter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/filter/HttpCatCrossFliter.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/CatRedisClient.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/CatRedisClient.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/http/HttpClientProxy.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/http/HttpClientProxy.class
--------------------------------------------------------------------------------
/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter:
--------------------------------------------------------------------------------
1 | dubboCatCrossFilter=net.tomjerry.catmonitor.dubbospi.DubboCatCrossFilter
2 | appnameAppend=net.tomjerry.catmonitor.dubbospi.AppNameAppendFilter
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/datasource/DataSourceHolder.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/datasource/DataSourceHolder.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/datasource/RoutingDataSource.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/datasource/RoutingDataSource.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/dubbospi/AppNameAppendFilter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/dubbospi/AppNameAppendFilter.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/dubbospi/DubboCatCrossFilter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/dubbospi/DubboCatCrossFilter.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/mybatisext/CatMybatisPlugin.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/mybatisext/CatMybatisPlugin.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/datasource/DataSourceAspectUtil.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/datasource/DataSourceAspectUtil.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/datasource/DataSourceAspectUtil$1.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/datasource/DataSourceAspectUtil$1.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/http/CatCrossHttpClientProxy.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/http/CatCrossHttpClientProxy.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$JedisCallback.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$JedisCallback.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/datasource/AnnotationDataSourceAspect.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/datasource/AnnotationDataSourceAspect.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/dubbospi/registry/CatRegistryFactoryWrapper.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/dubbospi/registry/CatRegistryFactoryWrapper.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/CatRedisClient$CatJedisCallback.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/CatRedisClient$CatJedisCallback.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$SharedRedisCallback.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/cache/RedisClient$SharedRedisCallback.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/util/http/HttpClientProxy$StringResponseHandler.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/util/http/HttpClientProxy$StringResponseHandler.class
--------------------------------------------------------------------------------
/target/classes/net/tomjerry/catmonitor/dubbospi/registry/CatRegistryFactoryWrapper$RegistryWrapper.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/summerpotato/cat-monitor/HEAD/target/classes/net/tomjerry/catmonitor/dubbospi/registry/CatRegistryFactoryWrapper$RegistryWrapper.class
--------------------------------------------------------------------------------
/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
6 | Archetype Created Web Application
7 |
8 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.project.facet.core.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/maven/net.tomjerry/cat-monitor/pom.properties:
--------------------------------------------------------------------------------
1 | #Generated by Maven Integration for Eclipse
2 | #Mon Jun 20 12:01:28 CST 2016
3 | version=0.0.1-SNAPSHOT
4 | groupId=net.tomjerry
5 | m2e.projectName=cat-monitor
6 | m2e.projectLocation=D\:\\Zorkspace\\luna4.4-workspc2\\cat-monitor
7 | artifactId=cat-monitor
8 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.jdt.core.prefs:
--------------------------------------------------------------------------------
1 | eclipse.preferences.version=1
2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
4 | org.eclipse.jdt.core.compiler.compliance=1.7
5 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
6 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
7 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
8 | org.eclipse.jdt.core.compiler.source=1.7
9 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/datasource/RoutingDataSource.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.datasource;
2 |
3 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
4 |
5 | /**
6 | * 根据线程中数据源名称,返回数据源
7 | * @author potato
8 | *
9 | */
10 | public class RoutingDataSource extends AbstractRoutingDataSource {
11 |
12 | @Override
13 | protected Object determineCurrentLookupKey() {
14 | return DataSourceHolder.getDBName();
15 | }
16 |
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/datasource/DataSourceHolder.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.datasource;
2 |
3 | /**
4 | * 在当前线程中保存数据源信息
5 | *
6 | * @author potato
7 | */
8 | public class DataSourceHolder {
9 |
10 | private static final ThreadLocal contextHolder = new ThreadLocal();
11 |
12 | public static void setDBName(String dbName) {
13 | contextHolder.set(dbName);
14 | }
15 |
16 | public static String getDBName() {
17 | return contextHolder.get();
18 | }
19 |
20 | public static void clearDBName() {
21 | contextHolder.remove();
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/.settings/.jsdtscope:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/common/CatContext.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.common;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | import com.dianping.cat.Cat;
7 |
8 | /**
9 | * 实现CAT上下文,以用来传递messageTreeId
10 | * @author potato
11 | * @date 2016-6-8
12 | */
13 | public class CatContext implements Cat.Context {
14 |
15 | private Map properties = new HashMap();
16 |
17 | @Override
18 | public void addProperty(String key, String value) {
19 | properties.put(key, value);
20 | }
21 |
22 | @Override
23 | public String getProperty(String key) {
24 | return properties.get(key);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/datasource/DataSource.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.datasource;
2 |
3 | import java.lang.annotation.Documented;
4 | import java.lang.annotation.ElementType;
5 | import java.lang.annotation.Inherited;
6 | import java.lang.annotation.Retention;
7 | import java.lang.annotation.RetentionPolicy;
8 | import java.lang.annotation.Target;
9 |
10 | /**
11 | * 多数据源标签 - 根据value值切换数据源
12 | * @author potato
13 | *
14 | */
15 | @Retention(RetentionPolicy.RUNTIME)
16 | @Target({ElementType.METHOD, ElementType.TYPE})
17 | @Inherited
18 | @Documented
19 | public @interface DataSource {
20 |
21 | /**
22 | * database name
23 | * @return
24 | */
25 | String value() default "";
26 | }
27 |
--------------------------------------------------------------------------------
/.settings/org.eclipse.wst.common.component:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/datasource/AnnotationDataSourceAspect.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.datasource;
2 |
3 | import org.aspectj.lang.ProceedingJoinPoint;
4 | import org.aspectj.lang.annotation.Around;
5 | import org.aspectj.lang.annotation.Aspect;
6 | import org.springframework.core.Ordered;
7 |
8 | /**
9 | * 将数据库名(DataSource注解的value值)保存到当前线程
10 | * @author potato
11 | *
12 | */
13 | @Aspect
14 | public class AnnotationDataSourceAspect implements Ordered {
15 |
16 | @Around("@annotation(net.tomjerry.catmonitor.datasource.DataSource)")
17 | public Object selectDataSource(ProceedingJoinPoint point) throws Throwable {
18 | return DataSourceAspectUtil.selectDataSource(point);
19 | }
20 |
21 | @Override
22 | public int getOrder() {
23 | //确保在@Transactional之前调用
24 | return 0;
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/util/ThreadHelper.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.util;
2 |
3 | import java.util.concurrent.TimeUnit;
4 |
5 | /**
6 | * 线程相关工具类
7 | *
8 | * @author potato
9 | */
10 | public class ThreadHelper {
11 |
12 | /**
13 | * sleep等待,单位为ms,已捕捉并处理InterruptedException.
14 | */
15 | public static void sleep(long durationMillis){
16 | try {
17 | Thread.sleep(durationMillis);
18 | } catch (InterruptedException e) {
19 | Thread.currentThread().interrupt();
20 | }
21 | }
22 |
23 | /**
24 | * sleep等待,已捕捉并处理InterruptedException.
25 | */
26 | public static void sleep(long duration, TimeUnit unit){
27 | try {
28 | Thread.sleep(unit.toMillis(duration));
29 | } catch (InterruptedException e) {
30 | Thread.currentThread().interrupt();
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/dubbospi/AppNameAppendFilter.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.dubbospi;
2 |
3 | import com.alibaba.dubbo.common.Constants;
4 | import com.alibaba.dubbo.common.extension.Activate;
5 | import com.alibaba.dubbo.rpc.Filter;
6 | import com.alibaba.dubbo.rpc.Invocation;
7 | import com.alibaba.dubbo.rpc.Invoker;
8 | import com.alibaba.dubbo.rpc.Result;
9 | import com.alibaba.dubbo.rpc.RpcContext;
10 | import com.alibaba.dubbo.rpc.RpcException;
11 |
12 | /**
13 | * 获取application-name
14 | * @author potato
15 | */
16 | @Activate(group = {Constants.CONSUMER})
17 | public class AppNameAppendFilter implements Filter {
18 |
19 | @Override
20 | public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
21 | RpcContext.getContext().setAttachment(Constants.APPLICATION_KEY, invoker.getUrl().getParameter(Constants.APPLICATION_KEY));
22 | return invoker.invoke(invocation);
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/common/CatConstants.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.common;
2 |
3 | /**
4 | * CAT相关关键字定义
5 | * @author potato
6 | *
7 | */
8 | public interface CatConstants {
9 |
10 | public static final String CROSS_CONSUMER = "PigeonCall";
11 |
12 | public static final String CROSS_SERVER = "PigeonService";
13 |
14 | public static final String CONSUMER_CALL_SERVER = "PigeonCall.server";
15 |
16 | public static final String CONSUMER_CALL_APP = "PigeonCall.app";
17 |
18 | public static final String CONSUMER_CALL_PORT = "PigeonCall.port";
19 |
20 | public static final String PROVIDER_SERVICE_CLIENT = "PigeonService.client";
21 |
22 | public static final String PROVIDER_SERVICE_APP = "PigeonService.app";
23 |
24 | public static final String CLIENT_APPLICATION_NAME = "ClientApplication.Name";
25 |
26 | public static final String DUBBO_PROVIDER_APPLICATION_NAME = "serverApplicationName";
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | cat-monitor
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.wst.jsdt.core.javascriptValidator
10 |
11 |
12 |
13 |
14 | org.eclipse.jdt.core.javabuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.wst.common.project.facet.core.builder
20 |
21 |
22 |
23 |
24 | org.eclipse.m2e.core.maven2Builder
25 |
26 |
27 |
28 |
29 | org.eclipse.wst.validation.validationbuilder
30 |
31 |
32 |
33 |
34 |
35 | org.eclipse.jem.workbench.JavaEMFNature
36 | org.eclipse.wst.common.modulecore.ModuleCoreNature
37 | org.eclipse.jdt.core.javanature
38 | org.eclipse.m2e.core.maven2Nature
39 | org.eclipse.wst.common.project.facet.core.nature
40 | org.eclipse.wst.jsdt.core.jsNature
41 |
42 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/dubbospi/registry/CatRegistryFactoryWrapper.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.dubbospi.registry;
2 |
3 | import java.util.List;
4 |
5 | import net.tomjerry.catmonitor.common.CatConstants;
6 |
7 | import com.alibaba.dubbo.common.Constants;
8 | import com.alibaba.dubbo.common.URL;
9 | import com.alibaba.dubbo.registry.NotifyListener;
10 | import com.alibaba.dubbo.registry.Registry;
11 | import com.alibaba.dubbo.registry.RegistryFactory;
12 |
13 | /**
14 | * 获取应用名称
15 | * @author potato
16 | */
17 | public class CatRegistryFactoryWrapper implements RegistryFactory {
18 |
19 | private RegistryFactory registryFactory;
20 |
21 | public CatRegistryFactoryWrapper(RegistryFactory registryFactory) {
22 | this.registryFactory = registryFactory;
23 | }
24 |
25 | @Override
26 | public Registry getRegistry(URL url) {
27 | return new RegistryWrapper(registryFactory.getRegistry(url));
28 | }
29 |
30 | class RegistryWrapper implements Registry {
31 | private Registry originRegistry;
32 | private URL appendProviderAppName(URL url){
33 | String side = url.getParameter(Constants.SIDE_KEY);
34 | if(Constants.PROVIDER_SIDE.equals(side)){
35 | url = url.addParameter(CatConstants.DUBBO_PROVIDER_APPLICATION_NAME, url.getParameter(Constants.APPLICATION_KEY));
36 | }
37 | return url;
38 | }
39 |
40 | public RegistryWrapper(Registry originRegistry) {
41 | this.originRegistry = originRegistry;
42 | }
43 |
44 | @Override
45 | public URL getUrl() {
46 | return originRegistry.getUrl();
47 | }
48 |
49 | @Override
50 | public boolean isAvailable() {
51 | return originRegistry.isAvailable();
52 | }
53 |
54 | @Override
55 | public void destroy() {
56 | originRegistry.destroy();
57 | }
58 |
59 | @Override
60 | public void register(URL url) {
61 | originRegistry.register(appendProviderAppName(url));
62 | }
63 |
64 | @Override
65 | public void unregister(URL url) {
66 | originRegistry.unregister(appendProviderAppName(url));
67 | }
68 |
69 | @Override
70 | public void subscribe(URL url, NotifyListener listener) {
71 | originRegistry.subscribe(url, listener);
72 | }
73 |
74 | @Override
75 | public void unsubscribe(URL url, NotifyListener listener) {
76 | originRegistry.unsubscribe(url, listener);
77 | }
78 |
79 | @Override
80 | public List lookup(URL url) {
81 | return originRegistry.lookup(appendProviderAppName(url));
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/datasource/DataSourceAspectUtil.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.datasource;
2 |
3 | import org.aspectj.lang.JoinPoint;
4 | import org.aspectj.lang.ProceedingJoinPoint;
5 | import org.aspectj.lang.reflect.MethodSignature;
6 | import org.springframework.core.annotation.AnnotationUtils;
7 | import org.springframework.util.ConcurrentReferenceHashMap;
8 |
9 | import java.lang.annotation.Annotation;
10 | import java.lang.reflect.Method;
11 | import java.util.Map;
12 |
13 | /**
14 | * 动态切换数据源,切面可调用本方法
15 | * @author potato
16 | */
17 | public class DataSourceAspectUtil {
18 |
19 | //注解缓存,提高性能
20 | private static final Map findAnnotationCache =
21 | new ConcurrentReferenceHashMap(256);
22 |
23 |
24 | public static Object selectDataSource(ProceedingJoinPoint point) throws Throwable {
25 | String currentDB = DataSourceHolder.getDBName();
26 | if (currentDB == null) {
27 | /**
28 | * 只有在上下文中没有指定数据库时才选择数据库
29 | * 确保在一个嵌套Session中使用同一个DB
30 | * 即:如果在Controller和DAO(或Mapper)中指定同时指定了DB,Controller中的值将被使用
31 | */
32 | DataSource a = getDataSourceAnnotation(point);
33 | if (a != null && a != NULL_ANNOTATION) {
34 | String dbName = a.value();
35 | DataSourceHolder.setDBName(dbName);
36 | }
37 | }
38 |
39 | try {
40 | Object result = point.proceed();
41 | return result;
42 | } finally {
43 | //恢复当前线程中的设置
44 | DataSourceHolder.setDBName(currentDB);
45 | }
46 | }
47 |
48 | /**
49 | * 从方法或类或实现的接口中获取DataSource注解
50 | */
51 | private static DataSource getDataSourceAnnotation(JoinPoint point) throws NoSuchMethodException, SecurityException {
52 | Object target = point.getTarget();
53 | Class> classz = target.getClass();
54 | String methodName = point.getSignature().getName();
55 | Class>[] parameterTypes = ((MethodSignature) point.getSignature())
56 | .getMethod().getParameterTypes();
57 | Method method = target.getClass().getMethod(methodName, parameterTypes);
58 |
59 | DataSource result = findAnnotationCache.get(method);
60 | if (result == NULL_ANNOTATION) {
61 | return null;
62 | }
63 | if (result != null) {
64 | return result;
65 | }
66 |
67 | result = AnnotationUtils.findAnnotation(method, DataSource.class);
68 | if (result == null) {
69 | result = AnnotationUtils.findAnnotation(classz, DataSource.class);
70 | }
71 | if (result == null) {
72 | result = NULL_ANNOTATION;
73 | }
74 |
75 | findAnnotationCache.put(method, result);//保存到缓存
76 |
77 | return result;
78 | }
79 |
80 |
81 | //定义个NULL常量,方便缓存
82 | private static final DataSource NULL_ANNOTATION = new DataSource() {
83 | @Override
84 | public Class extends Annotation> annotationType() {
85 | return null;
86 | }
87 |
88 | @Override
89 | public String value() {
90 | return null;
91 | }
92 | };
93 | }
94 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/util/cache/CatRedisClient.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.util.cache;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import redis.clients.jedis.Jedis;
8 |
9 | import com.dianping.cat.Cat;
10 | import com.dianping.cat.message.Transaction;
11 |
12 | /**
13 | * 添加了Cat监控的Redis工具类
14 | * 只对execute(JedisCallback jedisCallback, String key)添加了监控
15 | * execute(SharedRedisCallback redisCallback)需要自己添加cat监控
16 | *
17 | * @author potato
18 | */
19 | public class CatRedisClient extends RedisClient {
20 |
21 | private Logger logger = LoggerFactory.getLogger(CatRedisClient.class);
22 |
23 | public static final String REDIS_TYPE_PREFIX = "Cache.";
24 | public static final String REDIS_EVENT_TYPE = "Cache.redis.server";
25 | private static final String REDIS_SERVER_IP_PATTERN = "%s(%s)";
26 |
27 | //cat auth level,设置这个字段在cat报表中区分不同的auth level
28 | private String catAuthLevel = "default";
29 |
30 | private String redisGroup; //需注入来初始化,redis分组,用于在CAT分类redis服务器
31 | private String redisType;
32 |
33 | public String getRedisGroup() {
34 | return redisGroup;
35 | }
36 |
37 | public void setRedisGroup(String redisGroup) {
38 | this.redisGroup = redisGroup;
39 |
40 | if(StringUtils.isBlank(redisGroup)){
41 | this.redisType = "Cache.redis";
42 | }else{
43 | this.redisType = REDIS_TYPE_PREFIX + this.redisGroup;
44 | }
45 | }
46 |
47 | @Override
48 | public T execute(JedisCallback jedisCallback, String key) {
49 | return super.execute(new CatJedisCallback(jedisCallback), key);
50 | }
51 |
52 | public class CatJedisCallback implements JedisCallback {
53 | private JedisCallback callback;
54 | public CatJedisCallback(JedisCallback callback) {
55 | this.callback = callback;
56 | }
57 |
58 | @Override
59 | public T doInJedis(Jedis jedis) {
60 | String host = jedis.getClient().getHost();
61 | int port = jedis.getClient().getPort();
62 |
63 | Transaction t = Cat.newTransaction(redisType, CatRedisClient.this.catAuthLevel + ':' + this.callback.redisMethodName());
64 |
65 | Cat.logEvent(REDIS_EVENT_TYPE, String.format(REDIS_SERVER_IP_PATTERN, host, port));
66 | try {
67 | T ret = this.callback.doInJedis(jedis);
68 | t.setStatus(Transaction.SUCCESS);
69 | return ret;
70 | } catch (Exception e) {
71 | t.setStatus(e.getClass().getSimpleName());
72 | //throw e;
73 |
74 | logger.error("--- redis cat error : ", e);
75 | return null;
76 |
77 | } finally {
78 | t.complete();
79 | }
80 | }
81 |
82 | @Override
83 | public String redisMethodName() {
84 | return this.callback.redisMethodName();
85 | }
86 | }
87 |
88 | public String getCatAuthLevel() {
89 | return catAuthLevel;
90 | }
91 |
92 | public void setCatAuthLevel(String catAuthLevel) {
93 | this.catAuthLevel = catAuthLevel;
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/target/m2e-wtp/web-resources/META-INF/maven/net.tomjerry/cat-monitor/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | net.tomjerry
5 | cat-monitor
6 | war
7 | 0.0.1-SNAPSHOT
8 | cat-monitor Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 3.2.9.RELEASE
13 | 4.4
14 | 3.4
15 | 1.7.12
16 | 2.8.0
17 |
18 |
19 |
20 |
21 | junit
22 | junit
23 | 3.8.1
24 | test
25 |
26 |
27 |
28 | org.springframework
29 | spring-context
30 | ${spring.version}
31 |
32 |
33 | org.springframework
34 | spring-jdbc
35 | ${spring.version}
36 |
37 |
38 | org.apache.httpcomponents
39 | httpclient
40 | ${httpclient.version}
41 |
42 |
43 | org.slf4j
44 | slf4j-api
45 | ${slf4j.version}
46 |
47 |
48 | org.apache.commons
49 | commons-lang3
50 | ${commons.lang3.version}
51 |
52 |
53 |
54 | com.alibaba
55 | dubbo
56 | 2.8.4
57 |
58 |
59 |
60 | com.dianping.cat
61 | cat-client
62 | 1.3.6
63 |
64 |
65 |
66 | redis.clients
67 | jedis
68 | ${jedis.version}
69 |
70 |
71 |
72 |
73 |
74 | org.mybatis
75 | mybatis
76 | 3.3.1
77 |
78 |
79 |
80 | org.mybatis
81 | mybatis-spring
82 | 1.2.2
83 |
84 |
85 |
86 |
87 | mysql
88 | mysql-connector-java
89 | 5.1.38
90 |
91 |
92 |
93 |
94 | com.alibaba
95 | druid
96 | 1.0.16
97 |
98 |
99 |
100 |
101 | cat-monitor
102 |
103 |
104 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
3 | 4.0.0
4 | net.tomjerry
5 | cat-monitor
6 | jar
7 | 1.0.0.RELEASE
8 | cat-monitor Maven Webapp
9 | http://maven.apache.org
10 |
11 |
12 | 3.2.9.RELEASE
13 | 4.4
14 | 3.4
15 | 1.7.12
16 | 2.8.0
17 |
18 | UTF-8
19 |
20 |
21 |
22 |
23 | junit
24 | junit
25 | 3.8.1
26 | test
27 |
28 |
29 |
30 | org.springframework
31 | spring-context
32 | ${spring.version}
33 |
34 |
35 | org.springframework
36 | spring-jdbc
37 | ${spring.version}
38 |
39 |
40 | org.apache.httpcomponents
41 | httpclient
42 | ${httpclient.version}
43 |
44 |
45 | org.slf4j
46 | slf4j-api
47 | ${slf4j.version}
48 |
49 |
50 | org.apache.commons
51 | commons-lang3
52 | ${commons.lang3.version}
53 |
54 |
55 |
56 | com.alibaba
57 | dubbo
58 | 2.8.4
59 |
60 |
61 |
62 | com.dianping.cat
63 | cat-client
64 | 1.3.6
65 |
66 |
67 |
68 | redis.clients
69 | jedis
70 | ${jedis.version}
71 |
72 |
73 |
74 |
75 |
76 | org.mybatis
77 | mybatis
78 | 3.3.1
79 |
80 |
81 |
82 | org.mybatis
83 | mybatis-spring
84 | 1.2.2
85 |
86 |
87 |
88 |
89 | mysql
90 | mysql-connector-java
91 | 5.1.38
92 |
93 |
94 |
95 |
96 | com.alibaba
97 | druid
98 | 1.0.16
99 |
100 |
101 |
102 |
103 |
104 |
105 | cat-monitor
106 |
107 |
108 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/filter/HttpCatCrossFliter.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.filter;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.Filter;
6 | import javax.servlet.FilterChain;
7 | import javax.servlet.FilterConfig;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.ServletRequest;
10 | import javax.servlet.ServletResponse;
11 | import javax.servlet.http.HttpServletRequest;
12 |
13 | import org.slf4j.Logger;
14 | import org.slf4j.LoggerFactory;
15 |
16 | import net.tomjerry.catmonitor.common.CatConstants;
17 | import net.tomjerry.catmonitor.common.CatContext;
18 |
19 | import com.dianping.cat.Cat;
20 | import com.dianping.cat.message.Event;
21 | import com.dianping.cat.message.Transaction;
22 | import com.dianping.cat.message.internal.AbstractMessage;
23 | import com.dianping.cat.message.internal.NullMessage;
24 |
25 | /**
26 | * 服务提供侧串联消息树
27 | * @author potato
28 | * @date 2016-6-8 11:36:10
29 | */
30 | public class HttpCatCrossFliter implements Filter {
31 |
32 | private static final Logger logger = LoggerFactory.getLogger(HttpCatCrossFliter.class);
33 |
34 | private static final String DEFAULT_APPLICATION_NAME = "default";
35 |
36 | @Override
37 | public void doFilter(ServletRequest req, ServletResponse resp, FilterChain filterChain) throws IOException, ServletException {
38 |
39 | HttpServletRequest request = (HttpServletRequest) req;
40 | String requestURI = request.getRequestURI();
41 |
42 | Transaction t = Cat.newTransaction(CatConstants.CROSS_SERVER, requestURI);
43 |
44 | try{
45 | Cat.Context context = new CatContext();
46 | context.addProperty(Cat.Context.ROOT, request.getHeader(Cat.Context.ROOT));
47 | context.addProperty(Cat.Context.PARENT, request.getHeader(Cat.Context.PARENT));
48 | context.addProperty(Cat.Context.CHILD, request.getHeader(Cat.Context.CHILD));
49 | Cat.logRemoteCallServer(context);
50 | this.createProviderCross(request, t);
51 |
52 | filterChain.doFilter(req, resp);
53 | t.setStatus(Transaction.SUCCESS);
54 | } catch (Exception e) {
55 | logger.error("------ Get cat msgtree error : ", e);
56 |
57 | Event event = null;
58 | event = Cat.newEvent("HTTP_REST_CAT_ERROR", requestURI);
59 | event.setStatus(e);
60 | completeEvent(event);
61 | t.addChild(event);
62 | t.setStatus(e.getClass().getSimpleName());
63 | } finally {
64 | t.complete();
65 | }
66 |
67 | }
68 |
69 | @Override
70 | public void init(FilterConfig arg0) throws ServletException {
71 | }
72 |
73 | @Override
74 | public void destroy() {
75 | }
76 |
77 | /**
78 | * 串联provider端消息树
79 | * @param request
80 | * @param t
81 | */
82 | private void createProviderCross(HttpServletRequest request, Transaction t){
83 |
84 | Event crossAppEvent = Cat.newEvent(CatConstants.PROVIDER_SERVICE_APP, request.getHeader(CatConstants.CLIENT_APPLICATION_NAME)); //clientName
85 | Event crossServerEvent = Cat.newEvent(CatConstants.PROVIDER_SERVICE_CLIENT, request.getRemoteAddr()); //clientIp
86 | crossAppEvent.setStatus(Event.SUCCESS);
87 | crossServerEvent.setStatus(Event.SUCCESS);
88 | completeEvent(crossAppEvent);
89 | completeEvent(crossServerEvent);
90 | t.addChild(crossAppEvent);
91 | t.addChild(crossServerEvent);
92 | }
93 |
94 | private void completeEvent(Event event){
95 | if (event != NullMessage.EVENT) {
96 | AbstractMessage message = (AbstractMessage) event;
97 | message.setCompleted(true);
98 | }
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/util/http/CatCrossHttpClientProxy.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.util.http;
2 |
3 | import java.io.IOException;
4 |
5 | import net.tomjerry.catmonitor.common.CatConstants;
6 | import net.tomjerry.catmonitor.common.CatContext;
7 |
8 | import org.apache.http.annotation.ThreadSafe;
9 | import org.apache.http.client.methods.HttpRequestBase;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | import com.dianping.cat.Cat;
14 | import com.dianping.cat.message.Event;
15 | import com.dianping.cat.message.Transaction;
16 | import com.dianping.cat.message.internal.AbstractMessage;
17 | import com.dianping.cat.message.internal.NullMessage;
18 |
19 | /**
20 | * 支持CatCross监控的HttpClient类
21 | *
22 | * @author potato
23 | * @date 2016-6-8
24 | */
25 | @ThreadSafe
26 | public class CatCrossHttpClientProxy extends HttpClientProxy {
27 |
28 | private Logger logger = LoggerFactory.getLogger(CatCrossHttpClientProxy.class);
29 |
30 | //please inject this attr in the spring-applicationContext
31 | private String applicationName;
32 |
33 | public String getApplicationName() {
34 | return applicationName;
35 | }
36 |
37 | public void setApplicationName(String applicationName) {
38 | this.applicationName = applicationName;
39 | }
40 |
41 | /**
42 | * 发起Http请求
43 | * 较复杂的请求如设置HttpHeader等,可调用本方法执行
44 | * @param request
45 | * @param socketTimeout
46 | * @param connectTimeout
47 | * @return
48 | * @throws IOException
49 | */
50 | public String execute(HttpRequestBase request, int socketTimeout, int connectTimeout) throws IOException {
51 | Transaction t = Cat.newTransaction(CatConstants.CROSS_CONSUMER, request.getURI().getPath());
52 |
53 | //串联message-tree埋点
54 | this.createConsumerCross(request, t);
55 | Cat.Context context = new CatContext();
56 | Cat.logRemoteCallClient(context);
57 | request.setHeader(Cat.Context.ROOT, context.getProperty(Cat.Context.ROOT));
58 | request.setHeader(Cat.Context.PARENT, context.getProperty(Cat.Context.PARENT));
59 | request.setHeader(Cat.Context.CHILD, context.getProperty(Cat.Context.CHILD));
60 |
61 | //设置服务消费方的clientName
62 | request.setHeader(CatConstants.CLIENT_APPLICATION_NAME, applicationName);
63 |
64 | try {
65 | String ret = super.execute(request, socketTimeout, connectTimeout);
66 | t.setStatus(Transaction.SUCCESS);
67 | return ret;
68 | } catch (IOException e) {
69 |
70 | Event event = null;
71 | event = Cat.newEvent("HTTP_REST_CAT_ERROR", request.getURI().getPath());
72 | event.setStatus(e);
73 | completeEvent(event);
74 | t.addChild(event);
75 | t.setStatus(e.getClass().getSimpleName());
76 | throw e;
77 | } finally {
78 | t.complete();
79 | }
80 | }
81 |
82 | private void createConsumerCross(HttpRequestBase request, Transaction t) {
83 |
84 | String uriPath = request.getURI().getPath();
85 | Event crossAppEvent = Cat.newEvent(CatConstants.CONSUMER_CALL_APP, uriPath.substring(0, uriPath.lastIndexOf("/"))); //serverName
86 | Event crossServerEvent = Cat.newEvent(CatConstants.CONSUMER_CALL_SERVER, request.getURI().getHost()); //serverIp
87 | Event crossPortEvent = Cat.newEvent(CatConstants.CONSUMER_CALL_PORT, String.valueOf(request.getURI().getPort()));
88 | crossAppEvent.setStatus(Event.SUCCESS);
89 | crossServerEvent.setStatus(Event.SUCCESS);
90 | crossPortEvent.setStatus(Event.SUCCESS);
91 | completeEvent(crossAppEvent);
92 | completeEvent(crossPortEvent);
93 | completeEvent(crossServerEvent);
94 | t.addChild(crossAppEvent);
95 | t.addChild(crossPortEvent);
96 | t.addChild(crossServerEvent);
97 | }
98 |
99 | private void completeEvent(Event event){
100 | if (event != NullMessage.EVENT) {
101 | AbstractMessage message = (AbstractMessage) event;
102 | message.setCompleted(true);
103 | }
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/mybatisext/CatMybatisPlugin.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.mybatisext;
2 |
3 | import java.lang.reflect.Field;
4 | import java.lang.reflect.Method;
5 | import java.util.Map;
6 | import java.util.Properties;
7 |
8 | import net.tomjerry.catmonitor.datasource.DataSourceHolder;
9 |
10 | import org.apache.ibatis.executor.Executor;
11 | import org.apache.ibatis.mapping.MappedStatement;
12 | import org.apache.ibatis.mapping.SqlCommandType;
13 | import org.apache.ibatis.plugin.Interceptor;
14 | import org.apache.ibatis.plugin.Intercepts;
15 | import org.apache.ibatis.plugin.Invocation;
16 | import org.apache.ibatis.plugin.Plugin;
17 | import org.apache.ibatis.plugin.Signature;
18 | import org.apache.ibatis.session.ResultHandler;
19 | import org.apache.ibatis.session.RowBounds;
20 | import org.mybatis.spring.transaction.SpringManagedTransaction;
21 | import org.slf4j.Logger;
22 | import org.slf4j.LoggerFactory;
23 | import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
24 | import org.springframework.util.ConcurrentReferenceHashMap;
25 | import org.springframework.util.ReflectionUtils;
26 |
27 | import com.alibaba.druid.pool.DruidDataSource;
28 | import com.dianping.cat.Cat;
29 | import com.dianping.cat.message.Transaction;
30 |
31 | /**
32 | * 对MyBatis进行拦截,添加Cat监控
33 | * 目前仅支持RoutingDataSource和Druid组合配置的数据源
34 | *
35 | * @author potato
36 | */
37 |
38 | @Intercepts({
39 | @Signature(method = "query", type = Executor.class, args = {
40 | MappedStatement.class, Object.class, RowBounds.class,
41 | ResultHandler.class }),
42 | @Signature(method = "update", type = Executor.class, args = { MappedStatement.class, Object.class })
43 | })
44 | public class CatMybatisPlugin implements Interceptor {
45 |
46 | private static Logger logger = LoggerFactory.getLogger(CatMybatisPlugin.class);
47 |
48 | //缓存,提高性能
49 | private static final Map sqlURLCache = new ConcurrentReferenceHashMap(256);
50 |
51 | private static final String EMPTY_CONNECTION = "jdbc:mysql://unknown:3306/%s?useUnicode=true";
52 |
53 | private Executor target;
54 |
55 | @Override
56 | public Object intercept(Invocation invocation) throws Throwable {
57 | MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
58 | //得到类名,方法
59 | String[] strArr = mappedStatement.getId().split("\\.");
60 | String methodName = strArr[strArr.length - 2] + "." + strArr[strArr.length - 1];
61 |
62 |
63 | Transaction t = Cat.newTransaction("SQL", methodName);
64 |
65 | //获取SQL类型
66 | SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
67 | Cat.logEvent("SQL.Method", sqlCommandType.name().toLowerCase());
68 |
69 | String s = this.getSQLDatabase();
70 | Cat.logEvent("SQL.Database", s);
71 |
72 | Object returnObj = null;
73 | try {
74 | returnObj = invocation.proceed();
75 | t.setStatus(Transaction.SUCCESS);
76 | } catch (Exception e) {
77 | Cat.logError(e);
78 | } finally {
79 | t.complete();
80 | }
81 |
82 | return returnObj;
83 | }
84 |
85 | private javax.sql.DataSource getDataSource() {
86 | org.apache.ibatis.transaction.Transaction transaction = this.target.getTransaction();
87 | if (transaction == null) {
88 | logger.error(String.format("Could not find transaction on target [%s]", this.target));
89 | return null;
90 | }
91 | if (transaction instanceof SpringManagedTransaction) {
92 | String fieldName = "dataSource";
93 | Field field = ReflectionUtils.findField(transaction.getClass(), fieldName, javax.sql.DataSource.class);
94 |
95 | if (field == null) {
96 | logger.error(String.format("Could not find field [%s] of type [%s] on target [%s]",
97 | fieldName, javax.sql.DataSource.class, this.target));
98 | return null;
99 | }
100 |
101 | ReflectionUtils.makeAccessible(field);
102 | javax.sql.DataSource dataSource = (javax.sql.DataSource) ReflectionUtils.getField(field, transaction);
103 | return dataSource;
104 | }
105 |
106 | logger.error(String.format("---the transaction is not SpringManagedTransaction:%s", transaction.getClass().toString()));
107 |
108 | return null;
109 | }
110 |
111 | private String getSqlURL() {
112 | javax.sql.DataSource dataSource = this.getDataSource();
113 |
114 | if (dataSource == null) {
115 | return null;
116 | }
117 |
118 | if (dataSource instanceof AbstractRoutingDataSource) {
119 | String methodName = "determineTargetDataSource";
120 | Method method = ReflectionUtils.findMethod(AbstractRoutingDataSource.class, methodName);
121 |
122 | if (method == null) {
123 | logger.error(String.format("---Could not find method [%s] on target [%s]",
124 | methodName, dataSource));
125 | return null;
126 | }
127 |
128 | ReflectionUtils.makeAccessible(method);
129 | javax.sql.DataSource dataSource1 = (javax.sql.DataSource) ReflectionUtils.invokeMethod(method, dataSource);
130 | if (dataSource1 instanceof DruidDataSource) {
131 | DruidDataSource druidDataSource = (DruidDataSource) dataSource1;
132 | return druidDataSource.getUrl();
133 | } else {
134 | logger.error("---only surpport DruidDataSource:" + dataSource1.getClass().toString());
135 | }
136 | }
137 | return null;
138 | }
139 |
140 | private String getSQLDatabase() {
141 | String dbName = DataSourceHolder.getDBName();
142 | if (dbName == null) {
143 | dbName = "DEFAULT";
144 | }
145 | String url = CatMybatisPlugin.sqlURLCache.get(dbName);
146 | if (url != null) {
147 | return url;
148 | }
149 |
150 | url = this.getSqlURL();
151 | if (url == null) {
152 | url = String.format(EMPTY_CONNECTION, dbName);
153 | }
154 | CatMybatisPlugin.sqlURLCache.put(dbName, url);
155 | return url;
156 | }
157 |
158 |
159 | @Override
160 | public Object plugin(Object target) {
161 | if (target instanceof Executor) {
162 | this.target = (Executor) target;
163 | return Plugin.wrap(target, this);
164 | }
165 | return target;
166 | }
167 |
168 | @Override
169 | public void setProperties(Properties properties) {
170 | }
171 |
172 | }
173 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/util/cache/RedisClient.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.util.cache;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 | import redis.clients.jedis.Jedis;
6 | import redis.clients.jedis.ShardedJedis;
7 | import redis.clients.jedis.ShardedJedisPool;
8 |
9 | /**
10 | * redis工具类
11 | * @author potato
12 | * @date 2016-6-16
13 | */
14 | public class RedisClient {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(RedisClient.class);
17 |
18 | private ShardedJedisPool shardedJedisPool;
19 | private int redisTimeout; //redis缓存默认过时时间(秒)
20 |
21 |
22 | public boolean set(final String key, final String value) {
23 | return this.execute(new JedisCallback() {
24 | @Override
25 | public Boolean doInJedis(Jedis jedis) {
26 | String s = jedis.set(key, value);
27 |
28 | return "OK".equals(s);
29 | }
30 |
31 | @Override
32 | public String redisMethodName() {
33 | return "set";
34 | }
35 | }, key);
36 | }
37 |
38 | /**
39 | * 支持value为byte[]
40 | * @date 2016-8-15
41 | */
42 | public boolean setByte(final String key, final byte[] value){
43 |
44 | return this.execute(new JedisCallback() {
45 | @Override
46 | public Boolean doInJedis(Jedis jedis) {
47 | String s = jedis.set(key.getBytes(), value);
48 |
49 | return "OK".equals(s);
50 | }
51 |
52 | @Override
53 | public String redisMethodName() {
54 | return "set";
55 | }
56 | }, key);
57 |
58 | }
59 |
60 |
61 | /**
62 | * 使用默认超时时间
63 | * @param key
64 | * @param value
65 | * @return
66 | */
67 | public boolean setex(final String key, final String value) {
68 | return this.setex(key, value, this.redisTimeout);
69 | }
70 |
71 | public boolean setex(final String key, final byte[] value) {
72 | return this.setexByte(key, value, this.redisTimeout);
73 | }
74 |
75 | /**
76 | *
77 | * @param key
78 | * @param value
79 | * @param timeout 超时时间(秒)
80 | * @return
81 | */
82 | public boolean setex(final String key, final String value, final int timeout) {
83 | return this.execute(new JedisCallback() {
84 | @Override
85 | public Boolean doInJedis(Jedis jedis) {
86 | String s = jedis.setex(key, timeout, value);
87 | return "OK".equals(s);
88 | }
89 |
90 | @Override
91 | public String redisMethodName() {
92 | return "setex";
93 | }
94 | }, key);
95 | }
96 |
97 | /**
98 | * 支持byte[]
99 | * @param key
100 | * @param value
101 | * @param timeout
102 | * @return
103 | */
104 | public boolean setexByte(final String key, final byte[] value, final int timeout) {
105 | return this.execute(new JedisCallback() {
106 | @Override
107 | public Boolean doInJedis(Jedis jedis) {
108 | String s = jedis.setex(key.getBytes(), timeout, value);
109 | return "OK".equals(s);
110 | }
111 |
112 | @Override
113 | public String redisMethodName() {
114 | return "setex";
115 | }
116 | }, key);
117 | }
118 |
119 | public String get(final String key) {
120 | return this.execute(new JedisCallback() {
121 | @Override
122 | public String doInJedis(Jedis jedis) {
123 | String value = jedis.get(key);
124 | return value;
125 | }
126 |
127 | @Override
128 | public String redisMethodName() {
129 | return "get";
130 | }
131 | }, key);
132 | }
133 |
134 | /**
135 | * 支持key为byte[]
136 | * @param key
137 | * @return
138 | */
139 | public byte[] getByte(final String key) {
140 | return this.execute(new JedisCallback() {
141 | @Override
142 | public byte[] doInJedis(Jedis jedis) {
143 | byte[] value = jedis.get(key.getBytes());
144 | return value;
145 | }
146 |
147 | @Override
148 | public String redisMethodName() {
149 | return "get";
150 | }
151 | }, key);
152 | }
153 |
154 | public Long delete(final String key) {
155 | return this.execute(new JedisCallback() {
156 | @Override
157 | public Long doInJedis(Jedis jedis) {
158 | return jedis.del(key);
159 | }
160 |
161 | @Override
162 | public String redisMethodName() {
163 | return "delete";
164 | }
165 | }, key);
166 | }
167 |
168 | public T execute(SharedRedisCallback redisCallback) {
169 | ShardedJedis jedis = null;
170 | try {
171 | jedis = this.getShardedJedisPool().getResource();
172 | return redisCallback.doInRedis(jedis);
173 | } finally {
174 | if (jedis != null) {
175 | try {
176 | jedis.close();
177 | } catch (Exception e) {
178 | log.error("redis close exception", e);
179 | }
180 | }
181 | }
182 | }
183 |
184 | public T execute(JedisCallback jedisCallback, String key) {
185 | ShardedJedis sharededJedis = null;
186 | try {
187 | sharededJedis = this.getShardedJedisPool().getResource();
188 | Jedis j = sharededJedis.getShard(key);
189 | return jedisCallback.doInJedis(j);
190 | } finally {
191 | if (sharededJedis != null) {
192 | try {
193 | sharededJedis.close();
194 | } catch (Exception e) {
195 | log.error("redis close exception", e);
196 | }
197 | }
198 | }
199 | }
200 |
201 | public ShardedJedisPool getShardedJedisPool() {
202 | return shardedJedisPool;
203 | }
204 |
205 | public void setShardedJedisPool(ShardedJedisPool shardedJedisPool) {
206 | this.shardedJedisPool = shardedJedisPool;
207 | }
208 |
209 | public int getRedisTimeout() {
210 | return redisTimeout;
211 | }
212 |
213 | public void setRedisTimeout(int redisTimeout) {
214 | this.redisTimeout = redisTimeout;
215 | }
216 |
217 | public static interface SharedRedisCallback {
218 |
219 | public T doInRedis(ShardedJedis jedis);
220 | }
221 |
222 | /**
223 | * 使用于只对一个key进行操作的情况
224 | * @param
225 | */
226 | public static interface JedisCallback {
227 |
228 | public T doInJedis(Jedis jedis);
229 |
230 | /**
231 | * 返回要执行的redis方法名,如setex, get等
232 | */
233 | public String redisMethodName();
234 |
235 | }
236 |
237 | }
238 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/util/http/HttpClientProxy.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.util.http;
2 |
3 | import java.io.IOException;
4 | import java.util.concurrent.TimeUnit;
5 |
6 | import org.apache.http.Consts;
7 | import org.apache.http.HttpEntity;
8 | import org.apache.http.annotation.ThreadSafe;
9 | import org.apache.http.client.config.RequestConfig;
10 | import org.apache.http.client.methods.HttpGet;
11 | import org.apache.http.client.methods.HttpPost;
12 | import org.apache.http.client.methods.HttpRequestBase;
13 | import org.apache.http.config.SocketConfig;
14 | import org.apache.http.entity.ContentType;
15 | import org.apache.http.entity.StringEntity;
16 | import org.apache.http.impl.client.BasicResponseHandler;
17 | import org.apache.http.impl.client.CloseableHttpClient;
18 | import org.apache.http.impl.client.HttpClientBuilder;
19 | import org.apache.http.impl.client.HttpClients;
20 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
21 | import org.apache.http.util.EntityUtils;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 | import org.springframework.beans.factory.InitializingBean;
25 |
26 | /**
27 | * Http Client的包装类,基于4.4实现
28 | * 应根据具体应用个性化maxPerRoute, maxTotal, timeToLive参数
29 | *
30 | * @author potato
31 | */
32 | @ThreadSafe
33 | public class HttpClientProxy implements InitializingBean {
34 |
35 | private Logger logger = LoggerFactory.getLogger(HttpClientProxy.class);
36 |
37 | private static final int DEFAULT_MAX_PER_ROUTE = 15;
38 | private static final int DEFAULT_MAX_TOTAL = 100;
39 | private static final int DEFAULT_TIME_TO_LIVE = 3000; //毫秒
40 |
41 | private CloseableHttpClient httpClient;
42 |
43 | private Integer maxPerRoute;
44 |
45 | private Integer maxTotal;
46 |
47 | private Integer timeToLive;
48 |
49 | private Integer defaultSocketTimeout = 1000;
50 |
51 | private Integer defaultConnectTimeout = 1000;
52 |
53 | public String get(String url) throws IOException {
54 | return this.get(url, -1, -1);
55 | }
56 |
57 | public String get(String url, int socketTimeout, int connectTimeout) throws IOException {
58 | HttpGet httpGet = new HttpGet(url);
59 | return this.execute(httpGet, socketTimeout, connectTimeout);
60 | }
61 |
62 | public String postJson(String url, String json) throws IOException {
63 | return this.postJson(url, json, -1, -1);
64 | }
65 |
66 | public String postJson(String url, String json, int socketTimeout, int connectTimeout) throws IOException {
67 | StringEntity entity = new StringEntity(json, Consts.UTF_8);
68 | entity.setContentEncoding(ContentType.APPLICATION_JSON.getCharset().name());
69 | entity.setContentType(ContentType.APPLICATION_JSON.getMimeType());
70 | return this.post(url, entity, socketTimeout, connectTimeout);
71 | }
72 |
73 | public String post(String url, HttpEntity entity) throws IOException {
74 | return this.post(url, entity, -1, -1);
75 | }
76 |
77 | public String post(String url, HttpEntity entity, int socketTimeout, int connectTimeout) throws IOException {
78 | HttpPost method = new HttpPost(url);
79 | method.setEntity(entity);
80 | return this.execute(method, socketTimeout, connectTimeout);
81 | }
82 |
83 | public String execute(HttpRequestBase request) throws IOException {
84 | return this.execute(request, -1, -1);
85 | }
86 |
87 | /**
88 | * 发起Http请求
89 | * 较复杂的请求如设置HttpHeader等,可调用本方法执行
90 | * @param request
91 | * @param socketTimeout
92 | * @param connectTimeout
93 | * @return
94 | * @throws IOException
95 | */
96 | public String execute(HttpRequestBase request,int socketTimeout, int connectTimeout) throws IOException {
97 | if (socketTimeout <= 0) {
98 | socketTimeout = this.defaultSocketTimeout;
99 | }
100 | if (connectTimeout <= 0) {
101 | connectTimeout = this.defaultConnectTimeout;
102 | }
103 |
104 | RequestConfig requestConfig = RequestConfig.custom()
105 | .setSocketTimeout(socketTimeout)
106 | .setConnectTimeout(connectTimeout)
107 | .build();
108 |
109 | request.setConfig(requestConfig);
110 | return httpClient.execute(request, new StringResponseHandler());
111 | }
112 |
113 | @Override
114 | public void afterPropertiesSet() throws Exception {
115 | if (this.httpClient != null) {
116 | return;
117 | }
118 |
119 | int timeToLive;
120 | if (this.timeToLive != null) {
121 | timeToLive = this.timeToLive.intValue();
122 | } else {
123 | timeToLive = DEFAULT_TIME_TO_LIVE;
124 | }
125 | PoolingHttpClientConnectionManager connectionManager =
126 | new PoolingHttpClientConnectionManager(timeToLive, TimeUnit.MILLISECONDS);
127 |
128 | SocketConfig socketConfig = SocketConfig.custom().setTcpNoDelay(true).build();
129 | connectionManager.setDefaultSocketConfig(socketConfig);
130 |
131 | connectionManager.setValidateAfterInactivity(1000);
132 |
133 | if (this.maxPerRoute != null) {
134 | connectionManager.setDefaultMaxPerRoute(this.maxPerRoute);
135 | } else {
136 | connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
137 | }
138 | if (this.maxTotal != null) {
139 | connectionManager.setMaxTotal(this.maxTotal);
140 | } else {
141 | connectionManager.setMaxTotal(DEFAULT_MAX_TOTAL);
142 | }
143 |
144 | HttpClientBuilder clientBuilder = HttpClients.custom();
145 | clientBuilder.setConnectionManager(connectionManager);
146 | this.httpClient = clientBuilder.build();
147 | }
148 |
149 | public void setHttpClient(CloseableHttpClient httpClient) {
150 | this.httpClient = httpClient;
151 | }
152 |
153 | public CloseableHttpClient getHttpClient() {
154 | return this.httpClient;
155 | }
156 |
157 | public Integer getMaxPerRoute() {
158 | return maxPerRoute;
159 | }
160 |
161 | public void setMaxPerRoute(Integer maxPerRoute) {
162 | this.maxPerRoute = maxPerRoute;
163 | }
164 |
165 | public Integer getMaxTotal() {
166 | return maxTotal;
167 | }
168 |
169 | public void setMaxTotal(Integer maxTotal) {
170 | this.maxTotal = maxTotal;
171 | }
172 |
173 | public Integer getTimeToLive() {
174 | return timeToLive;
175 | }
176 |
177 | public void setTimeToLive(Integer timeToLive) {
178 | this.timeToLive = timeToLive;
179 | }
180 |
181 | public Integer getSocketTimeout() {
182 | return defaultSocketTimeout;
183 | }
184 |
185 | public void setSocketTimeout(Integer socketTimeout) {
186 | this.defaultSocketTimeout = socketTimeout;
187 | }
188 |
189 | public Integer getConnectTimeout() {
190 | return defaultConnectTimeout;
191 | }
192 |
193 | public void setConnectTimeout(Integer connectTimeout) {
194 | this.defaultConnectTimeout = connectTimeout;
195 | }
196 |
197 | /**
198 | * 将Http响应解析为字符串
199 | * 默认编码格式设置为UTF-8
200 | */
201 | public static class StringResponseHandler extends BasicResponseHandler {
202 | @Override
203 | public String handleEntity(final HttpEntity entity) throws IOException {
204 | return EntityUtils.toString(entity, "UTF-8");
205 | }
206 | }
207 |
208 | }
209 |
--------------------------------------------------------------------------------
/src/main/java/net/tomjerry/catmonitor/dubbospi/DubboCatCrossFilter.java:
--------------------------------------------------------------------------------
1 | package net.tomjerry.catmonitor.dubbospi;
2 |
3 | import java.util.Map;
4 |
5 | import net.tomjerry.catmonitor.common.CatConstants;
6 | import net.tomjerry.catmonitor.common.CatContext;
7 |
8 | import com.alibaba.dubbo.common.Constants;
9 | import com.alibaba.dubbo.common.URL;
10 | import com.alibaba.dubbo.common.extension.Activate;
11 | import com.alibaba.dubbo.common.utils.StringUtils;
12 | import com.alibaba.dubbo.remoting.RemotingException;
13 | import com.alibaba.dubbo.remoting.TimeoutException;
14 | import com.alibaba.dubbo.rpc.Filter;
15 | import com.alibaba.dubbo.rpc.Invocation;
16 | import com.alibaba.dubbo.rpc.Invoker;
17 | import com.alibaba.dubbo.rpc.Result;
18 | import com.alibaba.dubbo.rpc.RpcContext;
19 | import com.alibaba.dubbo.rpc.RpcException;
20 | import com.dianping.cat.Cat;
21 | import com.dianping.cat.message.Event;
22 | import com.dianping.cat.message.Transaction;
23 | import com.dianping.cat.message.internal.AbstractMessage;
24 | import com.dianping.cat.message.internal.NullMessage;
25 |
26 | /**
27 | * 消息树串联:dubbo-rpc服务调用
28 | * @author potato
29 | *
30 | */
31 | @Activate(group = {Constants.PROVIDER, Constants.CONSUMER}, order = -9000)
32 | public class DubboCatCrossFilter implements Filter {
33 |
34 | private static final ThreadLocal CAT_CONTEXT_LOCAL = new ThreadLocal();
35 |
36 | @Override
37 | public Result invoke(Invoker> invoker, Invocation invocation) throws RpcException {
38 |
39 | URL url = invoker.getUrl();
40 | String sideKey = url.getParameter(Constants.SIDE_KEY);
41 | String loggerName = invoker.getInterface().getSimpleName() + "." + invocation.getMethodName();
42 | String type = CatConstants.CROSS_CONSUMER;
43 | if(Constants.PROVIDER_SIDE.equals(sideKey)){
44 | type = CatConstants.CROSS_SERVER;
45 | }
46 | Transaction t = Cat.newTransaction(type, loggerName);
47 | Result result = null;
48 | try{
49 | Cat.Context context = this.getCatContext();
50 | if(Constants.CONSUMER_SIDE.equals(sideKey)){
51 | this.createConsumerCross(url, t);
52 | Cat.logRemoteCallClient(context);
53 | }else{
54 | this.createProviderCross(url, t);
55 | Cat.logRemoteCallServer(context);
56 | }
57 | this.setAttachment(context);
58 | result = invoker.invoke(invocation);
59 |
60 | if(result.hasException()){
61 | //给调用接口出现异常进行打点
62 | Throwable throwable = result.getException();
63 | Event event = null;
64 | if(RpcException.class == throwable.getClass()){
65 | Throwable caseBy = throwable.getCause();
66 | if(caseBy != null && caseBy.getClass() == TimeoutException.class){
67 | event = Cat.newEvent("DUBBO_TIMEOUT_ERROR", loggerName);
68 | }else{
69 | event = Cat.newEvent("DUBBO_REMOTING_ERROR", loggerName);
70 | }
71 | }else if(RemotingException.class.isAssignableFrom(throwable.getClass())){
72 | event = Cat.newEvent("DUBBO_REMOTING_ERROR", loggerName);
73 | }else{
74 | event = Cat.newEvent("DUBBO_BIZ_ERROR", loggerName);
75 | }
76 | event.setStatus(result.getException());
77 | this.completeEvent(event);
78 | t.addChild(event);
79 | t.setStatus(result.getException().getClass().getSimpleName());
80 | }else{
81 | t.setStatus(Transaction.SUCCESS);
82 | }
83 | return result;
84 | }catch (RuntimeException e){
85 | Event event = null;
86 | if(RpcException.class == e.getClass()){
87 | Throwable caseBy = e.getCause();
88 | if(caseBy != null && caseBy.getClass() == TimeoutException.class){
89 | event = Cat.newEvent("DUBBO_TIMEOUT_ERROR", loggerName);
90 | }else{
91 | event = Cat.newEvent("DUBBO_REMOTING_ERROR", loggerName);
92 | }
93 | }else{
94 | event = Cat.newEvent("DUBBO_BIZ_ERROR", loggerName);
95 | }
96 | event.setStatus(e);
97 | this.completeEvent(event);
98 | t.addChild(event);
99 | t.setStatus(e.getClass().getSimpleName());
100 | if(result == null){
101 | throw e;
102 | }else{
103 | return result;
104 | }
105 | } finally {
106 | t.complete();
107 | CAT_CONTEXT_LOCAL.remove();
108 | }
109 | }
110 |
111 |
112 | private Cat.Context getCatContext(){
113 | Cat.Context context = CAT_CONTEXT_LOCAL.get();
114 | if(context == null){
115 | context = initCatContext();
116 | CAT_CONTEXT_LOCAL.set(context);
117 | }
118 | return context;
119 | }
120 |
121 | private Cat.Context initCatContext(){
122 | Cat.Context context = new CatContext();
123 | Map attachments = RpcContext.getContext().getAttachments();
124 | if(attachments != null && attachments.size() > 0){
125 | for(Map.Entry entry : attachments.entrySet()){
126 | if(Cat.Context.CHILD.equals(entry.getKey()) || Cat.Context.ROOT.equals(entry.getKey()) || Cat.Context.PARENT.equals(entry.getKey())){
127 | context.addProperty(entry.getKey(), entry.getValue());
128 | }
129 | }
130 | }
131 | return context;
132 | }
133 |
134 | private void setAttachment(Cat.Context context){
135 | RpcContext.getContext().setAttachment(Cat.Context.ROOT, context.getProperty(Cat.Context.ROOT));
136 | RpcContext.getContext().setAttachment(Cat.Context.CHILD, context.getProperty(Cat.Context.CHILD));
137 | RpcContext.getContext().setAttachment(Cat.Context.PARENT, context.getProperty(Cat.Context.PARENT));
138 | }
139 |
140 | private void createConsumerCross(URL url, Transaction t){
141 | Event crossAppEvent = Cat.newEvent(CatConstants.CONSUMER_CALL_APP, this.getProviderAppName(url));
142 | Event crossServerEvent = Cat.newEvent(CatConstants.CONSUMER_CALL_SERVER, url.getHost());
143 | Event crossPortEvent = Cat.newEvent(CatConstants.CONSUMER_CALL_PORT, url.getPort()+"");
144 | crossAppEvent.setStatus(Event.SUCCESS);
145 | crossServerEvent.setStatus(Event.SUCCESS);
146 | crossPortEvent.setStatus(Event.SUCCESS);
147 | completeEvent(crossAppEvent);
148 | completeEvent(crossPortEvent);
149 | completeEvent(crossServerEvent);
150 | t.addChild(crossAppEvent);
151 | t.addChild(crossPortEvent);
152 | t.addChild(crossServerEvent);
153 | }
154 |
155 | private void createProviderCross(URL url, Transaction t){
156 | String consumerAppName = RpcContext.getContext().getAttachment(Constants.APPLICATION_KEY);
157 | if(StringUtils.isEmpty(consumerAppName)){
158 | consumerAppName = RpcContext.getContext().getRemoteHost() + ":" + RpcContext.getContext().getRemotePort();
159 | }
160 | Event crossAppEvent = Cat.newEvent(CatConstants.PROVIDER_SERVICE_APP, consumerAppName);
161 | Event crossServerEvent = Cat.newEvent(CatConstants.PROVIDER_SERVICE_CLIENT, url.getHost());
162 | crossAppEvent.setStatus(Event.SUCCESS);
163 | crossServerEvent.setStatus(Event.SUCCESS);
164 | completeEvent(crossAppEvent);
165 | completeEvent(crossServerEvent);
166 | t.addChild(crossAppEvent);
167 | t.addChild(crossServerEvent);
168 | }
169 |
170 | private String getProviderAppName(URL url){
171 | String appName = url.getParameter(CatConstants.DUBBO_PROVIDER_APPLICATION_NAME);
172 | if(StringUtils.isEmpty(appName)){
173 | String interfaceName = url.getParameter(Constants.INTERFACE_KEY);
174 | appName = interfaceName.substring(0,interfaceName.lastIndexOf('.'));
175 | }
176 | return appName;
177 | }
178 |
179 | private void completeEvent(Event event){
180 | if (event != NullMessage.EVENT) {
181 | AbstractMessage message = (AbstractMessage) event;
182 | message.setCompleted(true);
183 | }
184 | }
185 |
186 | }
187 |
--------------------------------------------------------------------------------