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
contrib/database/sql: prevent DBM propagation full mode with incompatible dbs #2328
Conversation
BenchmarksBenchmark execution time: 2023-12-01 10:24:08 Comparing candidate commit 4c9ef99 in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 41 metrics, 0 unstable metrics. |
706d891
to
b8a0110
Compare
contrib/database/sql/sql.go
Outdated
fullModeSupported := func() bool { | ||
unsupportedDrivers := []string{"sqlserver", "oracle"} | ||
for _, dr := range unsupportedDrivers { | ||
if dr == driverName { |
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.
this looks a bit brittle, tell me if I'm wrong, but it looks like driverName
is just a key used to retrieve it later and/or make sure init is only done once, and it can take pretty much any value ?
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.
Obviously take my perspective with a grain of salt since I'm not an owner/maintainer for the go tracer but I agree that the driverName based logic is somewhat brittle. I know it's done in other places but I wonder if we could still consider doing type checking on the driver.Driver
or driver.Connector
.
Something like
if connector.Driver().(go_ora.OracleDriver) {
// we know this is one of the oracle drivers
}
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.
Agree! I've added a new way to detect the driver, following this logic:
- check driver package path using reflection
- check dsn prefix
- lastly check the driverName like I was doing in this version
please let me know what you think @vandonr @alexandre-normand
contrib/database/sql/sql.go
Outdated
return true | ||
} | ||
if cfg.dbmPropagationMode == tracer.DBMPropagationModeFull && !fullModeSupported() { | ||
log.Warn("Using DBM_PROPAGATION_MODE in 'full' mode is not supported for %s. See "+ |
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 it might make sense here to state that we're downgrading to service
mode.
contrib/database/sql/sql.go
Outdated
} | ||
|
||
func checkDBMPropagation(cfg *config, driverName string) { | ||
fullModeSupported := func() bool { |
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.
Just curious about style: why make this an inner anonymous function rather than a named function?
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 was just a matter of namespacing (this way I could use a shorter function name instead of dbmPropagationFullModeSupported
). Anyway, I refactored this code, please take a look at the new version 🙏
@@ -288,6 +288,33 @@ func TestDBMTraceContextTagging(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestDBMPropagation_PreventFullMode(t *testing.T) { |
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 might make sense to have a test that goes through the implicit driver registration (i.e. when a user doesn't call Register
and uses Open
directly?
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.
nice catch! adding it 👍
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.
🙇
contrib/database/sql/sql.go
Outdated
fullModeSupported := func() bool { | ||
unsupportedDrivers := []string{"sqlserver", "oracle"} | ||
for _, dr := range unsupportedDrivers { | ||
if dr == driverName { |
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.
Obviously take my perspective with a grain of salt since I'm not an owner/maintainer for the go tracer but I agree that the driverName based logic is somewhat brittle. I know it's done in other places but I wonder if we could still consider doing type checking on the driver.Driver
or driver.Connector
.
Something like
if connector.Driver().(go_ora.OracleDriver) {
// we know this is one of the oracle drivers
}
This PR is stale because it has been open 20 days with no activity. Remove stale label or comment or this will be closed in 10 days. |
} | ||
} | ||
|
||
func dbmFullModeUnsupported(driverName string, driver driver.Driver, dsn string) (string, bool) { |
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 this way more robust implementation. Nice work gathering the packages/prefixes needed to do the detection.
@@ -288,6 +288,33 @@ func TestDBMTraceContextTagging(t *testing.T) { | |||
} | |||
} | |||
|
|||
func TestDBMPropagation_PreventFullMode(t *testing.T) { |
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.
🙇
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.
nice job getting all the values those variables can take 💦
What does this PR do?
Automatically downgrade DBM propagation mode from
full
toservice
mode with an incompatible database (currently SQL Server and Oracle).Motivation
These DBs don't support full propagation mode due to statement caching behavior which could cause performance issues when including full trace context. See Datadog official docs for more info: https://docs.datadoghq.com/database_monitoring/connect_dbm_and_apm
Reviewer's Checklist
For Datadog employees:
@DataDog/security-design-and-guidance
.Unsure? Have a question? Request a review!