Skip to content

Commit 9e342ef

Browse files
Add full APM/DBM mode for Oracle (#8090)
* Full APM/DBM mode for Oracle * enabled injection in tests * tests * oracle container * fixing oracle image * fixed containers * fixed first tests * more oracle tests * finished tests * fixed tests * Update dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java Co-authored-by: Raphaël Vandon <[email protected]> * DD_INSTRUMENTATION_PREFIX * compute isOracle --------- Co-authored-by: Raphaël Vandon <[email protected]>
1 parent 8d5f5ac commit 9e342ef

File tree

7 files changed

+138
-33
lines changed

7 files changed

+138
-33
lines changed

dd-java-agent/agent-bootstrap/src/main/java/datadog/trace/bootstrap/instrumentation/jdbc/DBInfo.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,6 @@ public static class Builder {
9191

9292
public Builder type(String type) {
9393
this.type = type;
94-
// Those DBs use the full text of the query including the comments as a cache key,
95-
// so we disable full propagation support for them to avoid destroying the cache.
96-
if (type.equals("oracle")) this.fullPropagationSupport = false;
9794
return this;
9895
}
9996

dd-java-agent/instrumentation/jdbc/build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ dependencies {
3737
testImplementation group: 'mysql', name: 'mysql-connector-java', version: '8.0.23'
3838
testImplementation group: 'org.postgresql', name: 'postgresql', version: '[9.4,42.2.18]'
3939
testImplementation group: 'com.microsoft.sqlserver', name: 'mssql-jdbc', version: '10.2.0.jre8'
40+
testImplementation group: 'com.oracle.database.jdbc', name: 'ojdbc8', version: '19.19.0.0'
4041

4142
testImplementation group: 'org.testcontainers', name:'mysql', version: libs.versions.testcontainers.get()
4243
testImplementation group: 'org.testcontainers', name:'postgresql', version: libs.versions.testcontainers.get()
4344
testImplementation group: 'org.testcontainers', name:'mssqlserver', version: libs.versions.testcontainers.get()
45+
testImplementation group: 'org.testcontainers', name:'oracle-xe', version: '1.20.4'
4446

4547
testRuntimeOnly project(':dd-java-agent:instrumentation:iast-instrumenter')
4648

dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/AbstractPreparedStatementInstrumentation.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ public static AgentScope onEnter(@Advice.This final Statement statement) {
9191
} else if (DECORATE.isPostgres(dbInfo) && DBM_TRACE_PREPARED_STATEMENTS) {
9292
span = startSpan(DATABASE_QUERY);
9393
DECORATE.setApplicationName(span, connection);
94+
} else if (DECORATE.isOracle(dbInfo)) {
95+
span = startSpan(DATABASE_QUERY);
96+
DECORATE.setAction(span, connection);
9497
} else {
9598
span = startSpan(DATABASE_QUERY);
9699
}

dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/JDBCDecorator.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ public class JDBCDecorator extends DatabaseClientDecorator<DBInfo> {
4949
public static final String DBM_PROPAGATION_MODE_STATIC = "service";
5050
public static final String DBM_PROPAGATION_MODE_FULL = "full";
5151

52+
public static final String DD_INSTRUMENTATION_PREFIX = "_DD_";
53+
5254
public static final String DBM_PROPAGATION_MODE = Config.get().getDBMPropagationMode();
5355
public static final boolean INJECT_COMMENT =
5456
DBM_PROPAGATION_MODE.equals(DBM_PROPAGATION_MODE_FULL)
@@ -252,6 +254,10 @@ public String traceParent(AgentSpan span, int samplingPriority) {
252254
return sb.toString();
253255
}
254256

257+
public boolean isOracle(final DBInfo dbInfo) {
258+
return "oracle".equals(dbInfo.getType());
259+
}
260+
255261
public boolean isPostgres(final DBInfo dbInfo) {
256262
return dbInfo.getType().startsWith("postgres");
257263
}
@@ -260,6 +266,38 @@ public boolean isSqlServer(final DBInfo dbInfo) {
260266
return "sqlserver".equals(dbInfo.getType());
261267
}
262268

269+
/**
270+
* Executes `connection.setClientInfo("OCSID.ACTION", traceContext)` statement on the Oracle DB to
271+
* set the trace parent in `v$session.action`. This is used because it isn't possible to propagate
272+
* trace parent with the comment.
273+
*
274+
* @param span The span of the instrumented statement
275+
* @param connection The same connection as the one that will be used for the actual statement
276+
*/
277+
public void setAction(AgentSpan span, Connection connection) {
278+
try {
279+
280+
Integer priority = span.forceSamplingDecision();
281+
if (priority == null) {
282+
return;
283+
}
284+
final String traceContext = DD_INSTRUMENTATION_PREFIX + DECORATE.traceParent(span, priority);
285+
286+
connection.setClientInfo("OCSID.ACTION", traceContext);
287+
288+
} catch (Throwable e) {
289+
log.debug(
290+
"Failed to set extra DBM data in application_name for trace {}. "
291+
+ "To disable this behavior, set trace_prepared_statements to 'false'. "
292+
+ "See https://docs.datadoghq.com/database_monitoring/connect_dbm_and_apm/ for more info. {}",
293+
span.getTraceId().toHexString(),
294+
e);
295+
DECORATE.onError(span, e);
296+
} finally {
297+
span.setTag("_dd.dbm_trace_injected", true);
298+
}
299+
}
300+
263301
/**
264302
* Executes a `SET CONTEXT_INFO` statement on the DB with the active trace ID and the given span
265303
* ID. This context will be "attached" to future queries on the same connection. See <a

dd-java-agent/instrumentation/jdbc/src/main/java/datadog/trace/instrumentation/jdbc/StatementInstrumentation.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,20 @@ public static AgentScope onEnter(
8787
boolean injectTraceContext = DECORATE.shouldInjectTraceContext(dbInfo);
8888
final AgentSpan span;
8989
final boolean isSqlServer = DECORATE.isSqlServer(dbInfo);
90+
final boolean isOracle = DECORATE.isOracle(dbInfo);
9091

91-
if (isSqlServer && INJECT_COMMENT && injectTraceContext) {
92-
// The span ID is pre-determined so that we can reference it when setting the context
93-
final long spanID = DECORATE.setContextInfo(connection, dbInfo);
94-
// we then force that pre-determined span ID for the span covering the actual query
95-
span = AgentTracer.get().buildSpan(DATABASE_QUERY).withSpanId(spanID).start();
92+
if (INJECT_COMMENT && injectTraceContext) {
93+
if (isSqlServer) {
94+
// The span ID is pre-determined so that we can reference it when setting the context
95+
final long spanID = DECORATE.setContextInfo(connection, dbInfo);
96+
// we then force that pre-determined span ID for the span covering the actual query
97+
span = AgentTracer.get().buildSpan(DATABASE_QUERY).withSpanId(spanID).start();
98+
} else if (isOracle) {
99+
span = startSpan(DATABASE_QUERY);
100+
DECORATE.setAction(span, connection);
101+
} else {
102+
span = startSpan(DATABASE_QUERY);
103+
}
96104
} else {
97105
span = startSpan(DATABASE_QUERY);
98106
}

dd-java-agent/instrumentation/jdbc/src/test/groovy/JDBCDecoratorTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ abstract class JDBCDecoratorTest extends AgentTestRunner {
2020
2121
where:
2222
dbType | expectedByType
23-
"oracle" | false
23+
"oracle" | true
2424
"sqlserver" | true
2525
"mysql" | true
2626
"postgresql" | true

0 commit comments

Comments
 (0)