Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ public void methodAdvice(MethodTransformer transformer) {
}

public static class DriverAdvice {

@Advice.OnMethodExit(suppress = Throwable.class)
public static void addDBInfo(
@Advice.Argument(0) final String url,
Expand All @@ -75,8 +76,10 @@ public static void addDBInfo(
}
String connectionUrl = url;
Properties connectionProps = props;
if (null == props
|| !Boolean.parseBoolean(props.getProperty("oracle.jdbc.useShardingDriverConnection"))) {
if (JDBCDecorator.FETCH_DB_METADATA_ON_CONNECT
&& (null == props
|| !Boolean.parseBoolean(
props.getProperty("oracle.jdbc.useShardingDriverConnection")))) {
try {
DatabaseMetaData metaData = connection.getMetaData();
connectionUrl = metaData.getURL();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand Down Expand Up @@ -59,6 +60,10 @@ public class JDBCDecorator extends DatabaseClientDecorator<DBInfo> {
DBM_PROPAGATION_MODE.equals(DBM_PROPAGATION_MODE_FULL);
public static final boolean DBM_TRACE_PREPARED_STATEMENTS =
Config.get().isDbmTracePreparedStatements();
private static final boolean FETCH_DB_METADATA_ON_QUERY =
Config.get().isDbMetadataFetchingOnQueryEnabled();
public static final boolean FETCH_DB_METADATA_ON_CONNECT =
Config.get().isDbMetadataFetchingOnConnectEnabled();

private volatile boolean warnedAboutDBMPropagationMode = false; // to log a warning only once

Expand Down Expand Up @@ -181,7 +186,7 @@ public static DBInfo parseDBInfo(
} catch (Throwable ignore) {
}
if (dbInfo == null) {
// couldn't find DBInfo anywhere, so fall back to default
// couldn't find DBInfo from a previous call anywhere, so we try to fetch it from the DB
dbInfo = parseDBInfoFromConnection(connection);
}
// store the DBInfo on the outermost connection instance to avoid future searches
Expand All @@ -200,7 +205,7 @@ public String getDbService(final DBInfo dbInfo) {
}

public static DBInfo parseDBInfoFromConnection(final Connection connection) {
if (connection == null) {
if (connection == null || !FETCH_DB_METADATA_ON_QUERY) {
// we can log here, but it risks to be too verbose
return DBInfo.DEFAULT;
}
Expand All @@ -209,16 +214,19 @@ public static DBInfo parseDBInfoFromConnection(final Connection connection) {
final DatabaseMetaData metaData = connection.getMetaData();
final String url;
if (metaData != null && (url = metaData.getURL()) != null) {
Properties clientInfo = null;
try {
dbInfo = JDBCConnectionUrlParser.extractDBInfo(url, connection.getClientInfo());
clientInfo = connection.getClientInfo();
} catch (final Throwable ex) {
// getClientInfo is likely not allowed.
dbInfo = JDBCConnectionUrlParser.extractDBInfo(url, null);
// getClientInfo is likely not allowed, we can still extract info from the url alone
log.debug("Could not get client info from DB", ex);
}
dbInfo = JDBCConnectionUrlParser.extractDBInfo(url, clientInfo);
} else {
dbInfo = DBInfo.DEFAULT;
}
} catch (final SQLException se) {
log.debug("Could not get metadata from DB", se);
dbInfo = DBInfo.DEFAULT;
}
return dbInfo;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_METADATA_FETCHING_ON_QUERY

import datadog.trace.agent.test.InstrumentationSpecification
import datadog.trace.bootstrap.instrumentation.jdbc.DBInfo
import datadog.trace.instrumentation.jdbc.JDBCDecorator
import java.sql.Connection
import test.TestDatabaseMetaData

/**
* Base test class for parseDBInfoFromConnection with different flag configurations
*/
abstract class JDBCDecoratorParseDBInfoTestBase extends InstrumentationSpecification {

def "test parseDBInfoFromConnection with null connection"() {
when:
def result = JDBCDecorator.parseDBInfoFromConnection(null)

then:
result == DBInfo.DEFAULT
}

def "test parseDBInfoFromConnection with null ClientInfo"() {
setup:
def metadata = new TestDatabaseMetaData()
metadata.setURL("jdbc:postgresql://testhost:5432/testdb")
def connection = Mock(Connection) {
getMetaData() >> metadata
getClientInfo() >> null
}

when:
def result = JDBCDecorator.parseDBInfoFromConnection(connection)

then:
if (shouldFetchMetadata()) {
result.type == "postgresql"
result.host == "testhost"
result.port == 5432
result.db == "testdb"
} else {
result == DBInfo.DEFAULT
}
}

def "test parseDBInfoFromConnection regular case"() {
setup:
def metadata = new TestDatabaseMetaData()
metadata.setURL("jdbc:postgresql://testhost:5432/testdb")
def clientInfo = new Properties()
clientInfo.setProperty("warehouse", "my-test-warehouse") // we'll check that property to know if clientInfo were used
def connection = Mock(Connection) {
getMetaData() >> (shouldFetchMetadata() ? metadata : { assert false })
}

when:
def result = JDBCDecorator.parseDBInfoFromConnection(connection)

then:
if (shouldFetchMetadata()) {
result.type == "postgresql"
result.host == "testhost"
result.port == 5432
result.db == "testdb"
result.warehouse == "my-test-warehouse"
} else {
result == DBInfo.DEFAULT
}
}

abstract boolean shouldFetchMetadata()
}

/**
* Test with both flags enabled (default behavior)
*/
class JDBCDecoratorParseDBInfoWithMetadataForkedTest extends JDBCDecoratorParseDBInfoTestBase {

@Override
void configurePreAgent() {
super.configurePreAgent()
injectSysConfig(DB_METADATA_FETCHING_ON_QUERY, "true")
}

@Override
boolean shouldFetchMetadata() {
return true
}
}

class JDBCDecoratorParseDBInfoWithoutCallsForkedTest extends JDBCDecoratorParseDBInfoTestBase {

@Override
void configurePreAgent() {
super.configurePreAgent()
injectSysConfig(DB_METADATA_FETCHING_ON_QUERY, "false")
}

@Override
boolean shouldFetchMetadata() {
return false
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ public final class TraceInstrumentationConfig {
"trace.db.client.split-by-instance.type.suffix";
public static final String DB_CLIENT_HOST_SPLIT_BY_HOST = "trace.db.client.split-by-host";

public static final String DB_METADATA_FETCHING_ON_QUERY = "trace.db.metadata.fetching.on.query";
public static final String DB_METADATA_FETCHING_ON_CONNECT =
"trace.db.metadata.fetching.on.connect";

public static final String JDBC_PREPARED_STATEMENT_CLASS_NAME =
"trace.jdbc.prepared.statement.class.name";

Expand Down
19 changes: 19 additions & 0 deletions internal-api/src/main/java/datadog/trace/api/Config.java
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,8 @@
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_INJECT_SQL_BASEHASH;
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_PROPAGATION_MODE_MODE;
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_DBM_TRACE_PREPARED_STATEMENTS;
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_METADATA_FETCHING_ON_CONNECT;
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_METADATA_FETCHING_ON_QUERY;
import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_AND_PARAMS_ENABLED;
import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_BODY_ENABLED;
import static datadog.trace.api.config.TraceInstrumentationConfig.ELASTICSEARCH_PARAMS_ENABLED;
Expand Down Expand Up @@ -1076,6 +1078,8 @@ public static String getHostName() {
private final boolean dbmInjectSqlBaseHash;
private final String dbmPropagationMode;
private final boolean dbmTracePreparedStatements;
private final boolean dbMetadataFetchingOnQuery;
private final boolean dbMetadataFetchingOnConnect;

private final boolean dynamicInstrumentationEnabled;
private final String dynamicInstrumentationSnapshotUrl;
Expand Down Expand Up @@ -1626,6 +1630,9 @@ private Config(final ConfigProvider configProvider, final InstrumenterConfig ins
DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX,
DEFAULT_DB_CLIENT_HOST_SPLIT_BY_INSTANCE_TYPE_SUFFIX);

dbMetadataFetchingOnQuery = configProvider.getBoolean(DB_METADATA_FETCHING_ON_QUERY, true);
dbMetadataFetchingOnConnect = configProvider.getBoolean(DB_METADATA_FETCHING_ON_CONNECT, true);

dbClientSplitByHost =
configProvider.getBoolean(
DB_CLIENT_HOST_SPLIT_BY_HOST, DEFAULT_DB_CLIENT_HOST_SPLIT_BY_HOST);
Expand Down Expand Up @@ -3146,6 +3153,14 @@ public boolean isDbClientSplitByHost() {
return dbClientSplitByHost;
}

public boolean isDbMetadataFetchingOnQueryEnabled() {
return dbMetadataFetchingOnQuery;
}

public boolean isDbMetadataFetchingOnConnectEnabled() {
return dbMetadataFetchingOnConnect;
}

public Set<String> getSplitByTags() {
return splitByTags;
}
Expand Down Expand Up @@ -5551,6 +5566,10 @@ public String toString() {
+ dbClientSplitByInstanceTypeSuffix
+ ", dbClientSplitByHost="
+ dbClientSplitByHost
+ ", dbMetadataFetchingEnabled="
+ dbMetadataFetchingOnQuery
+ ", dbMetadataFetchingOnConnect="
+ dbMetadataFetchingOnConnect
+ ", dbmInjectSqlBaseHash="
+ dbmInjectSqlBaseHash
+ ", dbmPropagationMode="
Expand Down
Loading