diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DriverInstrumentation.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DriverInstrumentation.java index 17ac8d7629a..c5c266ed312 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DriverInstrumentation.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/DriverInstrumentation.java @@ -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, @@ -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(); diff --git a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java index 73fa19fe8da..b81a7170e2f 100644 --- a/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java +++ b/dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java @@ -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; @@ -61,6 +62,10 @@ public class JDBCDecorator extends DatabaseClientDecorator { Config.get().isDbmTracePreparedStatements(); public static final boolean DBM_ALWAYS_APPEND_SQL_COMMENT = Config.get().isDbmAlwaysAppendSqlComment(); + public static final boolean FETCH_DB_METADATA_ON_CONNECT = + Config.get().isDbMetadataFetchingOnConnectEnabled(); + private static final boolean FETCH_DB_METADATA_ON_QUERY = + Config.get().isDbMetadataFetchingOnQueryEnabled(); private volatile boolean warnedAboutDBMPropagationMode = false; // to log a warning only once @@ -183,7 +188,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 @@ -202,7 +207,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; } @@ -211,16 +216,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; diff --git a/dd-java-agent/instrumentation/jdbc/src/test/groovy/DriverInstrumentationMetadataFetchingTest.groovy b/dd-java-agent/instrumentation/jdbc/src/test/groovy/DriverInstrumentationMetadataFetchingTest.groovy new file mode 100644 index 00000000000..43abf38721a --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/src/test/groovy/DriverInstrumentationMetadataFetchingTest.groovy @@ -0,0 +1,271 @@ +import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace +import static datadog.trace.api.config.TraceInstrumentationConfig.DB_METADATA_FETCHING_ON_CONNECT + +import datadog.trace.agent.test.InstrumentationSpecification +import datadog.trace.api.DDSpanTypes +import datadog.trace.bootstrap.instrumentation.api.Tags +import java.sql.Connection +import java.sql.DatabaseMetaData +import java.sql.SQLException +import java.sql.Statement +import test.TestConnection +import test.TestDatabaseMetaData +import test.TestDriver + +abstract class DriverInstrumentationMetadataFetchingTestBase extends InstrumentationSpecification { + + def "test dbInfo extraction from metadata or URL with username"() { + setup: + def originalUrl = "jdbc:postgresql://original-host:1234/originaldb" + def metadataUrl = "jdbc:postgresql://metadata-host:5678/metadatadb" + + def metadata = new TestDatabaseMetaData() { + @Override + String getURL() throws SQLException { + return metadataUrl + } + + @Override + String getUserName() throws SQLException { + return "metadata-user" + } + } + + def testConnection = new TestConnection(false) + testConnection.setMetaData(metadata) + + def driver = new TestDriver() { + @Override + Connection connect(String url, Properties info) { + return testConnection + } + } + + def props = new Properties() + props.put("user", "original-user") + + // Expected values depend on whether metadata fetching is enabled + def expectedDbInstance = shouldFetchMetadataOnConnect() ? "metadatadb" : "originaldb" + def expectedDbUser = shouldFetchMetadataOnConnect() ? "metadata-user" : "original-user" + + when: + def connection = driver.connect(originalUrl, props) + Statement statement = connection.createStatement() + runUnderTrace("parent") { + statement.execute("SELECT 1") + } + + then: + assertTraces(1) { + trace(2) { + span(0) { + operationName "parent" + } + span(1) { + operationName "postgresql.query" + spanType DDSpanTypes.SQL + childOf span(0) + tags(false) { + "$Tags.DB_INSTANCE" expectedDbInstance + "$Tags.DB_USER" expectedDbUser + } + } + } + } + + cleanup: + statement?.close() + connection?.close() + } + + def "test driver connect with null metadata URL"() { + setup: + def originalUrl = "jdbc:postgresql://original-host:5432/originaldb" + + def metadata = new TestDatabaseMetaData() { + @Override + String getURL() throws SQLException { + return null + } + } + + def testConnection = new TestConnection(false) + testConnection.setMetaData(metadata) + + def driver = new TestDriver() { + @Override + Connection connect(String url, Properties info) { + return testConnection + } + } + + def props = new Properties() + + when: + def connection = driver.connect(originalUrl, props) + Statement statement = connection.createStatement() + runUnderTrace("parent") { + statement.execute("SELECT 1") + } + + then: + assertTraces(1) { + trace(2) { + span(0) { + operationName "parent" + } + span(1) { + operationName "postgresql.query" + spanType DDSpanTypes.SQL + childOf span(0) + tags(false) { + // Should fallback to original URL regardless of flag when metadata URL is null + "$Tags.DB_INSTANCE" "originaldb" + } + } + } + } + + cleanup: + statement?.close() + connection?.close() + } + + def "test driver connect with metadata exception"() { + setup: + def originalUrl = "jdbc:postgresql://original-host:5432/originaldb" + + def testConnection = new TestConnection(false) { + @Override + DatabaseMetaData getMetaData() throws SQLException { + throw new SQLException("Test exception") + } + } + + def driver = new TestDriver() { + @Override + Connection connect(String url, Properties info) { + return testConnection + } + } + + def props = new Properties() + + when: + def connection = driver.connect(originalUrl, props) + Statement statement = connection.createStatement() + runUnderTrace("parent") { + statement.execute("SELECT 1") + } + + then: + assertTraces(1) { + trace(2) { + span(0) { + operationName "parent" + } + span(1) { + operationName "postgresql.query" + spanType DDSpanTypes.SQL + childOf span(0) + tags(false) { + // Should fallback to original URL when exception occurs + "$Tags.DB_INSTANCE" "originaldb" + } + } + } + } + + cleanup: + statement?.close() + connection?.close() + } + + def "test driver connect with Oracle sharding driver"() { + setup: + def originalUrl = "jdbc:oracle:thin:@original-host:1521:orcl" + def metadataUrl = "jdbc:oracle:thin:@metadata-host:1521:orcl" + + def metadata = new TestDatabaseMetaData() + metadata.setURL(metadataUrl) + + def testConnection = new TestConnection(false) + testConnection.setMetaData(metadata) + + def driver = new TestDriver() { + @Override + Connection connect(String url, Properties info) { + return testConnection + } + } + + def props = new Properties() + props.setProperty("oracle.jdbc.useShardingDriverConnection", "true") + + when: + def connection = driver.connect(originalUrl, props) + Statement statement = connection.createStatement() + runUnderTrace("parent") { + statement.execute("SELECT 1") + } + + then: + assertTraces(1) { + trace(2) { + span(0) { + operationName "parent" + } + span(1) { + operationName "oracle.query" + spanType DDSpanTypes.SQL + childOf span(0) + tags(false) { + // Should use original URL for Oracle sharding driver regardless of flag + "$Tags.DB_INSTANCE" "orcl" + } + } + } + } + + cleanup: + statement?.close() + connection?.close() + } + + abstract boolean shouldFetchMetadataOnConnect() +} + +/** + * Test with metadata fetching enabled on connect (default behavior) + */ +class DriverInstrumentationWithMetadataOnConnectForkedTest extends DriverInstrumentationMetadataFetchingTestBase { + + @Override + void configurePreAgent() { + super.configurePreAgent() + injectSysConfig(DB_METADATA_FETCHING_ON_CONNECT, "true") + } + + @Override + boolean shouldFetchMetadataOnConnect() { + return true + } +} + +/** + * Test with metadata fetching disabled on connect + */ +class DriverInstrumentationWithoutMetadataOnConnectForkedTest extends DriverInstrumentationMetadataFetchingTestBase { + + @Override + void configurePreAgent() { + super.configurePreAgent() + injectSysConfig(DB_METADATA_FETCHING_ON_CONNECT, "false") + } + + @Override + boolean shouldFetchMetadataOnConnect() { + return false + } +} + diff --git a/dd-java-agent/instrumentation/jdbc/src/test/groovy/JDBCDecoratorParseDBInfoTestBase.groovy b/dd-java-agent/instrumentation/jdbc/src/test/groovy/JDBCDecoratorParseDBInfoTestBase.groovy new file mode 100644 index 00000000000..76f6b0b19e8 --- /dev/null +++ b/dd-java-agent/instrumentation/jdbc/src/test/groovy/JDBCDecoratorParseDBInfoTestBase.groovy @@ -0,0 +1,105 @@ +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()) { + assert result.type == "postgresql" + assert result.host == "testhost" + assert result.port == 5432 + assert result.db == "testdb" + } else { + assert 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 }) + getClientInfo() >> clientInfo + } + + when: + def result = JDBCDecorator.parseDBInfoFromConnection(connection) + + then: + if (shouldFetchMetadata()) { + assert result.type == "postgresql" + assert result.host == "testhost" + assert result.port == 5432 + assert result.db == "testdb" + assert result.warehouse == "my-test-warehouse" + } else { + assert 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 + } +} + + diff --git a/dd-trace-api/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java b/dd-trace-api/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java index e7bc74a4443..974c1214981 100644 --- a/dd-trace-api/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java +++ b/dd-trace-api/src/main/java/datadog/trace/api/config/TraceInstrumentationConfig.java @@ -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"; diff --git a/internal-api/src/main/java/datadog/trace/api/Config.java b/internal-api/src/main/java/datadog/trace/api/Config.java index 4455a97403a..6b33719038a 100644 --- a/internal-api/src/main/java/datadog/trace/api/Config.java +++ b/internal-api/src/main/java/datadog/trace/api/Config.java @@ -536,6 +536,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; @@ -1115,6 +1117,8 @@ public static String getHostName() { private final String dbmPropagationMode; private final boolean dbmTracePreparedStatements; private final boolean dbmAlwaysAppendSqlComment; + private final boolean dbMetadataFetchingOnQuery; + private final boolean dbMetadataFetchingOnConnect; private final boolean dynamicInstrumentationEnabled; private final String dynamicInstrumentationSnapshotUrl; @@ -1668,6 +1672,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); @@ -3296,6 +3303,14 @@ public boolean isDbClientSplitByHost() { return dbClientSplitByHost; } + public boolean isDbMetadataFetchingOnQueryEnabled() { + return dbMetadataFetchingOnQuery; + } + + public boolean isDbMetadataFetchingOnConnectEnabled() { + return dbMetadataFetchingOnConnect; + } + public Set getSplitByTags() { return splitByTags; } @@ -5765,6 +5780,10 @@ public String toString() { + dbClientSplitByInstanceTypeSuffix + ", dbClientSplitByHost=" + dbClientSplitByHost + + ", dbMetadataFetchingEnabled=" + + dbMetadataFetchingOnQuery + + ", dbMetadataFetchingOnConnect=" + + dbMetadataFetchingOnConnect + ", dbmInjectSqlBaseHash=" + dbmInjectSqlBaseHash + ", dbmPropagationMode=" diff --git a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy index 028e5f0e29b..86dcf18732e 100644 --- a/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy +++ b/internal-api/src/test/groovy/datadog/trace/api/ConfigTest.groovy @@ -1,11 +1,5 @@ package datadog.trace.api -import datadog.trace.api.env.FixedCapturedEnvironment -import datadog.trace.bootstrap.config.provider.AgentArgsInjector -import datadog.trace.bootstrap.config.provider.ConfigConverter -import datadog.trace.bootstrap.config.provider.ConfigProvider -import datadog.trace.test.util.DDSpecification -import datadog.trace.util.throwable.FatalAgentMisconfigurationError import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_CLIENT_ERROR_STATUSES import static datadog.trace.api.ConfigDefaults.DEFAULT_HTTP_SERVER_ERROR_STATUSES import static datadog.trace.api.ConfigDefaults.DEFAULT_PARTIAL_FLUSH_MIN_SPANS @@ -21,10 +15,10 @@ import static datadog.trace.api.DDTags.SERVICE import static datadog.trace.api.DDTags.SERVICE_TAG import static datadog.trace.api.TracePropagationStyle.B3MULTI import static datadog.trace.api.TracePropagationStyle.B3SINGLE +import static datadog.trace.api.TracePropagationStyle.BAGGAGE import static datadog.trace.api.TracePropagationStyle.DATADOG import static datadog.trace.api.TracePropagationStyle.HAYSTACK import static datadog.trace.api.TracePropagationStyle.TRACECONTEXT -import static datadog.trace.api.TracePropagationStyle.BAGGAGE import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_AGENTLESS_ENABLED import static datadog.trace.api.config.CiVisibilityConfig.CIVISIBILITY_ENABLED import static datadog.trace.api.config.DebuggerConfig.DYNAMIC_INSTRUMENTATION_CLASSFILE_DUMP_ENABLED @@ -50,16 +44,16 @@ import static datadog.trace.api.config.GeneralConfig.GLOBAL_TAGS import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_ENABLED import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_HOST import static datadog.trace.api.config.GeneralConfig.HEALTH_METRICS_STATSD_PORT +import static datadog.trace.api.config.GeneralConfig.INSTRUMENTATION_SOURCE import static datadog.trace.api.config.GeneralConfig.JDK_SOCKET_ENABLED import static datadog.trace.api.config.GeneralConfig.PERF_METRICS_ENABLED import static datadog.trace.api.config.GeneralConfig.SERVICE_NAME import static datadog.trace.api.config.GeneralConfig.SITE +import static datadog.trace.api.config.GeneralConfig.SSI_INJECTION_ENABLED +import static datadog.trace.api.config.GeneralConfig.SSI_INJECTION_FORCE import static datadog.trace.api.config.GeneralConfig.TAGS import static datadog.trace.api.config.GeneralConfig.TRACER_METRICS_IGNORED_RESOURCES import static datadog.trace.api.config.GeneralConfig.VERSION -import static datadog.trace.api.config.GeneralConfig.SSI_INJECTION_ENABLED -import static datadog.trace.api.config.GeneralConfig.SSI_INJECTION_FORCE -import static datadog.trace.api.config.GeneralConfig.INSTRUMENTATION_SOURCE import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_CHECK_PERIOD import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_ENABLED import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_METRICS_CONFIGS @@ -68,8 +62,8 @@ import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_HOST import static datadog.trace.api.config.JmxFetchConfig.JMX_FETCH_STATSD_PORT import static datadog.trace.api.config.JmxFetchConfig.JMX_TAGS import static datadog.trace.api.config.LlmObsConfig.LLMOBS_AGENTLESS_ENABLED -import static datadog.trace.api.config.LlmObsConfig.LLMOBS_ML_APP import static datadog.trace.api.config.LlmObsConfig.LLMOBS_ENABLED +import static datadog.trace.api.config.LlmObsConfig.LLMOBS_ML_APP import static datadog.trace.api.config.ProfilingConfig.PROFILING_AGENTLESS import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_OLD import static datadog.trace.api.config.ProfilingConfig.PROFILING_API_KEY_FILE_VERY_OLD @@ -110,10 +104,6 @@ import static datadog.trace.api.config.TracerConfig.HTTP_CLIENT_ERROR_STATUSES import static datadog.trace.api.config.TracerConfig.HTTP_SERVER_ERROR_STATUSES import static datadog.trace.api.config.TracerConfig.ID_GENERATION_STRATEGY import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_ENABLED -import static datadog.trace.api.config.TracerConfig.TRACE_EXPERIMENTAL_FEATURES_ENABLED -import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_ENABLED -import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_FLUSH_INTERVAL -import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_INITIAL_FLUSH_INTERVAL import static datadog.trace.api.config.TracerConfig.PARTIAL_FLUSH_MIN_SPANS import static datadog.trace.api.config.TracerConfig.PRIORITIZATION_TYPE import static datadog.trace.api.config.TracerConfig.PRIORITY_SAMPLING @@ -126,8 +116,12 @@ import static datadog.trace.api.config.TracerConfig.SPAN_TAGS import static datadog.trace.api.config.TracerConfig.SPLIT_BY_TAGS import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_PORT import static datadog.trace.api.config.TracerConfig.TRACE_AGENT_URL -import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST +import static datadog.trace.api.config.TracerConfig.TRACE_EXPERIMENTAL_FEATURES_ENABLED +import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_ENABLED +import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_FLUSH_INTERVAL +import static datadog.trace.api.config.TracerConfig.TRACE_LONG_RUNNING_INITIAL_FLUSH_INTERVAL import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_BEHAVIOR_EXTRACT +import static datadog.trace.api.config.TracerConfig.TRACE_PROPAGATION_EXTRACT_FIRST import static datadog.trace.api.config.TracerConfig.TRACE_RATE_LIMIT import static datadog.trace.api.config.TracerConfig.TRACE_REPORT_HOSTNAME import static datadog.trace.api.config.TracerConfig.TRACE_RESOLVER_ENABLED @@ -152,6 +146,13 @@ import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_TIMEOUT import static datadog.trace.api.config.OtlpConfig.OTLP_METRICS_TEMPORALITY_PREFERENCE import datadog.trace.config.inversion.ConfigHelper +import datadog.trace.api.env.FixedCapturedEnvironment +import datadog.trace.bootstrap.config.provider.AgentArgsInjector +import datadog.trace.bootstrap.config.provider.ConfigConverter +import datadog.trace.bootstrap.config.provider.ConfigProvider +import datadog.trace.test.util.DDSpecification +import datadog.trace.util.throwable.FatalAgentMisconfigurationError + class ConfigTest extends DDSpecification { private static final String PREFIX = "dd." private static final DD_API_KEY_ENV = "DD_API_KEY" @@ -3181,4 +3182,56 @@ class ConfigTest extends DDSpecification { configProvider.getBoolean("a", true) == true } } + + def "db metadata fetching enabled with sys = #sys env = #env"() { + setup: + if (sys != null) { + System.setProperty("dd.trace.db.metadata.fetching.on.query", sys) + } + if (env != null) { + environmentVariables.set("DD_TRACE_DB_METADATA_FETCHING_ON_QUERY", env) + } + + when: + def config = new Config() + + then: + config.isDbMetadataFetchingOnQueryEnabled() == expected + + where: + sys | env | expected + null | null | true // default is true + null | "true" | true + null | "false" | false + "true" | null | true + "false" | null | false + "true" | "false" | true // sys prop takes precedence + "false" | "true" | false // sys prop takes precedence + } + + def "db client info fetching enabled with sys = #sys env = #env"() { + setup: + if (sys != null) { + System.setProperty("dd.trace.db.metadata.fetching.on.connect", sys) + } + if (env != null) { + environmentVariables.set("DD_TRACE_DB_METADATA_FETCHING_ON_CONNECT", env) + } + + when: + def config = new Config() + + then: + config.isDbMetadataFetchingOnConnectEnabled() == expected + + where: + sys | env | expected + null | null | true // default is true + null | "true" | true + null | "false" | false + "true" | null | true + "false" | null | false + "true" | "false" | true // sys prop takes precedence + "false" | "true" | false // sys prop takes precedence + } } diff --git a/metadata/supported-configurations.json b/metadata/supported-configurations.json index 29a68a26cd8..84e775c812a 100644 --- a/metadata/supported-configurations.json +++ b/metadata/supported-configurations.json @@ -2030,6 +2030,12 @@ "DD_TRACE_CUCUMBER_5_ANALYTICS_ENABLED": ["DD_CUCUMBER_5_ANALYTICS_ENABLED"], "DD_TRACE_CUCUMBER_ANALYTICS_ENABLED": ["DD_CUCUMBER_ANALYTICS_ENABLED"], "DD_TRACE_DATANUCLEUS_ANALYTICS_ENABLED": ["DD_DATANUCLEUS_ANALYTICS_ENABLED"], + "DD_TRACE_DB_METADATA_FETCHING_ON_CONNECT": [ + "DD_TRACE_DB_METADATA_FETCHING_ON_CONNECT" + ], + "DD_TRACE_DB_METADATA_FETCHING_ON_QUERY": [ + "DD_TRACE_DB_METADATA_FETCHING_ON_QUERY" + ], "DD_TRACE_ELASTICSEARCH_ANALYTICS_ENABLED": ["DD_ELASTICSEARCH_ANALYTICS_ENABLED"], "DD_TRACE_FINATRA_ANALYTICS_ENABLED": ["DD_FINATRA_ANALYTICS_ENABLED"], "DD_TRACE_GOOGLE_HTTP_CLIENT_ANALYTICS_ENABLED": ["DD_GOOGLE_HTTP_CLIENT_ANALYTICS_ENABLED"],