Skip to content

Commit

Permalink
[#2496] Add datasource metric collection
Browse files Browse the repository at this point in the history
1. Change JdbcUrlParser management method
2. Change the collection properties of the DataSource (poolName -> databaseName)
  • Loading branch information
koo-taejin authored and emeroad committed Feb 28, 2017
1 parent f01a711 commit 52dfcd5
Show file tree
Hide file tree
Showing 73 changed files with 1,424 additions and 387 deletions.
Expand Up @@ -24,6 +24,7 @@
* @author emeroad
*/
public interface DatabaseInfo {

List<String> getHost();

String getMultipleHost();
Expand All @@ -37,4 +38,7 @@ public interface DatabaseInfo {
ServiceType getType();

ServiceType getExecuteQueryType();

boolean isParsingComplete();

}
Expand Up @@ -17,6 +17,7 @@
package com.navercorp.pinpoint.bootstrap.context;

import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.JdbcConnectionStringParserContext;
import com.navercorp.pinpoint.common.annotations.InterfaceAudience;

/**
Expand Down Expand Up @@ -88,4 +89,6 @@ public interface TraceContext {

int getAsyncId();

JdbcConnectionStringParserContext getJdbcUrlParserContext();

}
Expand Up @@ -15,6 +15,7 @@
package com.navercorp.pinpoint.bootstrap.plugin;

import com.navercorp.pinpoint.bootstrap.config.ProfilerConfig;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.JdbcConnectionStringParser;

/**
* Provides attributes and objects to interceptors.
Expand All @@ -39,4 +40,6 @@ public interface ProfilerPluginSetupContext {
*/
void addApplicationTypeDetector(ApplicationTypeDetector... detectors);

void addJdbcConnectionStringParser(JdbcConnectionStringParser jdbcConnectionStringParser);

}
Expand Up @@ -26,15 +26,20 @@
*/
public class DefaultDatabaseInfo implements DatabaseInfo {

private ServiceType type = ServiceType.UNKNOWN_DB;
private ServiceType executeQueryType = ServiceType.UNKNOWN_DB_EXECUTE_QUERY;
private String databaseId;
private String realUrl; // URL BEFORE refinement
private String normalizedUrl;
private List<String> host;
private String multipleHost;
private final ServiceType type;
private final ServiceType executeQueryType;
private final String databaseId;
private final String realUrl; // URL BEFORE refinement
private final String normalizedUrl;
private final List<String> host;
private final String multipleHost;
private final boolean parsingComplete;

public DefaultDatabaseInfo(ServiceType type, ServiceType executeQueryType, String realUrl, String normalizedUrl, List<String> host, String databaseId) {
this(type, executeQueryType, realUrl, normalizedUrl, host, databaseId, true);
}

public DefaultDatabaseInfo(ServiceType type, ServiceType executeQueryType, String realUrl, String normalizedUrl, List<String> host, String databaseId, boolean parsingComplete) {
if (type == null) {
throw new NullPointerException("type must not be null");
}
Expand All @@ -48,6 +53,7 @@ public DefaultDatabaseInfo(ServiceType type, ServiceType executeQueryType, Strin
this.host = host;
this.multipleHost = merge(host);
this.databaseId = databaseId;
this.parsingComplete = parsingComplete;
}

private String merge(List<String> host) {
Expand Down Expand Up @@ -101,15 +107,24 @@ public ServiceType getExecuteQueryType() {
return executeQueryType;
}

@Override
public boolean isParsingComplete() {
return parsingComplete;
}

@Override
public String toString() {
return "DatabaseInfo{" +
"type=" + type +
", executeQueryType=" + executeQueryType +
", databaseId='" + databaseId + '\'' +
", realUrl='" + realUrl + '\'' +
", normalizedUrl='" + normalizedUrl + '\'' +
", host=" + host +
'}';
final StringBuilder sb = new StringBuilder("DefaultDatabaseInfo{");
sb.append("type=").append(type);
sb.append(", executeQueryType=").append(executeQueryType);
sb.append(", databaseId='").append(databaseId).append('\'');
sb.append(", realUrl='").append(realUrl).append('\'');
sb.append(", normalizedUrl='").append(normalizedUrl).append('\'');
sb.append(", host=").append(host);
sb.append(", multipleHost='").append(multipleHost).append('\'');
sb.append(", parsingComplete=").append(parsingComplete);
sb.append('}');
return sb.toString();
}

}
@@ -0,0 +1,31 @@
/*
* 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.bootstrap.plugin.jdbc;

import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;

/**
* @author Taejin Koo
*/
public interface JdbcConnectionStringParser {

DatabaseInfo parse(String url);

ServiceType getServiceType();

}
@@ -0,0 +1,29 @@
/*
* 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.bootstrap.plugin.jdbc;

import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;

/**
* @author Taejin Koo
*/
public interface JdbcConnectionStringParserContext {

DatabaseInfo parse(ServiceType serviceType, String jdbcUrl);

}
Expand Up @@ -14,17 +14,21 @@
*/
package com.navercorp.pinpoint.bootstrap.plugin.jdbc;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.bootstrap.logging.PLogger;
import com.navercorp.pinpoint.bootstrap.logging.PLoggerFactory;

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
* @author Jongho Moon
*
*/
/**
* @deprecated Since 1.6.1. Use {@link JdbcConnectionStringParser )}
*/
@Deprecated
public abstract class JdbcUrlParser {
protected final PLogger logger = PLoggerFactory.getLogger(getClass());
private final ConcurrentMap<String, DatabaseInfo> cache = new ConcurrentHashMap<String, DatabaseInfo>();
Expand Down Expand Up @@ -59,4 +63,5 @@ public DatabaseInfo parse(String url) {
}

protected abstract DatabaseInfo doParse(String url);

}
Expand Up @@ -16,12 +16,12 @@

package com.navercorp.pinpoint.bootstrap.plugin.jdbc;

import java.util.ArrayList;
import java.util.List;

import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
import com.navercorp.pinpoint.common.trace.ServiceType;

import java.util.ArrayList;
import java.util.List;

/**
* @author emeroad
*/
Expand All @@ -31,7 +31,7 @@ public class UnKnownDatabaseInfo {
static{
final List<String> urls = new ArrayList<String>();
urls.add("unknown");
INSTANCE = new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, "unknown", "unknown", urls, "unknown");
INSTANCE = new DefaultDatabaseInfo(ServiceType.UNKNOWN_DB, ServiceType.UNKNOWN_DB_EXECUTE_QUERY, "unknown", "unknown", urls, "unknown", false);
}

public static DatabaseInfo createUnknownDataBase(String url) {
Expand All @@ -41,6 +41,7 @@ public static DatabaseInfo createUnknownDataBase(String url) {
public static DatabaseInfo createUnknownDataBase(ServiceType type, ServiceType executeQueryType, String url) {
List<String> list = new ArrayList<String>();
list.add("error");
return new DefaultDatabaseInfo(type, executeQueryType, url, url, list, "error");
return new DefaultDatabaseInfo(type, executeQueryType, url, url, list, "error", false);
}

}
Expand Up @@ -33,6 +33,10 @@
*
* @author emeroad
*/
/**
* @deprecated Since 1.6.1. Use {@link DriverConnectInterceptor2 )}
*/
@Deprecated
@TargetMethod(name="connect", paramTypes={ "java.lang.String", "java.util.Properties" })
public class DriverConnectInterceptor extends SpanEventSimpleAroundInterceptorForPlugin {

Expand Down
@@ -0,0 +1,111 @@
/*
* 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.bootstrap.plugin.jdbc.interceptor;

import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo;
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.TargetMethod;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.UnKnownDatabaseInfo;
import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils;
import com.navercorp.pinpoint.common.trace.ServiceType;


/**
* must be used with ExecutionPolicy.ALWAYS
*
* @author emeroad
*/
@TargetMethod(name="connect", paramTypes={ "java.lang.String", "java.util.Properties" })
public class DriverConnectInterceptor2 extends SpanEventSimpleAroundInterceptorForPlugin {

private final ServiceType serviceType;
private final boolean recordConnection;

public DriverConnectInterceptor2(TraceContext context, MethodDescriptor descriptor, ServiceType serviceType) {
this(context, descriptor, serviceType, true);
}

public DriverConnectInterceptor2(TraceContext context, MethodDescriptor descriptor, ServiceType serviceType, boolean recordConnection) {
super(context, descriptor);

this.serviceType = serviceType;
// option for mysql loadbalance only. Destination is recorded at lower implementations.
this.recordConnection = recordConnection;
}

@Override
protected void logBeforeInterceptor(Object target, Object[] args) {
// Must not log args because it contains a password
logger.beforeInterceptor(target, null);
}

@Override
protected void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) {
}


@Override
protected void logAfterInterceptor(Object target, Object[] args, Object result, Throwable throwable) {
logger.afterInterceptor(target, null, result, throwable);
}

@Override
protected void prepareAfterTrace(Object target, Object[] args, Object result, Throwable throwable) {
final boolean success = InterceptorUtils.isSuccess(throwable);
// Must not check if current transaction is trace target or not. Connection can be made by other thread.
final String driverUrl = (String) args[0];
DatabaseInfo databaseInfo = traceContext.getJdbcUrlParserContext().parse(serviceType, driverUrl);
if (success) {
if (recordConnection) {
if (result instanceof DatabaseInfoAccessor) {
((DatabaseInfoAccessor) result)._$PINPOINT$_setDatabaseInfo(databaseInfo);
}
}
}
}

@Override
protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) {
if (recordConnection) {
DatabaseInfo databaseInfo;
if (result instanceof DatabaseInfoAccessor) {
databaseInfo = ((DatabaseInfoAccessor) result)._$PINPOINT$_getDatabaseInfo();
} else {
databaseInfo = null;
}

if (databaseInfo == null) {
databaseInfo = UnKnownDatabaseInfo.INSTANCE;
}

// Count database connect too because it's very heavy operation
recorder.recordServiceType(databaseInfo.getType());
recorder.recordEndPoint(databaseInfo.getMultipleHost());
recorder.recordDestinationId(databaseInfo.getDatabaseId());
}
final String driverUrl = (String) args[0];
// Invoking databaseInfo.getRealUrl() here is dangerous. It doesn't return real URL if it's a loadbalance connection.
recorder.recordApiCachedString(methodDescriptor, driverUrl, 0);

recorder.recordException(throwable);
}

}
Expand Up @@ -25,8 +25,6 @@ public interface DataSourceMonitor {

ServiceType getServiceType();

String getName();

String getUrl();

int getActiveConnectionSize();
Expand Down
Expand Up @@ -24,6 +24,7 @@
import com.navercorp.pinpoint.bootstrap.context.Trace;
import com.navercorp.pinpoint.bootstrap.context.TraceContext;
import com.navercorp.pinpoint.bootstrap.context.TraceId;
import com.navercorp.pinpoint.bootstrap.plugin.jdbc.JdbcConnectionStringParserContext;

/**
* @author emeroad
Expand Down Expand Up @@ -160,4 +161,10 @@ public Trace removeTraceObject() {
trace = null;
return old;
}

@Override
public JdbcConnectionStringParserContext getJdbcUrlParserContext() {
return null;
}

}

0 comments on commit 52dfcd5

Please sign in to comment.