-
Notifications
You must be signed in to change notification settings - Fork 283
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DBM-APM: Selectively pre/append sql comments depending on DBMS typeq #6160
Conversation
BenchmarksStartupParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 54 cases. Startup time reports for insecure-bankgantt
title insecure-bank - global startup overhead: candidate=1.23.0-SNAPSHOT~edee3aa345, baseline=1.23.0-SNAPSHOT~67f30b8244
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.04 s) : 0, 1039980
Total [baseline] (8.803 s) : 0, 8803457
Agent [candidate] (1.035 s) : 0, 1034851
Total [candidate] (8.765 s) : 0, 8764926
section iast
Agent [baseline] (1.153 s) : 0, 1153124
Total [baseline] (9.346 s) : 0, 9346034
Agent [candidate] (1.162 s) : 0, 1161587
Total [candidate] (9.344 s) : 0, 9344459
section iast_TELEMETRY_OFF
Agent [baseline] (1.148 s) : 0, 1147535
Total [baseline] (9.306 s) : 0, 9305989
Agent [candidate] (1.144 s) : 0, 1143676
Total [candidate] (9.364 s) : 0, 9363761
gantt
title insecure-bank - break down per module: candidate=1.23.0-SNAPSHOT~edee3aa345, baseline=1.23.0-SNAPSHOT~67f30b8244
dateFormat X
axisFormat %s
section tracing
BytebuddyAgent [baseline] (649.047 ms) : 0, 649047
BytebuddyAgent [candidate] (645.447 ms) : 0, 645447
GlobalTracer [baseline] (295.231 ms) : 0, 295231
GlobalTracer [candidate] (293.958 ms) : 0, 293958
AppSec [baseline] (48.955 ms) : 0, 48955
AppSec [candidate] (49.075 ms) : 0, 49075
Remote Config [baseline] (700.664 µs) : 0, 701
Remote Config [candidate] (686.677 µs) : 0, 687
Telemetry [baseline] (11.362 ms) : 0, 11362
Telemetry [candidate] (11.351 ms) : 0, 11351
section iast
BytebuddyAgent [baseline] (765.515 ms) : 0, 765515
BytebuddyAgent [candidate] (771.871 ms) : 0, 771871
GlobalTracer [baseline] (275.529 ms) : 0, 275529
GlobalTracer [candidate] (277.506 ms) : 0, 277506
AppSec [baseline] (46.838 ms) : 0, 46838
AppSec [candidate] (47.343 ms) : 0, 47343
IAST [baseline] (18.343 ms) : 0, 18343
IAST [candidate] (15.601 ms) : 0, 15601
Remote Config [baseline] (581.95 µs) : 0, 582
Remote Config [candidate] (562.285 µs) : 0, 562
Telemetry [baseline] (11.905 ms) : 0, 11905
Telemetry [candidate] (13.984 ms) : 0, 13984
section iast_TELEMETRY_OFF
BytebuddyAgent [baseline] (762.585 ms) : 0, 762585
BytebuddyAgent [candidate] (758.351 ms) : 0, 758351
GlobalTracer [baseline] (275.202 ms) : 0, 275202
GlobalTracer [candidate] (274.514 ms) : 0, 274514
AppSec [baseline] (46.806 ms) : 0, 46806
AppSec [candidate] (46.619 ms) : 0, 46619
IAST [baseline] (17.307 ms) : 0, 17307
IAST [candidate] (16.767 ms) : 0, 16767
Remote Config [baseline] (564.851 µs) : 0, 565
Remote Config [candidate] (563.096 µs) : 0, 563
Telemetry [baseline] (10.474 ms) : 0, 10474
Telemetry [candidate] (12.533 ms) : 0, 12533
Startup time reports for petclinicgantt
title petclinic - global startup overhead: candidate=1.23.0-SNAPSHOT~edee3aa345, baseline=1.23.0-SNAPSHOT~67f30b8244
dateFormat X
axisFormat %s
section tracing
Agent [baseline] (1.035 s) : 0, 1034803
Total [baseline] (9.315 s) : 0, 9314754
Agent [candidate] (1.036 s) : 0, 1036000
Total [candidate] (9.285 s) : 0, 9285151
section appsec
Agent [baseline] (1.126 s) : 0, 1126053
Total [baseline] (9.427 s) : 0, 9427175
Agent [candidate] (1.119 s) : 0, 1119047
Total [candidate] (9.36 s) : 0, 9360359
section iast
Agent [baseline] (1.147 s) : 0, 1146967
Total [baseline] (9.463 s) : 0, 9463353
Agent [candidate] (1.15 s) : 0, 1149571
Total [candidate] (9.476 s) : 0, 9475569
section profiling
Agent [baseline] (1.221 s) : 0, 1220980
Total [baseline] (9.521 s) : 0, 9521255
Agent [candidate] (1.22 s) : 0, 1219930
Total [candidate] (9.553 s) : 0, 9552857
gantt
title petclinic - break down per module: candidate=1.23.0-SNAPSHOT~edee3aa345, baseline=1.23.0-SNAPSHOT~67f30b8244
dateFormat X
axisFormat %s
section tracing
BytebuddyAgent [baseline] (645.583 ms) : 0, 645583
BytebuddyAgent [candidate] (646.309 ms) : 0, 646309
GlobalTracer [baseline] (294.13 ms) : 0, 294130
GlobalTracer [candidate] (294.371 ms) : 0, 294371
AppSec [baseline] (48.806 ms) : 0, 48806
AppSec [candidate] (49.12 ms) : 0, 49120
Remote Config [baseline] (691.043 µs) : 0, 691
Remote Config [candidate] (691.226 µs) : 0, 691
Telemetry [baseline] (11.254 ms) : 0, 11254
Telemetry [candidate] (11.194 ms) : 0, 11194
section appsec
BytebuddyAgent [baseline] (649.482 ms) : 0, 649482
BytebuddyAgent [candidate] (645.862 ms) : 0, 645862
GlobalTracer [baseline] (295.609 ms) : 0, 295609
GlobalTracer [candidate] (293.749 ms) : 0, 293749
AppSec [baseline] (138.714 ms) : 0, 138714
AppSec [candidate] (137.572 ms) : 0, 137572
Remote Config [baseline] (651.762 µs) : 0, 652
Remote Config [candidate] (641.243 µs) : 0, 641
Telemetry [baseline] (6.927 ms) : 0, 6927
Telemetry [candidate] (6.83 ms) : 0, 6830
section iast
BytebuddyAgent [baseline] (763.618 ms) : 0, 763618
BytebuddyAgent [candidate] (765.263 ms) : 0, 765263
GlobalTracer [baseline] (274.015 ms) : 0, 274015
GlobalTracer [candidate] (274.402 ms) : 0, 274402
AppSec [baseline] (46.509 ms) : 0, 46509
AppSec [candidate] (46.791 ms) : 0, 46791
Remote Config [baseline] (567.557 µs) : 0, 568
Remote Config [candidate] (575.436 µs) : 0, 575
Telemetry [baseline] (10.557 ms) : 0, 10557
Telemetry [candidate] (11.243 ms) : 0, 11243
IAST [baseline] (17.352 ms) : 0, 17352
IAST [candidate] (16.951 ms) : 0, 16951
section profiling
BytebuddyAgent [baseline] (656.185 ms) : 0, 656185
BytebuddyAgent [candidate] (657.13 ms) : 0, 657130
GlobalTracer [baseline] (360.275 ms) : 0, 360275
GlobalTracer [candidate] (359.125 ms) : 0, 359125
AppSec [baseline] (49.623 ms) : 0, 49623
AppSec [candidate] (49.076 ms) : 0, 49076
Remote Config [baseline] (649.173 µs) : 0, 649
Remote Config [candidate] (662.625 µs) : 0, 663
Telemetry [baseline] (11.332 ms) : 0, 11332
Telemetry [candidate] (11.338 ms) : 0, 11338
ProfilingAgent [baseline] (88.637 ms) : 0, 88637
ProfilingAgent [candidate] (88.356 ms) : 0, 88356
Profiling [baseline] (88.66 ms) : 0, 88660
Profiling [candidate] (88.38 ms) : 0, 88380
LoadParameters
See matching parameters
SummaryFound 0 performance improvements and 0 performance regressions! Performance is the same for 22 cases. Request duration reports for insecure-bankgantt
title insecure-bank - request duration [CI 0.99] : candidate=1.23.0-SNAPSHOT~edee3aa345, baseline=1.23.0-SNAPSHOT~67f30b8244
dateFormat X
axisFormat %s
section baseline
no_agent (361.711 µs) : 342, 382
. : milestone, 362,
iast (469.502 µs) : 448, 491
. : milestone, 470,
iast_FULL (525.743 µs) : 505, 546
. : milestone, 526,
iast_INACTIVE (436.827 µs) : 416, 458
. : milestone, 437,
iast_TELEMETRY_OFF (463.461 µs) : 443, 484
. : milestone, 463,
tracing (438.097 µs) : 417, 460
. : milestone, 438,
section candidate
no_agent (367.639 µs) : 347, 388
. : milestone, 368,
iast (468.159 µs) : 447, 489
. : milestone, 468,
iast_FULL (526.27 µs) : 506, 547
. : milestone, 526,
iast_INACTIVE (436.846 µs) : 415, 459
. : milestone, 437,
iast_TELEMETRY_OFF (455.605 µs) : 435, 477
. : milestone, 456,
tracing (432.25 µs) : 411, 453
. : milestone, 432,
Request duration reports for petclinicgantt
title petclinic - request duration [CI 0.99] : candidate=1.23.0-SNAPSHOT~edee3aa345, baseline=1.23.0-SNAPSHOT~67f30b8244
dateFormat X
axisFormat %s
section baseline
no_agent (1.348 ms) : 1329, 1367
. : milestone, 1348,
appsec (1.717 ms) : 1693, 1741
. : milestone, 1717,
iast (1.483 ms) : 1459, 1506
. : milestone, 1483,
profiling (1.465 ms) : 1440, 1491
. : milestone, 1465,
tracing (1.445 ms) : 1420, 1470
. : milestone, 1445,
section candidate
no_agent (1.347 ms) : 1328, 1366
. : milestone, 1347,
appsec (1.71 ms) : 1685, 1736
. : milestone, 1710,
iast (1.456 ms) : 1431, 1480
. : milestone, 1456,
profiling (1.487 ms) : 1461, 1513
. : milestone, 1487,
tracing (1.464 ms) : 1440, 1489
. : milestone, 1464,
|
@@ -73,6 +73,8 @@ public DBMCompatibleConnectionInstrumentation() { | |||
"com.informix.jdbc.IfmxConnection", | |||
}; | |||
|
|||
private static final String locationMode = "prepend"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably makes more sense for this to be a boolean or an enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
boolean would be preferred in this case - avoids having to list all the enum classes as helpers
@@ -19,23 +19,28 @@ public class SQLCommenter { | |||
private static final char EQUALS = '='; | |||
private static final char COMMA = ','; | |||
private static final char QUOTE = '\''; | |||
private static final String OPEN_COMMENT_APPEND = " /*"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are there two constants for OPEN_COMMENT & OPEN_COMMENT_APPEND?
I also see that there's a use of the string literal as "/*" in the code as well.
I think having 3 of same thing is making the code a bit harder to follow.
private static final int INITIAL_CAPACITY = computeInitialCapacity(); | ||
private static final String PREPEND = "prepend"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd replace these with an enum or a boolean for the two different modes.
sb.append(sql); | ||
sb.append(OPEN_COMMENT_APPEND); | ||
toComment(sb, injectTrace, parentService, dbService, env, version, traceParent); | ||
if (sb.length() == OPEN_COMMENT_APPEND.length() + sql.length()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It isn't immediately obvious to me what this check is doing.
I'm guessing that it is checking whether the comment was able to be injected, but it is hard to tell.
If that's the case, I'd prefer to see toComment return a boolean indicating success.
That would make the code flow easier to follow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah sure, that makes sense
@@ -44,6 +49,16 @@ public static String inject( | |||
final String version = config.getVersion(); | |||
final int commentSize = capacity(traceParent, parentService, dbService, env, version); | |||
StringBuilder sb = new StringBuilder(sql.length() + commentSize); | |||
if (locationMode.equals(APPEND)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd prefer to see this as an if / else - rather than an if with an early return.
To me, that would make the code easier to understand.
"/*traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-01'*/ SELECT * FROM foo" | "SqlCommenter" | "Test" | "my-service" | "TestVersion" | false | null | "/*traceparent='00-00000000000000007fffffffffffffff-000000024cb016ea-01'*/ SELECT * FROM foo" | ||
"/*customer-comment*/ SELECT * FROM foo" | "SqlCommenter" | "Test" | "my-service" | "TestVersion" | false | null | "/*ddps='SqlCommenter',dddbs='my-service',dde='Test',ddpv='TestVersion'*/ /*customer-comment*/ SELECT * FROM foo" | ||
"/*traceparent" | "SqlCommenter" | "Test" | "my-service" | "TestVersion" | false | null | "/*ddps='SqlCommenter',dddbs='my-service',dde='Test',ddpv='TestVersion'*/ /*traceparent" | ||
query | ddService | ddEnv | dbService | ddVersion | injectTrace | locationMode | traceParent | expected |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff is hard to read. Is there a test here that tests the edge case where the injection fails?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find the logic hard to follow in places.
I'd like to see a bit of clean-up.
I also think the append vs prepend could be better handled with a boolean or an enum.
@@ -124,7 +127,7 @@ public static String onEnter( | |||
final DBInfo dbInfo = | |||
JDBCDecorator.parseDBInfo( | |||
connection, InstrumentationContext.get(Connection.class, DBInfo.class)); | |||
sql = SQLCommenter.inject(sql, DECORATE.getDbService(dbInfo)); | |||
sql = SQLCommenter.inject(sql, DECORATE.getDbService(dbInfo), appendComment); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Have you considered providing two methods SQLCommenter.append
and SQLCommenter.prepend
which each just call SQLCommenter.inject
with the appropriate boolean flag?
I think that would be much more self-documenting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah that probably would be easier on the eyes. I'll update that now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that was a nice improvement. Thanks for doing that.
private static final int INITIAL_CAPACITY = computeInitialCapacity(); | ||
|
||
public static String inject(final String sql, final String dbService) { | ||
return inject(sql, dbService, null, false); | ||
public static String append(final String sql, final String dbService) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the splitting of the functions.
edee3aa
to
422977d
Compare
the test failures are unrelated to my PR && is fixed in here #6177 Going to merge this since we have confidence based on the relevant unit / system tests passing |
What Does This Do
This PR updates the logic for the APM-DBM link feature introduced in #4847. It changes from prepending the sql comments, containing the APM trace context, to appending them to the raw sql for SQL Server driver implementations only. This requires no changes on the DBM side of things in either the agent or our backend.
Jira ticket: DBMON-2759
Motivation
This fixes an issue, which has been reported by several customers that executing
CallableStatement
s with the following syntax causes exceptions to be thrown when enabling APM-DBM link:We were able to reproduce this, using the latest version of the java tracer && an internal application. It seems to be caused by the SQL comments we inject being prepended instead of appended. For example, the issue of prepending the comment was reproduced with a simple java application (without APM-DBM link enabled), which did the following:
... this throws the same exception with message
Incorrect syntax near '{'.
Proof of Fix
After doing a custom build of this tracer code, we deployed our test app, which runs a combination of
PreparedStatement
/Statements
/CallableStatement
& no longer saw theIncorrect syntax near '{'.
exception being thrown.We were also able to confirm that injection is still working properly, e.g: our events are being properly decorated:
Expected DBM Behavior for Stored Procedures
Stored Procedures aren't supported for the APM-DBM usecase (unless the same app that is calling them is the thing that created the stored procedure & the linking was enabled). Otherwise, we wouldn't see the comments if someone had code that was simply calling
EXEC proc
or{call proc}
, since the actual text we see in the activity code is either:Neither, contains the text
EXEC proc
, which is what would have the comment injected via the tracer.Obviously, this is of secondary concern here. Updating the tracer to append the comment will fix this edge case being reported by customers. We really don't want the feature to cause users to see exceptions being thrown in their production code.