[Feature] Support collecting database connection pool metric,support dbcp2/druid/hikari (#96)
* [Feature] Support collecting database connection pool metric,support druid/hikari #8450 * [Feature] Support collecting database connection pool metric,support druid/hikari #8450 * [Feature] Support collecting database connection pool metric,support druid/hikari/dbcp2 #8450
This commit is contained in:
parent
a48a16b6d6
commit
00cf97e425
|
|
@ -8,6 +8,9 @@ Release Notes.
|
|||
* Support Tomcat thread pool metric collect.
|
||||
* Remove plugin for ServiceComb Java Chassis 0.x
|
||||
* Add Guava EventBus plugin.
|
||||
* Support Druid Connection pool metrics collecting.
|
||||
* Support HikariCP Connection pool metrics collecting.
|
||||
* Support Dbcp2 Connection pool metrics collecting.
|
||||
|
||||
#### Documentation
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,11 @@
|
|||
<version>${dbcp.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-jdbc-commons</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.dbcp.v2;
|
||||
|
||||
import org.apache.commons.dbcp2.BasicDataSourceMXBean;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* {@link PoolingJmxRegisterInterceptor} intercepted the method of DBCP jmxRegister register metric monitor.
|
||||
*/
|
||||
public class PoolingJmxRegisterInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
private static final String METER_NAME = "datasource";
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
|
||||
if (objInst.getSkyWalkingDynamicField() != null) {
|
||||
BasicDataSourceMXBean basicDataSource = (BasicDataSourceMXBean) objInst;
|
||||
String tagValue = (String) objInst.getSkyWalkingDynamicField();
|
||||
Map<String, Function<BasicDataSourceMXBean, Supplier<Double>>> metricMap = getMetrics();
|
||||
metricMap.forEach((key, value) -> MeterFactory.gauge(METER_NAME, value.apply(basicDataSource))
|
||||
.tag("name", tagValue).tag("status", key).build());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
}
|
||||
|
||||
private Map<String, Function<BasicDataSourceMXBean, Supplier<Double>>> getMetrics() {
|
||||
Map<String, Function<BasicDataSourceMXBean, Supplier<Double>>> metricMap = new HashMap();
|
||||
metricMap.put("numActive", (BasicDataSourceMXBean basicDataSource) -> () -> (double) basicDataSource.getNumActive());
|
||||
metricMap.put("maxTotal", (BasicDataSourceMXBean basicDataSource) -> () -> (double) basicDataSource.getMaxTotal());
|
||||
metricMap.put("numIdle", (BasicDataSourceMXBean basicDataSource) -> () -> (double) (basicDataSource.getNumIdle()));
|
||||
metricMap.put("maxWaitMillis", (BasicDataSourceMXBean basicDataSource) -> () -> (double) basicDataSource.getMaxWaitMillis());
|
||||
metricMap.put("maxIdle", (BasicDataSourceMXBean basicDataSource) -> () -> (double) basicDataSource.getMaxIdle());
|
||||
metricMap.put("minIdle", (BasicDataSourceMXBean basicDataSource) -> () -> (double) basicDataSource.getMinIdle());
|
||||
metricMap.put("initialSize", (BasicDataSourceMXBean basicDataSource) -> () -> (double) basicDataSource.getInitialSize());
|
||||
return metricMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.dbcp.v2;
|
||||
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser.URLParser;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* {@link PoolingSetUrlInterceptor} intercepted the method of DBCP set url Get parameters.
|
||||
*/
|
||||
public class PoolingSetUrlInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
private static final String METER_NAME = "datasource";
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
|
||||
ConnectionInfo connectionInfo = URLParser.parser((String) allArguments[0]);
|
||||
String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer();
|
||||
objInst.setSkyWalkingDynamicField(tagValue);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -31,10 +31,13 @@ import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName
|
|||
/**
|
||||
* BasicDataSource provides a "one stop shopping" solution for database connection pool solution
|
||||
* basic requirements. BasicDataSource#getConnection() creates (if necessary) and return a connection.
|
||||
* BasicDataSource#setUrl(String) set url
|
||||
*/
|
||||
public class BasicDataSourceInstrumentation extends ClassInstanceMethodsEnhancePluginDefine {
|
||||
private static final String ENHANCE_CLASS = "org.apache.commons.dbcp2.BasicDataSource";
|
||||
private static final String CONNECT_GET_INTERCEPTOR = "org.apache.skywalking.apm.plugin.dbcp.v2.PoolingGetConnectInterceptor";
|
||||
private static final String INTERCEPTOR_URL_CLASS = "org.apache.skywalking.apm.plugin.dbcp.v2.PoolingSetUrlInterceptor";
|
||||
private static final String INTERCEPTOR_CREATE_CLASS = "org.apache.skywalking.apm.plugin.dbcp.v2.PoolingJmxRegisterInterceptor";
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
|
|
@ -48,7 +51,7 @@ public class BasicDataSourceInstrumentation extends ClassInstanceMethodsEnhanceP
|
|||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[] {
|
||||
return new InstanceMethodsInterceptPoint[]{
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
|
|
@ -60,6 +63,38 @@ public class BasicDataSourceInstrumentation extends ClassInstanceMethodsEnhanceP
|
|||
return CONNECT_GET_INTERCEPTOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("setUrl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return INTERCEPTOR_URL_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("jmxRegister");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return INTERCEPTOR_CREATE_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,11 @@
|
|||
<version>${druid.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-jdbc-commons</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.druid.v1;
|
||||
|
||||
import com.alibaba.druid.pool.DruidDataSourceMBean;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.StaticMethodsAroundInterceptor;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser.URLParser;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* {@link PoolingAddDruidDataSourceInterceptor} intercepted the method of druid addDataSource and register metric monitor.
|
||||
*/
|
||||
public class PoolingAddDruidDataSourceInterceptor implements StaticMethodsAroundInterceptor {
|
||||
private static final String METER_NAME = "datasource";
|
||||
|
||||
@Override
|
||||
public void beforeMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, MethodInterceptResult result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, Object ret) {
|
||||
DruidDataSourceMBean druidDataSource = (DruidDataSourceMBean) allArguments[0];
|
||||
ConnectionInfo connectionInfo = URLParser.parser(druidDataSource.getUrl());
|
||||
String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer();
|
||||
Map<String, Function<DruidDataSourceMBean, Supplier<Double>>> metricMap = getMetrics();
|
||||
metricMap.forEach((key, value) -> MeterFactory.gauge(METER_NAME, value.apply(druidDataSource))
|
||||
.tag("name", tagValue).tag("status", key).build());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(Class clazz, Method method, Object[] allArguments, Class<?>[] parameterTypes, Throwable t) {
|
||||
|
||||
}
|
||||
|
||||
private Map<String, Function<DruidDataSourceMBean, Supplier<Double>>> getMetrics() {
|
||||
Map<String, Function<DruidDataSourceMBean, Supplier<Double>>> metricMap = new HashMap();
|
||||
metricMap.put("activeCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getActiveCount());
|
||||
metricMap.put("poolingCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getPoolingCount());
|
||||
metricMap.put("idleCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) (druidDataSource.getPoolingCount() - druidDataSource.getActiveCount()));
|
||||
metricMap.put("lockQueueLength", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getLockQueueLength());
|
||||
metricMap.put("maxWaitThreadCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getMaxWaitThreadCount());
|
||||
metricMap.put("commitCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getCommitCount());
|
||||
metricMap.put("connectCount", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getConnectCount());
|
||||
metricMap.put("connectError", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getConnectErrorCount());
|
||||
metricMap.put("createError", (DruidDataSourceMBean druidDataSource) -> () -> (double) druidDataSource.getCreateErrorCount());
|
||||
return metricMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -26,8 +26,8 @@ import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInst
|
|||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesNoArguments;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
/**
|
||||
|
|
@ -94,4 +94,5 @@ public class DruidDataSourceInstrumentation extends ClassInstanceMethodsEnhanceP
|
|||
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
|
||||
return new StaticMethodsInterceptPoint[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.druid.v1.define;
|
||||
|
||||
import net.bytebuddy.description.method.MethodDescription;
|
||||
import net.bytebuddy.matcher.ElementMatcher;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.StaticMethodsInterceptPoint;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassStaticMethodsEnhancePluginDefine;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch;
|
||||
|
||||
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||
import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName;
|
||||
|
||||
/**
|
||||
* Druid is a database connection pool from Alibaba inc.
|
||||
* <p>
|
||||
* DruidDataSource provides a "one stop" solution for database connection pool solution
|
||||
* basic requirements. DruidDataSourceStatManager.addDataSource(Object dataSource, String name)
|
||||
*/
|
||||
public class DruidDataSourceStatManagerInstrumentation extends ClassStaticMethodsEnhancePluginDefine {
|
||||
private static final String ENHANCE_CLASS = "com.alibaba.druid.stat.DruidDataSourceStatManager";
|
||||
private static final String ENHANCE_METHOD = "addDataSource";
|
||||
private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.druid.v1.PoolingAddDruidDataSourceInterceptor";
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
return byName(ENHANCE_CLASS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConstructorInterceptPoint[] getConstructorsInterceptPoints() {
|
||||
return new ConstructorInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() {
|
||||
return new InstanceMethodsInterceptPoint[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public StaticMethodsInterceptPoint[] getStaticMethodsInterceptPoints() {
|
||||
return new StaticMethodsInterceptPoint[]{
|
||||
new StaticMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named(ENHANCE_METHOD).and(takesArguments(Object.class, String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return INTERCEPTOR_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -15,4 +15,5 @@
|
|||
# limitations under the License.
|
||||
|
||||
druid-1.x=org.apache.skywalking.apm.plugin.druid.v1.define.DruidPooledConnectionInstrumentation
|
||||
druid-1.x=org.apache.skywalking.apm.plugin.druid.v1.define.DruidDataSourceInstrumentation
|
||||
druid-1.x=org.apache.skywalking.apm.plugin.druid.v1.define.DruidDataSourceInstrumentation
|
||||
druid-1.x=org.apache.skywalking.apm.plugin.druid.v1.define.DruidDataSourceStatManagerInstrumentation
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@
|
|||
<version>${hikaricp.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.skywalking</groupId>
|
||||
<artifactId>apm-jdbc-commons</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.skywalking.apm.plugin.hikaricp;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfigMXBean;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import com.zaxxer.hikari.HikariPoolMXBean;
|
||||
import org.apache.skywalking.apm.agent.core.meter.MeterFactory;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor;
|
||||
import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.connectionurl.parser.URLParser;
|
||||
import org.apache.skywalking.apm.plugin.jdbc.trace.ConnectionInfo;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* {@link PoolingSealInterceptor} intercepted the method of HikariCP getting connection.
|
||||
*/
|
||||
public class PoolingSealInterceptor implements InstanceMethodsAroundInterceptor {
|
||||
|
||||
private static final String METER_NAME = "datasource";
|
||||
|
||||
@Override
|
||||
public void beforeMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, MethodInterceptResult result) throws Throwable {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object afterMethod(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Object ret) throws Throwable {
|
||||
|
||||
HikariDataSource hikariDataSource = (HikariDataSource) objInst;
|
||||
ConnectionInfo connectionInfo = URLParser.parser(hikariDataSource.getJdbcUrl());
|
||||
String tagValue = connectionInfo.getDatabaseName() + "_" + connectionInfo.getDatabasePeer();
|
||||
final Map<String, Function<HikariPoolMXBean, Supplier<Double>>> poolMetricMap = getPoolMetrics();
|
||||
final Map<String, Function<HikariConfigMXBean, Supplier<Double>>> metricConfigMap = getConfigMetrics();
|
||||
poolMetricMap.forEach((key, value) -> MeterFactory.gauge(METER_NAME, value.apply(hikariDataSource.getHikariPoolMXBean()))
|
||||
.tag("name", tagValue).tag("status", key).build());
|
||||
metricConfigMap.forEach((key, value) -> MeterFactory.gauge(METER_NAME, value.apply(hikariDataSource))
|
||||
.tag("name", tagValue).tag("status", key).build());
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMethodException(EnhancedInstance objInst, Method method, Object[] allArguments, Class<?>[] argumentsTypes, Throwable t) {
|
||||
|
||||
}
|
||||
|
||||
private Map<String, Function<HikariPoolMXBean, Supplier<Double>>> getPoolMetrics() {
|
||||
final Map<String, Function<HikariPoolMXBean, Supplier<Double>>> poolMetricMap = new HashMap();
|
||||
poolMetricMap.put("activeConnections", (HikariPoolMXBean hikariPoolMXBean) -> () -> (double) hikariPoolMXBean.getActiveConnections());
|
||||
poolMetricMap.put("totalConnections", (HikariPoolMXBean hikariPoolMXBean) -> () -> (double) hikariPoolMXBean.getTotalConnections());
|
||||
poolMetricMap.put("idleConnections", (HikariPoolMXBean hikariPoolMXBean) -> () -> (double) hikariPoolMXBean.getIdleConnections());
|
||||
poolMetricMap.put("threadsAwaitingConnection", (HikariPoolMXBean hikariPoolMXBean) -> () -> (double) hikariPoolMXBean.getThreadsAwaitingConnection());
|
||||
return poolMetricMap;
|
||||
}
|
||||
|
||||
private Map<String, Function<HikariConfigMXBean, Supplier<Double>>> getConfigMetrics() {
|
||||
final Map<String, Function<HikariConfigMXBean, Supplier<Double>>> metricConfigMap = new HashMap();
|
||||
metricConfigMap.put("connectionTimeout", (HikariConfigMXBean hikariConfigMXBean) -> () -> (double) hikariConfigMXBean.getConnectionTimeout());
|
||||
metricConfigMap.put("validationTimeout", (HikariConfigMXBean hikariConfigMXBean) -> () -> (double) hikariConfigMXBean.getValidationTimeout());
|
||||
metricConfigMap.put("idleTimeout", (HikariConfigMXBean hikariConfigMXBean) -> () -> (double) hikariConfigMXBean.getIdleTimeout());
|
||||
metricConfigMap.put("leakDetectionThreshold", (HikariConfigMXBean hikariConfigMXBean) -> () -> (double) hikariConfigMXBean.getLeakDetectionThreshold());
|
||||
metricConfigMap.put("minimumIdle", (HikariConfigMXBean hikariConfigMXBean) -> () -> (double) hikariConfigMXBean.getMinimumIdle());
|
||||
metricConfigMap.put("maximumPoolSize", (HikariConfigMXBean hikariConfigMXBean) -> () -> (double) hikariConfigMXBean.getMaximumPoolSize());
|
||||
return metricConfigMap;
|
||||
}
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ public class HikariDataSourceInstrumentation extends ClassInstanceMethodsEnhance
|
|||
private static final String ENHANCE_CLASS = "com.zaxxer.hikari.HikariDataSource";
|
||||
private static final String ENHANCE_METHOD = "getConnection";
|
||||
private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.hikaricp.PoolingGetConnectInterceptor";
|
||||
private static final String SEAL_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.hikaricp.PoolingSealInterceptor";
|
||||
|
||||
@Override
|
||||
protected ClassMatch enhanceClass() {
|
||||
|
|
@ -82,6 +83,22 @@ public class HikariDataSourceInstrumentation extends ClassInstanceMethodsEnhance
|
|||
return INTERCEPTOR_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
new InstanceMethodsInterceptPoint() {
|
||||
@Override
|
||||
public ElementMatcher<MethodDescription> getMethodsMatcher() {
|
||||
return named("seal");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodsInterceptor() {
|
||||
return SEAL_INTERCEPTOR_CLASS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOverrideArgs() {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -15,4 +15,4 @@
|
|||
# limitations under the License.
|
||||
|
||||
hikaricp-3.x/4.x=org.apache.skywalking.apm.plugin.hikaricp.define.HikariProxyConnectionInstrumentation
|
||||
hikaricp-3.x/4.x=org.apache.skywalking.apm.plugin.hikaricp.define.HikariDataSourceInstrumentation
|
||||
hikaricp-3.x/4.x=org.apache.skywalking.apm.plugin.hikaricp.define.HikariDataSourceInstrumentation
|
||||
|
|
|
|||
|
|
@ -131,6 +131,9 @@
|
|||
<sourceDirectories>
|
||||
<sourceDirectory>${project.build.sourceDirectory}</sourceDirectory>
|
||||
<sourceDirectory>${project.build.testSourceDirectory}</sourceDirectory>
|
||||
<sourceDirectory>scenarios/dbcp-2.x-scenario</sourceDirectory>
|
||||
<sourceDirectory>scenarios/druid-1.x-scenario</sourceDirectory>
|
||||
<sourceDirectory>scenarios/druid-1.x</sourceDirectory>
|
||||
</sourceDirectories>
|
||||
<resourceIncludes>
|
||||
**/*.properties,
|
||||
|
|
|
|||
|
|
@ -221,3 +221,79 @@ segmentItems:
|
|||
tags:
|
||||
- {key: url, value: 'http://localhost:8080/dbcp-2.x-scenario/case/dbcp-2.x-scenario'}
|
||||
- {key: http.method, value: GET}
|
||||
meterItems:
|
||||
- serviceName: dbcp-2.x-scenario
|
||||
meterSize: 12
|
||||
meters:
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: numActive}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: maxTotal}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: numIdle}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: maxWaitMillis}
|
||||
singleValue: ge -1
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: maxIdle}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: minIdle}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: initialSize}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: core_pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 1
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: max_pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 1
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: active_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: queue_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
|
|
|
|||
|
|
@ -203,3 +203,91 @@ segmentItems:
|
|||
tags:
|
||||
- {key: url, value: 'http://localhost:8080/druid-1.x-scenario/case/druid-1.x-scenario'}
|
||||
- {key: http.method, value: GET}
|
||||
meterItems:
|
||||
- serviceName: druid-1.x-scenario
|
||||
meterSize: 14
|
||||
meters:
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: activeCount}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: poolingCount}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: idleCount}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: lockQueueLength}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: maxWaitThreadCount}
|
||||
singleValue: ge -1
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: commitCount}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: connectCount}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: connectError}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: createError}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: core_pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 1
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: max_pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 1
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: active_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: queue_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
|
|
|
|||
|
|
@ -203,3 +203,97 @@ segmentItems:
|
|||
tags:
|
||||
- {key: url, value: 'http://localhost:8080/hikaricp-scenario/case/hikaricp-scenario'}
|
||||
- {key: http.method, value: GET}
|
||||
meterItems:
|
||||
- serviceName: hikaricp-scenario
|
||||
meterSize: 15
|
||||
meters:
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: activeConnections}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: totalConnections}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: idleConnections}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: threadsAwaitingConnection}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: connectionTimeout}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: validationTimeout}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: idleTimeout}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: leakDetectionThreshold}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: minimumIdle}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: datasource
|
||||
tags:
|
||||
- {name: name, value: test_mysql-server:3306}
|
||||
- {name: status, value: maximumPoolSize}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: core_pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 1
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: max_pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 1
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: pool_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: active_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
- meterId:
|
||||
name: thread_pool
|
||||
tags:
|
||||
- {name: metric_type, value: queue_size}
|
||||
- {name: pool_name, value: tomcat_execute_pool}
|
||||
singleValue: ge 0
|
||||
|
|
|
|||
Loading…
Reference in New Issue