From 7bc4425353db4d9ee148d7701eeb04dcbc295efd Mon Sep 17 00:00:00 2001 From: "koo.taejin" Date: Tue, 7 Mar 2017 15:33:14 +0900 Subject: [PATCH] [#2496] Add datasource metric collection Datasource metric collection support in hikaricp. --- .../commons/dbcp/CommonsDbcpConstants.java | 2 +- .../hikaricp/DataSourceMonitorAccessor.java | 27 ++++ .../plugin/hikaricp/HikariCpConstants.java | 39 ++++++ .../hikaricp/HikariCpDataSourceMonitor.java | 124 ++++++++++++++++++ .../hikaricp/HikariCpMetadataProvider.java | 2 +- .../plugin/hikaricp/HikariCpPlugin.java | 84 +++++++++--- .../DataSourceCloseConnectionInterceptor.java | 49 +++++++ .../DataSourceCloseInterceptor.java | 40 ++++-- .../DataSourceConstructorInterceptor.java | 94 +++++++++++++ .../DataSourceGetConnectionInterceptor.java | 6 +- 10 files changed, 433 insertions(+), 34 deletions(-) create mode 100644 plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/DataSourceMonitorAccessor.java create mode 100644 plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpConstants.java create mode 100644 plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpDataSourceMonitor.java create mode 100644 plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseConnectionInterceptor.java create mode 100644 plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceConstructorInterceptor.java diff --git a/plugins/dbcp/src/main/java/com/navercorp/pinpoint/plugin/commons/dbcp/CommonsDbcpConstants.java b/plugins/dbcp/src/main/java/com/navercorp/pinpoint/plugin/commons/dbcp/CommonsDbcpConstants.java index 4bf054275..d49691ecf 100644 --- a/plugins/dbcp/src/main/java/com/navercorp/pinpoint/plugin/commons/dbcp/CommonsDbcpConstants.java +++ b/plugins/dbcp/src/main/java/com/navercorp/pinpoint/plugin/commons/dbcp/CommonsDbcpConstants.java @@ -31,7 +31,7 @@ public final class CommonsDbcpConstants { public static final String ACCESSOR_DATASOURCE_MONITOR = "com.navercorp.pinpoint.plugin.commons.dbcp.DataSourceMonitorAccessor"; public static final String INTERCEPTOR_CONSTRUCTOR = "com.navercorp.pinpoint.plugin.commons.dbcp.interceptor.DataSourceConstructorInterceptor"; - public static final String INTERCEPTOR_CLOSE = "com.navercorp.pinpoint.plugin.commons.dbcp.interceptor.DataSourceCloseInterceptor"; + public static final String INTERCEPTOR_CLOSE = "com.navercorp.pinpoint.plugin.commons.dbcp.interceptor.DataSourceCloseInterceptor"; public static final String INTERCEPTOR_GET_CONNECTION = "com.navercorp.pinpoint.plugin.commons.dbcp.interceptor.DataSourceGetConnectionInterceptor"; public static final String INTERCEPTOR_CLOSE_CONNECTION = "com.navercorp.pinpoint.plugin.commons.dbcp.interceptor.DataSourceCloseConnectionInterceptor"; diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/DataSourceMonitorAccessor.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/DataSourceMonitorAccessor.java new file mode 100644 index 000000000..e47009fef --- /dev/null +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/DataSourceMonitorAccessor.java @@ -0,0 +1,27 @@ +/* + * Copyright 2017 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.plugin.hikaricp; + +/** + * @author Taejin Koo + */ +public interface DataSourceMonitorAccessor { + + void _$PINPOINT$_setDataSourceMonitor(HikariCpDataSourceMonitor dataSourceMonitor); + HikariCpDataSourceMonitor _$PINPOINT$_getDataSourceMonitor(); + +} diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpConstants.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpConstants.java new file mode 100644 index 000000000..8d3e8ad4a --- /dev/null +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpConstants.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.plugin.hikaricp; + +import com.navercorp.pinpoint.common.trace.ServiceType; +import com.navercorp.pinpoint.common.trace.ServiceTypeFactory; + +/** + * @author Taejin Koo + */ +public final class HikariCpConstants { + + public static final String SCOPE = "HIKARICP_SCOPE"; + + public static final ServiceType SERVICE_TYPE = ServiceTypeFactory.of(6060, "HIKARICP"); + + public static final String ACCESSOR_DATASOURCE_MONITOR = "com.navercorp.pinpoint.plugin.hikaricp.DataSourceMonitorAccessor"; + + public static final String INTERCEPTOR_CONSTRUCTOR = "com.navercorp.pinpoint.plugin.hikaricp.interceptor.DataSourceConstructorInterceptor"; + public static final String INTERCEPTOR_CLOSE = "com.navercorp.pinpoint.plugin.hikaricp.interceptor.DataSourceCloseInterceptor"; + + public static final String INTERCEPTOR_GET_CONNECTION = "com.navercorp.pinpoint.plugin.hikaricp.interceptor.DataSourceGetConnectionInterceptor"; + public static final String INTERCEPTOR_CLOSE_CONNECTION = "com.navercorp.pinpoint.plugin.hikaricp.interceptor.DataSourceCloseConnectionInterceptor"; + +} diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpDataSourceMonitor.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpDataSourceMonitor.java new file mode 100644 index 000000000..0c50cdeff --- /dev/null +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpDataSourceMonitor.java @@ -0,0 +1,124 @@ +/* + * Copyright 2017 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.plugin.hikaricp; + +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.monitor.DataSourceMonitor; +import com.navercorp.pinpoint.common.trace.ServiceType; + +import java.lang.reflect.Method; + +/** + * @author Taejin Koo + */ +public class HikariCpDataSourceMonitor implements DataSourceMonitor { + + private final PLogger logger = PLoggerFactory.getLogger(getClass()); + + private final String jdbcUrl; + private final Object object; + + private final Method getActiveConnectionsMethod; + private final Method getTotalConnectionsMethod; + + + public HikariCpDataSourceMonitor(Object object, String jdbcUrl) { + this.object = object; + this.jdbcUrl = jdbcUrl; + + try { + this.getActiveConnectionsMethod = getActiveConnectionsMethod(object); + this.getTotalConnectionsMethod = getTotalConnectionsMethod(object); + } catch (Exception e) { + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + private volatile boolean closed = false; + + private Method getActiveConnectionsMethod(Object object) throws NoSuchMethodException { + Method getActiveConnectionsMethod = object.getClass().getMethod("getActiveConnections"); + if (getActiveConnectionsMethod == null) { + throw new IllegalArgumentException("object must has getActiveConnections method"); + } + + + Class returnType = getActiveConnectionsMethod.getReturnType(); + if (int.class != returnType) { + throw new IllegalArgumentException("invalid return type. expected:int, actual:" + returnType); + } + + return getActiveConnectionsMethod; + } + + private Method getTotalConnectionsMethod(Object object) throws NoSuchMethodException { + Method getTotalConnections = object.getClass().getMethod("getTotalConnections"); + if (getTotalConnections == null) { + throw new IllegalArgumentException("object must has getTotalConnections method"); + } + + Class returnType = getTotalConnections.getReturnType(); + if (int.class != returnType) { + throw new IllegalArgumentException("invalid return type. expected:int, actual:" + returnType); + } + + return getTotalConnections; + } + + @Override + public ServiceType getServiceType() { + return HikariCpConstants.SERVICE_TYPE; + } + + @Override + public String getUrl() { + return jdbcUrl; + } + + @Override + public int getActiveConnectionSize() { + try { + Object result = getActiveConnectionsMethod.invoke(object); + return (Integer) result; + } catch (Exception e) { + logger.info("failed while executing getActiveConnectionSize()"); + } + return -1; + } + + @Override + public int getMaxConnectionSize() { + try { + Object result = getTotalConnectionsMethod.invoke(object); + return (Integer) result; + } catch (Exception e) { + logger.info("failed while executing getActiveConnectionSize()"); + } + return -1; + } + + @Override + public boolean isDisabled() { + return closed; + } + + public void close() { + closed = true; + } + +} diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpMetadataProvider.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpMetadataProvider.java index 092ac5f70..fc7a3e115 100644 --- a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpMetadataProvider.java +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpMetadataProvider.java @@ -26,7 +26,7 @@ public class HikariCpMetadataProvider implements TraceMetadataProvider { @Override public void setup(TraceMetadataSetupContext context) { - context.addServiceType(HikariCpPlugin.HIKARICP_SERVICE_TYPE); + context.addServiceType(HikariCpConstants.SERVICE_TYPE); } } diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpPlugin.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpPlugin.java index 6864ba44b..17b21470e 100644 --- a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpPlugin.java +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/HikariCpPlugin.java @@ -18,6 +18,7 @@ package com.navercorp.pinpoint.plugin.hikaricp; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentClass; import com.navercorp.pinpoint.bootstrap.instrument.InstrumentException; +import com.navercorp.pinpoint.bootstrap.instrument.InstrumentMethod; import com.navercorp.pinpoint.bootstrap.instrument.Instrumentor; import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformCallback; import com.navercorp.pinpoint.bootstrap.instrument.transformer.TransformTemplate; @@ -26,8 +27,6 @@ import com.navercorp.pinpoint.bootstrap.logging.PLogger; import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPlugin; import com.navercorp.pinpoint.bootstrap.plugin.ProfilerPluginSetupContext; -import com.navercorp.pinpoint.common.trace.ServiceType; -import com.navercorp.pinpoint.common.trace.ServiceTypeFactory; import java.security.ProtectionDomain; @@ -36,8 +35,6 @@ import java.security.ProtectionDomain; */ public class HikariCpPlugin implements ProfilerPlugin, TransformTemplateAware { - public static final ServiceType HIKARICP_SERVICE_TYPE = ServiceTypeFactory.of(6060, "HIKARICP"); - public static final String HIKARICP_SCOPE = "HIKARICP_SCOPE"; private final PLogger logger = PLoggerFactory.getLogger(this.getClass()); private HikariCpConfig config; @@ -56,6 +53,20 @@ public class HikariCpPlugin implements ProfilerPlugin, TransformTemplateAware { if (config.isProfileClose()) { addPoolGuardConnectionWrapperTransformer(); } + addHikariPoolTransformer(); + } + + private void addBasicDataSourceTransformer() { + transformTemplate.transform("com.zaxxer.hikari.HikariDataSource", new TransformCallback() { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + target.addInterceptor(HikariCpConstants.INTERCEPTOR_GET_CONNECTION); + return target.toBytecode(); + } + + }); } private void addPoolGuardConnectionWrapperTransformer() { @@ -66,17 +77,12 @@ public class HikariCpPlugin implements ProfilerPlugin, TransformTemplateAware { transformTemplate.transform("com.zaxxer.hikari.proxy.ConnectionProxy", new ConnectionTransformCallback()); } - private void addBasicDataSourceTransformer() { - transformTemplate.transform("com.zaxxer.hikari.HikariDataSource", new TransformCallback() { + private void addHikariPoolTransformer() { + // 1.3.7 ~ 2.6.x (without 2.3.x) + transformTemplate.transform("com.zaxxer.hikari.pool.HikariPool", new HikariPoolTransformCallback()); - @Override - public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { - InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); - target.addInterceptor("com.navercorp.pinpoint.plugin.hikaricp.interceptor.DataSourceGetConnectionInterceptor"); - return target.toBytecode(); - } - - }); + // 2.3.x + transformTemplate.transform("com.zaxxer.hikari.pool.BaseHikariPool", new HikariPoolTransformCallback()); } @Override @@ -84,14 +90,60 @@ public class HikariCpPlugin implements ProfilerPlugin, TransformTemplateAware { this.transformTemplate = transformTemplate; } - static class ConnectionTransformCallback implements TransformCallback { + private static class ConnectionTransformCallback implements TransformCallback { @Override public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); - target.addInterceptor("com.navercorp.pinpoint.plugin.hikaricp.interceptor.DataSourceCloseInterceptor"); + target.addInterceptor(HikariCpConstants.INTERCEPTOR_CLOSE_CONNECTION); return target.toBytecode(); } } + + private static class HikariPoolTransformCallback implements TransformCallback { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader classLoader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(classLoader, className, classfileBuffer); + if (isAvailableDataSourceMonitor(target)) { + // ~ 2.4.0 + InstrumentMethod constructor = target.getConstructor("com.zaxxer.hikari.HikariConfig", "java.lang.String", "java.lang.String"); + if (constructor != null) { + addDataSourceMonitorInterceptor(target, constructor); + return target.toBytecode(); + } + + // 2.4.1 ~ + constructor = target.getConstructor("com.zaxxer.hikari.HikariConfig"); + if (constructor != null) { + addDataSourceMonitorInterceptor(target, constructor); + return target.toBytecode(); + } + } + return target.toBytecode(); + } + + private boolean isAvailableDataSourceMonitor(InstrumentClass target) { + InstrumentMethod getActiveConnectionsMethod = target.getDeclaredMethod("getActiveConnections"); + if (getActiveConnectionsMethod == null || !int.class.getName().equals(getActiveConnectionsMethod.getReturnType())) { + return false; + } + + InstrumentMethod getTotalConnectionsMethod = target.getDeclaredMethod("getTotalConnections"); + if (getTotalConnectionsMethod == null || !int.class.getName().equals(getTotalConnectionsMethod.getReturnType())) { + return false; + } + + return true; + } + + private void addDataSourceMonitorInterceptor(InstrumentClass target, InstrumentMethod constructor) throws InstrumentException { + target.addField(HikariCpConstants.ACCESSOR_DATASOURCE_MONITOR); + constructor.addInterceptor(HikariCpConstants.INTERCEPTOR_CONSTRUCTOR); + constructor.addInterceptor(HikariCpConstants.INTERCEPTOR_CLOSE); + } + + } + } diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseConnectionInterceptor.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseConnectionInterceptor.java new file mode 100644 index 000000000..706c1243a --- /dev/null +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseConnectionInterceptor.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.plugin.hikaricp.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Scope; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethod; +import com.navercorp.pinpoint.plugin.hikaricp.HikariCpConstants; + +/** + * @author Taejin Koo + */ +@Scope(HikariCpConstants.SCOPE) +@TargetMethod(name="close") +public class DataSourceCloseConnectionInterceptor extends SpanEventSimpleAroundInterceptorForPlugin { + + public DataSourceCloseConnectionInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { + super(traceContext, descriptor); + } + + @Override + public void doInBeforeTrace(SpanEventRecorder recorder, final Object target, Object[] args) { + } + + @Override + public void doInAfterTrace(SpanEventRecorder trace, Object target, Object[] args, Object result, Throwable throwable) { + trace.recordServiceType(HikariCpConstants.SERVICE_TYPE); + trace.recordApi(getMethodDescriptor()); + trace.recordException(throwable); + } + +} diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseInterceptor.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseInterceptor.java index 486fb9b25..d8a5f8962 100644 --- a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseInterceptor.java +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceCloseInterceptor.java @@ -17,33 +17,47 @@ package com.navercorp.pinpoint.plugin.hikaricp.interceptor; import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; -import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; import com.navercorp.pinpoint.bootstrap.context.TraceContext; -import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin; +import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Scope; import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethod; -import com.navercorp.pinpoint.plugin.hikaricp.HikariCpPlugin; +import com.navercorp.pinpoint.bootstrap.plugin.monitor.DataSourceMonitorRegistry; +import com.navercorp.pinpoint.plugin.hikaricp.DataSourceMonitorAccessor; +import com.navercorp.pinpoint.plugin.hikaricp.HikariCpConstants; +import com.navercorp.pinpoint.plugin.hikaricp.HikariCpDataSourceMonitor; /** * @author Taejin Koo */ -@Scope(HikariCpPlugin.HIKARICP_SCOPE) -@TargetMethod(name="close") -public class DataSourceCloseInterceptor extends SpanEventSimpleAroundInterceptorForPlugin { +@Scope(HikariCpConstants.SCOPE) +@TargetMethod(name="shutdown") +public class DataSourceCloseInterceptor implements AroundInterceptor { - public DataSourceCloseInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { - super(traceContext, descriptor); + private final TraceContext traceContext; + private final DataSourceMonitorRegistry dataSourceMonitorRegistry; + private final MethodDescriptor methodDescriptor; + + public DataSourceCloseInterceptor(TraceContext traceContext, DataSourceMonitorRegistry dataSourceMonitorRegistry, MethodDescriptor methodDescriptor) { + this.traceContext = traceContext; + this.dataSourceMonitorRegistry = dataSourceMonitorRegistry; + this.methodDescriptor = methodDescriptor; } @Override - public void doInBeforeTrace(SpanEventRecorder recorder, final Object target, Object[] args) { + public void before(Object target, Object[] args) { + if ((target instanceof DataSourceMonitorAccessor)) { + HikariCpDataSourceMonitor dataSourceMonitor = ((DataSourceMonitorAccessor) target)._$PINPOINT$_getDataSourceMonitor(); + if (dataSourceMonitor != null) { + ((DataSourceMonitorAccessor) target)._$PINPOINT$_setDataSourceMonitor(null); + dataSourceMonitor.close(); + dataSourceMonitorRegistry.unregister(dataSourceMonitor); + } + } } @Override - public void doInAfterTrace(SpanEventRecorder trace, Object target, Object[] args, Object result, Throwable throwable) { - trace.recordServiceType(HikariCpPlugin.HIKARICP_SERVICE_TYPE); - trace.recordApi(getMethodDescriptor()); - trace.recordException(throwable); + public void after(Object target, Object[] args, Object result, Throwable throwable) { + } } diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceConstructorInterceptor.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceConstructorInterceptor.java new file mode 100644 index 000000000..70a23843a --- /dev/null +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceConstructorInterceptor.java @@ -0,0 +1,94 @@ +/* + * Copyright 2017 NAVER Corp. + * + * Licensed 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 com.navercorp.pinpoint.plugin.hikaricp.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.AroundInterceptor; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Scope; +import com.navercorp.pinpoint.bootstrap.logging.PLogger; +import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory; +import com.navercorp.pinpoint.bootstrap.plugin.monitor.DataSourceMonitorRegistry; +import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils; +import com.navercorp.pinpoint.plugin.hikaricp.DataSourceMonitorAccessor; +import com.navercorp.pinpoint.plugin.hikaricp.HikariCpConstants; +import com.navercorp.pinpoint.plugin.hikaricp.HikariCpDataSourceMonitor; + +import java.lang.reflect.Method; + +/** + * @author Taejin Koo + */ +@Scope(HikariCpConstants.SCOPE) +public class DataSourceConstructorInterceptor implements AroundInterceptor { + + private final PLogger logger = PLoggerFactory.getLogger(getClass()); + + private final TraceContext traceContext; + private final DataSourceMonitorRegistry dataSourceMonitorRegistry; + private final MethodDescriptor methodDescriptor; + + public DataSourceConstructorInterceptor(TraceContext traceContext, DataSourceMonitorRegistry dataSourceMonitorRegistry, MethodDescriptor methodDescriptor) { + this.traceContext = traceContext; + this.dataSourceMonitorRegistry = dataSourceMonitorRegistry; + this.methodDescriptor = methodDescriptor; + } + + @Override + public void before(Object target, Object[] args) { + } + + @Override + public void after(Object target, Object[] args, Object result, Throwable throwable) { + if (!InterceptorUtils.isSuccess(throwable)) { + return; + } + + if (args.length >= 1) { + try { + String jdbcUrl = getJdbcUrl(args[0]); + HikariCpDataSourceMonitor dataSourceMonitor = new HikariCpDataSourceMonitor(target, jdbcUrl); + dataSourceMonitorRegistry.register(dataSourceMonitor); + + if (target instanceof DataSourceMonitorAccessor) { + ((DataSourceMonitorAccessor) target)._$PINPOINT$_setDataSourceMonitor(dataSourceMonitor); + } + } catch (Exception e) { + logger.info("failed while creating HikariCpDataSourceMonitor. message:{}", e.getMessage(), e); + } + } + } + + private String getJdbcUrl(Object object) { + try { + if (object == null) { + return null; + } + + Method getJdbcUrl = object.getClass().getMethod("getJdbcUrl"); + if (getJdbcUrl == null) { + return null; + } + + return String.valueOf(getJdbcUrl.invoke(object)); + } catch (Exception e) { + logger.info("failed while executing getJdbcUrl(). message:{}", e.getMessage(), e); + } + return null; + } + +} diff --git a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceGetConnectionInterceptor.java b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceGetConnectionInterceptor.java index e1def4585..f67f930b2 100644 --- a/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceGetConnectionInterceptor.java +++ b/plugins/hikaricp/src/main/java/com/navercorp/pinpoint/plugin/hikaricp/interceptor/DataSourceGetConnectionInterceptor.java @@ -23,12 +23,12 @@ import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterce import com.navercorp.pinpoint.bootstrap.interceptor.annotation.Scope; import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethod; import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethods; -import com.navercorp.pinpoint.plugin.hikaricp.HikariCpPlugin; +import com.navercorp.pinpoint.plugin.hikaricp.HikariCpConstants; /** * @author Taejin Koo */ -@Scope(HikariCpPlugin.HIKARICP_SCOPE) +@Scope(HikariCpConstants.SCOPE) @TargetMethods({ @TargetMethod(name="getConnection"), @TargetMethod(name="getConnection", paramTypes={"java.lang.String", "java.lang.String"}) @@ -45,7 +45,7 @@ public class DataSourceGetConnectionInterceptor extends SpanEventSimpleAroundInt @Override public void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { - recorder.recordServiceType(HikariCpPlugin.HIKARICP_SERVICE_TYPE); + recorder.recordServiceType(HikariCpConstants.SERVICE_TYPE); if (args == null) { // getConnection() without any arguments recorder.recordApi(getMethodDescriptor());