Skip to content
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

Merged
merged 9 commits into from Dec 12, 2023

Conversation

rarguelloF
Copy link
Contributor

@rarguelloF rarguelloF commented Nov 2, 2023

What does this PR do?

Automatically downgrade DBM propagation mode from full to service 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

  • Changed code has unit tests for its functionality at or near 100% coverage.
  • There is a benchmark for any new code, or changes to existing code.
  • If this interacts with the agent in a new way, a system test has been added.

For Datadog employees:

  • If this PR touches code that handles credentials of any kind, such as Datadog API keys, I've requested a review from @DataDog/security-design-and-guidance.
  • This PR doesn't touch any of that.

Unsure? Have a question? Request a review!

@rarguelloF rarguelloF changed the title database/sql: prevent DBM propagation full mode with incompatible dri… database/sql: prevent DBM propagation full mode with incompatible drivers Nov 2, 2023
@pr-commenter
Copy link

pr-commenter bot commented Nov 2, 2023

Benchmarks

Benchmark execution time: 2023-12-01 10:24:08

Comparing candidate commit 4c9ef99 in PR branch rarguelloF/dbm-prevent-full-mode with baseline commit d2016f2 in branch main.

Found 0 performance improvements and 0 performance regressions! Performance is the same for 41 metrics, 0 unstable metrics.

@rarguelloF rarguelloF force-pushed the rarguelloF/dbm-prevent-full-mode branch from 706d891 to b8a0110 Compare November 2, 2023 13:28
fullModeSupported := func() bool {
unsupportedDrivers := []string{"sqlserver", "oracle"}
for _, dr := range unsupportedDrivers {
if dr == driverName {
Copy link
Contributor

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 ?

Copy link
Contributor

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
}

Copy link
Contributor Author

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:

  1. check driver package path using reflection
  2. check dsn prefix
  3. lastly check the driverName like I was doing in this version

please let me know what you think @vandonr @alexandre-normand

return true
}
if cfg.dbmPropagationMode == tracer.DBMPropagationModeFull && !fullModeSupported() {
log.Warn("Using DBM_PROPAGATION_MODE in 'full' mode is not supported for %s. See "+
Copy link
Contributor

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.

}

func checkDBMPropagation(cfg *config, driverName string) {
fullModeSupported := func() bool {
Copy link
Contributor

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?

Copy link
Contributor Author

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) {
Copy link
Contributor

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch! adding it 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙇

fullModeSupported := func() bool {
unsupportedDrivers := []string{"sqlserver", "oracle"}
for _, dr := range unsupportedDrivers {
if dr == driverName {
Copy link
Contributor

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
}

Copy link

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.

@github-actions github-actions bot added the stale Stuck for more than 1 month label Nov 23, 2023
@rarguelloF rarguelloF removed the stale Stuck for more than 1 month label Nov 23, 2023
@rarguelloF rarguelloF marked this pull request as ready for review November 29, 2023 17:18
}
}

func dbmFullModeUnsupported(driverName string, driver driver.Driver, dsn string) (string, bool) {
Copy link
Contributor

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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙇

Copy link
Contributor

@vandonr vandonr left a 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 💦

@rarguelloF rarguelloF changed the title database/sql: prevent DBM propagation full mode with incompatible drivers contrib/database/sql: prevent DBM propagation full mode with incompatible dbs Dec 1, 2023
@github-actions github-actions bot added the apm:ecosystem contrib/* related feature requests or bugs label Dec 1, 2023
@rarguelloF rarguelloF enabled auto-merge (squash) December 12, 2023 13:01
@rarguelloF rarguelloF merged commit fa3ec4f into main Dec 12, 2023
45 of 49 checks passed
@rarguelloF rarguelloF deleted the rarguelloF/dbm-prevent-full-mode branch December 12, 2023 13:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
apm:ecosystem contrib/* related feature requests or bugs
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants