Skip to content

Commit 66401dd

Browse files
committed
add tests on driver instrumentation
1 parent a4ec186 commit 66401dd

File tree

2 files changed

+273
-2
lines changed

2 files changed

+273
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,10 @@ public class JDBCDecorator extends DatabaseClientDecorator<DBInfo> {
6060
DBM_PROPAGATION_MODE.equals(DBM_PROPAGATION_MODE_FULL);
6161
public static final boolean DBM_TRACE_PREPARED_STATEMENTS =
6262
Config.get().isDbmTracePreparedStatements();
63-
private static final boolean FETCH_DB_METADATA_ON_QUERY =
64-
Config.get().isDbMetadataFetchingOnQueryEnabled();
6563
public static final boolean FETCH_DB_METADATA_ON_CONNECT =
6664
Config.get().isDbMetadataFetchingOnConnectEnabled();
65+
private static final boolean FETCH_DB_METADATA_ON_QUERY =
66+
Config.get().isDbMetadataFetchingOnQueryEnabled();
6767

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

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
import static datadog.trace.agent.test.utils.TraceUtils.runUnderTrace
2+
import static datadog.trace.api.config.TraceInstrumentationConfig.DB_METADATA_FETCHING_ON_CONNECT
3+
4+
import datadog.trace.agent.test.InstrumentationSpecification
5+
import datadog.trace.api.DDSpanTypes
6+
import datadog.trace.bootstrap.instrumentation.api.Tags
7+
import java.sql.Connection
8+
import java.sql.DatabaseMetaData
9+
import java.sql.SQLException
10+
import java.sql.Statement
11+
import test.TestConnection
12+
import test.TestDatabaseMetaData
13+
import test.TestDriver
14+
15+
abstract class DriverInstrumentationMetadataFetchingTestBase extends InstrumentationSpecification {
16+
17+
def "test dbInfo extraction from metadata or URL with username"() {
18+
setup:
19+
def originalUrl = "jdbc:postgresql://original-host:1234/originaldb"
20+
def metadataUrl = "jdbc:postgresql://metadata-host:5678/metadatadb"
21+
22+
def metadata = new TestDatabaseMetaData() {
23+
@Override
24+
String getURL() throws SQLException {
25+
return metadataUrl
26+
}
27+
28+
@Override
29+
String getUserName() throws SQLException {
30+
return "metadata-user"
31+
}
32+
}
33+
34+
def testConnection = new TestConnection(false)
35+
testConnection.setMetaData(metadata)
36+
37+
def driver = new TestDriver() {
38+
@Override
39+
Connection connect(String url, Properties info) {
40+
return testConnection
41+
}
42+
}
43+
44+
def props = new Properties()
45+
props.put("user", "original-user")
46+
47+
// Expected values depend on whether metadata fetching is enabled
48+
def expectedDbInstance = shouldFetchMetadataOnConnect() ? "metadatadb" : "originaldb"
49+
def expectedDbUser = shouldFetchMetadataOnConnect() ? "metadata-user" : "original-user"
50+
51+
when:
52+
def connection = driver.connect(originalUrl, props)
53+
Statement statement = connection.createStatement()
54+
runUnderTrace("parent") {
55+
statement.execute("SELECT 1")
56+
}
57+
58+
then:
59+
assertTraces(1) {
60+
trace(2) {
61+
span(0) {
62+
operationName "parent"
63+
}
64+
span(1) {
65+
operationName "postgresql.query"
66+
spanType DDSpanTypes.SQL
67+
childOf span(0)
68+
tags(false) {
69+
"$Tags.DB_INSTANCE" expectedDbInstance
70+
"$Tags.DB_USER" expectedDbUser
71+
}
72+
}
73+
}
74+
}
75+
76+
cleanup:
77+
statement?.close()
78+
connection?.close()
79+
}
80+
81+
def "test driver connect with null metadata URL"() {
82+
setup:
83+
def originalUrl = "jdbc:postgresql://original-host:5432/originaldb"
84+
85+
def metadata = new TestDatabaseMetaData() {
86+
@Override
87+
String getURL() throws SQLException {
88+
return null
89+
}
90+
}
91+
92+
def testConnection = new TestConnection(false)
93+
testConnection.setMetaData(metadata)
94+
95+
def driver = new TestDriver() {
96+
@Override
97+
Connection connect(String url, Properties info) {
98+
return testConnection
99+
}
100+
}
101+
102+
def props = new Properties()
103+
104+
when:
105+
def connection = driver.connect(originalUrl, props)
106+
Statement statement = connection.createStatement()
107+
runUnderTrace("parent") {
108+
statement.execute("SELECT 1")
109+
}
110+
111+
then:
112+
assertTraces(1) {
113+
trace(2) {
114+
span(0) {
115+
operationName "parent"
116+
}
117+
span(1) {
118+
operationName "postgresql.query"
119+
spanType DDSpanTypes.SQL
120+
childOf span(0)
121+
tags(false) {
122+
// Should fallback to original URL regardless of flag when metadata URL is null
123+
"$Tags.DB_INSTANCE" "originaldb"
124+
}
125+
}
126+
}
127+
}
128+
129+
cleanup:
130+
statement?.close()
131+
connection?.close()
132+
}
133+
134+
def "test driver connect with metadata exception"() {
135+
setup:
136+
def originalUrl = "jdbc:postgresql://original-host:5432/originaldb"
137+
138+
def testConnection = new TestConnection(false) {
139+
@Override
140+
DatabaseMetaData getMetaData() throws SQLException {
141+
throw new SQLException("Test exception")
142+
}
143+
}
144+
145+
def driver = new TestDriver() {
146+
@Override
147+
Connection connect(String url, Properties info) {
148+
return testConnection
149+
}
150+
}
151+
152+
def props = new Properties()
153+
154+
when:
155+
def connection = driver.connect(originalUrl, props)
156+
Statement statement = connection.createStatement()
157+
runUnderTrace("parent") {
158+
statement.execute("SELECT 1")
159+
}
160+
161+
then:
162+
assertTraces(1) {
163+
trace(2) {
164+
span(0) {
165+
operationName "parent"
166+
}
167+
span(1) {
168+
operationName "postgresql.query"
169+
spanType DDSpanTypes.SQL
170+
childOf span(0)
171+
tags(false) {
172+
// Should fallback to original URL when exception occurs
173+
"$Tags.DB_INSTANCE" "originaldb"
174+
}
175+
}
176+
}
177+
}
178+
179+
cleanup:
180+
statement?.close()
181+
connection?.close()
182+
}
183+
184+
def "test driver connect with Oracle sharding driver"() {
185+
setup:
186+
def originalUrl = "jdbc:oracle:thin:@original-host:1521:orcl"
187+
def metadataUrl = "jdbc:oracle:thin:@metadata-host:1521:orcl"
188+
189+
def metadata = new TestDatabaseMetaData()
190+
metadata.setURL(metadataUrl)
191+
192+
def testConnection = new TestConnection(false)
193+
testConnection.setMetaData(metadata)
194+
195+
def driver = new TestDriver() {
196+
@Override
197+
Connection connect(String url, Properties info) {
198+
return testConnection
199+
}
200+
}
201+
202+
def props = new Properties()
203+
props.setProperty("oracle.jdbc.useShardingDriverConnection", "true")
204+
205+
when:
206+
def connection = driver.connect(originalUrl, props)
207+
Statement statement = connection.createStatement()
208+
runUnderTrace("parent") {
209+
statement.execute("SELECT 1")
210+
}
211+
212+
then:
213+
assertTraces(1) {
214+
trace(2) {
215+
span(0) {
216+
operationName "parent"
217+
}
218+
span(1) {
219+
operationName "oracle.query"
220+
spanType DDSpanTypes.SQL
221+
childOf span(0)
222+
tags(false) {
223+
// Should use original URL for Oracle sharding driver regardless of flag
224+
"$Tags.DB_INSTANCE" "orcl"
225+
}
226+
}
227+
}
228+
}
229+
230+
cleanup:
231+
statement?.close()
232+
connection?.close()
233+
}
234+
235+
abstract boolean shouldFetchMetadataOnConnect()
236+
}
237+
238+
/**
239+
* Test with metadata fetching enabled on connect (default behavior)
240+
*/
241+
class DriverInstrumentationWithMetadataOnConnectForkedTest extends DriverInstrumentationMetadataFetchingTestBase {
242+
243+
@Override
244+
void configurePreAgent() {
245+
super.configurePreAgent()
246+
injectSysConfig(DB_METADATA_FETCHING_ON_CONNECT, "true")
247+
}
248+
249+
@Override
250+
boolean shouldFetchMetadataOnConnect() {
251+
return true
252+
}
253+
}
254+
255+
/**
256+
* Test with metadata fetching disabled on connect
257+
*/
258+
class DriverInstrumentationWithoutMetadataOnConnectForkedTest extends DriverInstrumentationMetadataFetchingTestBase {
259+
260+
@Override
261+
void configurePreAgent() {
262+
super.configurePreAgent()
263+
injectSysConfig(DB_METADATA_FETCHING_ON_CONNECT, "false")
264+
}
265+
266+
@Override
267+
boolean shouldFetchMetadataOnConnect() {
268+
return false
269+
}
270+
}
271+

0 commit comments

Comments
 (0)