Add DBNamespaceFromDSN helper and fix AttributesFromDSN bugs#623
Add DBNamespaceFromDSN helper and fix AttributesFromDSN bugs#623cyrille-leclerc wants to merge 7 commits into
Conversation
Introduce DBNamespaceFromDSN to extract the db.namespace OTel attribute from a DSN string, with support for sqlserver (database query param) and an explicit error for oracle (DB_UNIQUE_NAME is not DSN-derivable). Also fix a panic in AttributesFromDSN when the closing protocol parenthesis is missing and the DSN has no path nor query string, and fix server.port parsing when the DSN has a query string but no path.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #623 +/- ##
=======================================
+ Coverage 86.4% 87.0% +0.5%
=======================================
Files 16 16
Lines 752 786 +34
=======================================
+ Hits 650 684 +34
Misses 75 75
Partials 27 27 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
| // It makes the best effort to retrieve values for [semconv.ServerAddressKey] and [semconv.ServerPortKey]. | ||
| func AttributesFromDSN(dsn string) []attribute.KeyValue { | ||
| // [scheme://][user[:password]@][protocol([addr])]/dbname[?param1=value1¶mN=valueN] | ||
| // [scheme://][user[:password]@][protocol([addr])][/path][?param1=value1¶mN=valueN] |
There was a problem hiding this comment.
We see with sqlserver and oracle that the /path is not always the dbname
| // [protocol([addr])]/dbname[?param1=value1¶mN=valueN] | ||
| // [protocol([addr])][/path][?param1=value1¶mN=valueN] | ||
| // Find the '?' that separates the query string. | ||
| if questionMarkIndex := strings.Index(dsn, "?"); questionMarkIndex != -1 { |
There was a problem hiding this comment.
Fix bug in server.port parsing when DSN has no path but a query string.
| // Find the '(' that starts the address part. | ||
| openParen := strings.Index(dsn, "(") | ||
| if openParen != -1 { | ||
| rest := dsn[openParen+1:] |
There was a problem hiding this comment.
Fix panic in server.address parsing when a protocol is specified but a parenthesis is missing and DSN has no /path nor query string
Add //nolint:gosec to TestAttributesFromDSN and use require.NoError instead of assert.NoError in TestDBNamespaceFromDSN.
- DBNamespaceFromDSN now returns errDBNamespaceNotFound for unknown and scheme-less DSNs; supported schemes are postgresql, postgres, mysql, clickhouse (path-based) and sqlserver, mssql (query param) - Extract parseHostPort helper from AttributesFromDSN to reduce its cyclomatic complexity from 12 to 7 - Update test expectations and CHANGELOG accordingly
XSAM
left a comment
There was a problem hiding this comment.
Could we separate this PR into two? One for the fix of AttributesFromDSN, one for DBNamespaceFromDSN?
| }, | ||
| }, | ||
| { | ||
| // Missing closing protocol parenthesis and no path/queryString shouldn't cause a panic |
There was a problem hiding this comment.
The main branch won't cause a panic in this case after #625
| // Missing closing protocol parenthesis and no path/queryString shouldn't cause a panic | ||
| dsn: "mysql://root:otel_password@tcp(example.com", | ||
| expected: []attribute.KeyValue{ | ||
| semconv.ServerAddress("example.com"), |
There was a problem hiding this comment.
mysql://root:otel_password@tcp(example.com does not look like a valid DSN. Maybe we should drop the value.
| switch scheme { | ||
| case "sqlserver", "mssql": | ||
| if params, err := url.ParseQuery(queryString); err == nil { | ||
| if db := params.Get("database"); db != "" { | ||
| return semconv.DBNamespace(db), nil | ||
| } | ||
| } | ||
| case "postgresql", "postgres", "mysql", "clickhouse": | ||
| if path != "" { | ||
| return semconv.DBNamespace(path), nil |
There was a problem hiding this comment.
I am not sure whether we should add this. Maybe this repo needs a contrib package to contain vendor-specific logic.
Summary
I explore 2 solutions to add
db.namespace.In all cases, we extract
db.namespaceonly for well-known DSN patterns to avoid mapping it to incorrect values. Well-known DSN patterns: “postgresql”, “postgres”, “mysql”, “clickhouse”, “sqlserver”, or “mssql”.Solutions:
In this PR, we introduce an additional helper function
DBNamespaceFromDSN, and users have to change their code to benefit of this improvement. New code style looks like:In PR Extract
db.namespacefrom DSN inAttributesFromDSN#608,db.namespaceis parsed in theAttributesFromDSNfunction, no code change for users to benefit of it. Code style remains:PR Summary
Add
DBNamespaceFromDSNhelper and fixAttributesFromDSNbugsDBNamespaceFromDSNto extract thedb.namespaceOTel attributefrom a DSN string, with support for Microsoft sqlserver (database query param) and
an explicit error for oracle (DB_UNIQUE_NAME is not DSN-derivable).
AttributesFromDSNwhen the closing protocolparenthesis is missing and the DSN has no path nor query string,
server.portparsing when the DSN has a query string but no path.