-
Notifications
You must be signed in to change notification settings - Fork 234
feat: database/sql integration #893
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
base: master
Are you sure you want to change the base?
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #893 +/- ##
==========================================
- Coverage 84.00% 83.89% -0.12%
==========================================
Files 50 57 +7
Lines 5171 5544 +373
==========================================
+ Hits 4344 4651 +307
- Misses 673 726 +53
- Partials 154 167 +13 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
I really don't like golangci-lint, it's so pedantic :( |
Should be good by now. |
I'll test this locally myself this week and report back. We should also update the docs and main repository with this integration. |
You're missing examples in _examples. These should also include example on how to set the DSN. |
@ribice I've been occupied so much with work this week. Will find the time to work on this later. |
To be honest, I don't know how to make some of that as covered other than using old Go versions. But I might try creating another database driver implementation that does not implement
I might be able to help with the sentry-docs one, since I also need to update some of the self-hosted docs. |
I haven't reviewed this PR in full yet, but some things I would like to be changed:
|
We are not supporting 3rd party libraries here. We only import the database driver since Go does not bring built-in database drivers and rely on third party drivers. The database drivers we're using should not going to be compiled to the resulting binary since it's only used in tests. Although it seems like we're using it as a library here, it is not, it's still considered a database driver: sentry-go/_examples/sql/main.go Lines 40 to 45 in c5fa49d
MongoDB does not have and does not conform to the
Since we're wrapping a database driver and thus making us another database driver, we are required to implement multiple methods that are considered duplicates by the linter, yet again, from the driver documentation, we're still required to implement those. |
Don't let this die! :) I'm sure many of us in the community will be grateful for an officially supported DB integration |
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.
Overall looks good with the most recent changes and should be functionally correct. Just wanna be sure that the context is passed correctly and also add some minor improvements
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.
some test changes.
// if WantSpan is nil, yet we got some spans, it should be an error | ||
if tt.WantSpan == nil { | ||
t.Errorf("Expecting no spans, but got %d spans: %v", len(gotSpans), gotSpans) | ||
continue | ||
} | ||
|
||
// if WantSpan is not nil, we should have at least one span | ||
if len(gotSpans) == 0 { | ||
t.Errorf("Expecting at least one span, but got %d spans: %v", len(gotSpans), gotSpans) | ||
continue | ||
} | ||
|
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.
Can we not have tt.WantSpans
as a []Span
so that we can compare immediately with gotSpans
? I'd say that it's not very readable.
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.
Did some rounds with this, I can't get []Span
comparison working (problems with google/go-cmp package). Is it okay if we backlog this somehow?
func TestMain(m *testing.M) { | ||
sql.Register("sentrysql-sqlite", sentrysql.NewSentrySQL(&sqlite.Driver{}, sentrysql.WithDatabaseName("memory"), sentrysql.WithDatabaseSystem(sentrysql.DatabaseSystem("sqlite")), sentrysql.WithServerAddress("localhost", "5432"))) | ||
// sentrysql-legacy is used by `sentrysql_legacy_test.go` | ||
sql.Register("sentrysql-legacy", sentrysql.NewSentrySQL(ldriver, sentrysql.WithDatabaseSystem(sentrysql.DatabaseSystem("legacydb")), sentrysql.WithDatabaseName("fake"))) | ||
|
||
os.Exit(m.Run()) | ||
} |
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 is obfuscated from the other tests. Should probably be an init
statement on each file that registers whatever we need only for the tests on the file.
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.
From the docs: If Register is called twice with the same name or if driver is nil, it panics.
I believe setting this here is the "right" way to do so, since it'll be run after any library's init
invocation.
var foundMatch = false | ||
gotSpans := got[i] | ||
|
||
var diffs []string | ||
for _, gotSpan := range gotSpans { | ||
if diff := cmp.Diff(tt.WantSpan, gotSpan, optstrans); diff != "" { | ||
diffs = append(diffs, diff) | ||
} else { | ||
foundMatch = true | ||
break | ||
} | ||
} | ||
|
||
if !foundMatch { | ||
t.Errorf("Span mismatch (-want +got):\n%s", strings.Join(diffs, "\n")) | ||
} |
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.
Same thing applies here. We should probably use a []Span
for WantSpans
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.
Pull Request Overview
Adds Sentry tracing integration to Go’s database/sql by wrapping drivers, connectors, connections, statements, and transactions to automatically start spans for SQL operations.
- Introduce
sentrySQLConfig
andOption
functions to attach metadata (db system, name, host, port). - Wrap
driver.Driver
,driver.Connector
,driver.Conn
, anddriver.Stmt
to emit spans on Exec/Query (including context versions). - Add
parseDatabaseOperation
helper to extract SQL operation names and tests for it.
Reviewed Changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
File | Description |
---|---|
sentrysql/tx.go | Added sentryTx wrapper for driver.Tx (currently no spans). |
sentrysql/stmt.go | Implemented sentryStmt with Exec/Query and ExecContext/QueryContext tracing. |
sentrysql/sentrysql.go | Defined DatabaseSystem , config struct, and constructors (NewSentrySQL , NewSentrySQLConnector ). |
sentrysql/options.go | Added Option functions to set database metadata. |
sentrysql/operation.go | Added parseDatabaseOperation to derive operation names. |
sentrysql/operation_test.go | Added tests for parseDatabaseOperation . |
sentrysql/driver.go | Wrapped driver.Driver and driver.Connector for injection. |
sentrysql/conn.go | Implemented sentryConn with span creation for Exec/Query/Ping/Tx. |
sentrysql/go.mod | Initialized module and dependencies. |
sentrysql/example_test.go | Added examples for NewSentrySQL and NewSentrySQLConnector . |
_examples/sql/main.go | End-to-end example demonstrating tracing of queries and transactions. |
Comments suppressed due to low confidence (1)
sentrysql/stmt.go:75
- There are no unit tests covering
ExecContext
andQueryContext
insentryStmt
. Adding tests would verify span creation and fallback behavior.
func (s *sentryStmt) ExecContext(ctx context.Context, args []driver.NamedValue) (driver.Result, error)
return s.Exec(values) | ||
} | ||
|
||
parentSpan := sentry.SpanFromContext(s.ctx) |
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.
In ExecContext
, you’re calling SpanFromContext
on s.ctx
instead of the passed-in ctx
. This can attach spans to a stale context. Use sentry.SpanFromContext(ctx)
instead.
parentSpan := sentry.SpanFromContext(s.ctx) | |
parentSpan := sentry.SpanFromContext(ctx) |
Copilot uses AI. Check for mistakes.
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 is wrong. ctx
provided from the function argument does not have sentry span context. SInce what matters is the context in which the statement was started.
return s.Query(values) | ||
} | ||
|
||
parentSpan := sentry.SpanFromContext(s.ctx) |
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.
In QueryContext
, you’re using s.ctx
for the parent span lookup instead of the method’s ctx
parameter. Update to sentry.SpanFromContext(ctx)
to ensure the correct context is used.
parentSpan := sentry.SpanFromContext(s.ctx) | |
parentSpan := sentry.SpanFromContext(ctx) |
Copilot uses AI. Check for mistakes.
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 is wrong. ctx
provided from the function argument does not have sentry span context. SInce what matters is the context in which the statement was started.
type sentryTx struct { | ||
originalTx driver.Tx | ||
ctx context.Context | ||
config *sentrySQLConfig |
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.
[nitpick] The config
field in sentryTx
is never used. Consider removing it or adding tracing for Commit
/Rollback
to leverage the config metadata.
Copilot uses AI. Check for mistakes.
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.
Tracing on Commit
/ Rollback
would be useless.
Queries insights tracing for Go.