Skip to content

fix(pkg/instrumentation/databasesql): traces drop server.address for standard DSN formats #470

Open
alaotach wants to merge 5 commits into
open-telemetry:mainfrom
alaotach:fix/databasesql-dsn-parsing
Open

fix(pkg/instrumentation/databasesql): traces drop server.address for standard DSN formats #470
alaotach wants to merge 5 commits into
open-telemetry:mainfrom
alaotach:fix/databasesql-dsn-parsing

Conversation

@alaotach
Copy link
Copy Markdown

@alaotach alaotach commented May 6, 2026

The DSN parsing in parse.go didn't handle several standard connection string formats causing spans to silently lose server.address, port, and namespace attributes for perfectly valid DSNs

What changed:

  • parsePostgres() - added fallback for libpq key value format (host=localhost port=5432 dbname=mydb). Previously only postgres:// URL scheme worked. Both pq and pgx use this format heavily.
  • parseMySQL() - added fallback to localhost:3306 when no quoted address is present. go-sql-driver/mysql allows user:pass@/dbname and treats it as local, but the parser was returning "invalid MySQL DSN" for these.
  • ParseDbName() - added regex based extraction for dbname= and Database= key value patterns before falling back to the / search. sql server and libpq style conn strings were returning empty db name.

Integration tests added for all three cases following existing test structure. Test app driver registration extended to cover the aliases these tests need (mysql, postgres, sqlserver etc).
Before this, any app using these DSN formats would get server.address="unknown" and empty namespace in their traces which defeats the point of the instrumentation.

closes #460

@alaotach alaotach requested a review from a team as a code owner May 6, 2026 19:53
@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla Bot commented May 6, 2026

CLA Signed
The committers listed above are authorized under a signed CLA.

  • ✅ login: alaotach / name: alaotach (0642a68)

@github-actions github-actions Bot added the scope:fix A bug that is being fixed label May 6, 2026
@txabman42 txabman42 requested a review from Copilot May 6, 2026 20:42
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This pull request improves pkg/instrumentation/databasesql DSN parsing so spans retain server.address, server.port, and db.namespace for common, valid DSN formats that previously failed parsing and caused attribute fallback to "unknown" / empty namespace.

Changes:

  • Extend Postgres parsing to support libpq key/value DSNs (host=... port=... dbname=...) with a default port fallback.
  • Extend MySQL parsing to treat DSNs without an explicit address (user:pass@/dbname and tcp()/...) as localhost:3306.
  • Enhance db name extraction to detect dbname= / database= key/value patterns before falling back to path-based parsing, and add integration tests + test driver aliases to cover these cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
pkg/instrumentation/databasesql/parse.go Adds key/value dbname parsing and expands Postgres/MySQL DSN parsing fallbacks to preserve endpoint + namespace attributes.
test/integration/db_client_test.go Adds integration test coverage for Postgres libpq DSNs, MySQL default-host DSNs, and SQL Server Database= key DSNs.
test/apps/dbclient/main.go Registers additional driver-name aliases in the integration test app so the new DSN parsing paths are exercised.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +87 to +96
if !strings.Contains(url, "://") {
host, port, ok := parseConnectionStringPair(url, []string{"host"})
if !ok || host == "" {
return "", errors.New("invalid Postgres DSN")
}
if port == "" {
port = "5432"
}
return host + ":" + port, nil
}
@codecov
Copy link
Copy Markdown

codecov Bot commented May 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 62.73%. Comparing base (6e35495) to head (85ec3b9).

Additional details and impacted files
@@            Coverage Diff            @@
##           main     #470       +/-   ##
=========================================
+ Coverage      0   62.73%   +62.73%     
=========================================
  Files         0       62       +62     
  Lines         0     4760     +4760     
=========================================
+ Hits          0     2986     +2986     
- Misses        0     1529     +1529     
- Partials      0      245      +245     
Flag Coverage Δ
pkg 62.73% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

alaotach and others added 2 commits May 7, 2026 12:09
Use JoinHostPort for libpq key/value hosts and add IPv6 DSN coverage.

Reuse the dbclient build across DB integration tests to cut runtime.
@alaotach
Copy link
Copy Markdown
Author

alaotach commented May 7, 2026

hey I’ve fixed the issues and the libpq host parsing problem, the pr should be safe to merge.

please take a look and let me know if you want any changes

@y1yang0 y1yang0 requested a review from NameHaibinZhang May 7, 2026 06:59
@y1yang0
Copy link
Copy Markdown
Contributor

y1yang0 commented May 7, 2026

@NameHaibinZhang Please help review this when you have time. Thanks.

"strings"
)

var dbNamePattern = regexp.MustCompile(`(?i)(^|[\s;?&])(?:dbname|database)\s*=\s*('([^']*)'|"([^"]*)"|[^;\s&]+)`)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This regex is too tricky, e.g. from user:pass@tcp(host)/mydb?timeout=30s&database=other matches database=other

what about making parseDSN return also the dbname?


func init() {
sql.Register("testdb", &testDriver{})
sql.Register("mysql", &testDriver{})
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What's the value of these new registrations in the test?


var dbNamePattern = regexp.MustCompile(`(?i)(^|[\s;?&])(?:dbname|database)\s*=\s*('([^']*)'|"([^"]*)"|[^;\s&]+)`)

func ParseDbName(dsn string) string {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we add some unit tests to cover non-happy path scenarios?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope:fix A bug that is being fixed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(pkg/instrumentation/databasesql): traces drop server.address for standard DSN formats

4 participants