feat: OpenTelemetry instrumentation#1394
Open
joschi wants to merge 20 commits into
Open
Conversation
Emit traces and metrics via the OTel API (no SDK init in library code).
Global providers are used, so there is zero overhead when the host
application has not configured OTel, and automatic telemetry when it has.
Traces
- One parent span per public operation: migrate.up, migrate.down,
migrate.migrate, migrate.steps, migrate.run, migrate.drop, migrate.force
- One child span per individual migration: migrate.run_migration
- Common attributes: db.system, migrate.source, migrate.direction,
migrate.version, migrate.target_version, migrate.identifier
- ErrNoChange and ErrNilVersion do not produce error spans
Metrics
- migrate.migrations.applied (Int64Counter, {migration})
- migrate.migrations.failed (Int64Counter, {migration})
- migrate.migration.run.duration (Float64Histogram, s)
New files
- otel.go tracer/meter factories, otelInstruments struct
- otel_test.go 9 tests using in-memory SDK exporters
Dependencies
- go.opentelemetry.io/otel v1.40.0 (direct)
- go.opentelemetry.io/otel/metric v1.40.0 (direct)
- go.opentelemetry.io/otel/trace v1.40.0 (direct)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add OTel wrapper types for database.Driver and source.Driver that emit child spans for every driver operation, auto-wired into all 4 public constructors so users get driver-level spans with zero code changes. Database driver spans (SpanKind: CLIENT): db.lock, db.unlock, db.run, db.set_version, db.version, db.drop Attributes: db.system, migrate.version, migrate.dirty (SetVersion) Source driver spans (SpanKind: INTERNAL): source.read_up, source.read_down Attributes: migrate.source, migrate.version os.ErrNotExist is treated as a non-error (expected sentinel) Both wrappers expose Unwrap() Driver following the errors.Unwrap convention, allowing test code and wrapping libraries to reach the inner driver without losing type identity. Also fixes a pre-existing context propagation bug in runMigrations: the child context from otelTracer.Start was discarded (assigned to _), causing all database driver spans to attach to the parent operation span instead of the per-migration migrate.run_migration span. Updates: - database/oteldriver.go: new OTelDriver for database.Driver - database/oteldriver_test.go: unit tests for db wrapper - source/oteldriver.go: new OTelDriver for source.Driver - source/oteldriver_test.go: unit tests for source wrapper - migrate.go: fix childCtx propagation; wrap drivers in constructors - migrate_test.go: add sourceStub/databaseStub helpers for Unwrap - otel_test.go: add TestOtelTraceTopology end-to-end topology test - README.md: document driver-level span tables and attributes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use github.com/XSAM/otelsql to add low-level SQL span instrumentation to the clickhouse, cockroachdb, mysql, and sqlite drivers. Each driver's Open() method now wraps the underlying sql.Driver via otelsql.Open(), producing child spans for every SQL operation (Exec, Query, Begin, Commit, Rollback) that automatically nest under the migrate-level db.* spans from the OTelDriver wrapper. The db.system attribute is set per driver: - clickhouse: "clickhouse" - cockroachdb: "cockroachdb" (uses postgres wire protocol) - mysql: "mysql" - sqlite: "sqlite" WithInstance callers who supply a pre-built *sql.DB retain their existing behaviour unchanged; otelsql wrapping applies only when the driver opens its own connection via Open(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add github.com/XSAM/otelsql instrumentation to all database/sql-based
drivers so every SQL operation (queries, execs, transactions) emits a
child span under the migrate-level spans from the OTel wrappers.
Instrumented drivers (otelsql.Open / otelsql.OpenDB):
- firebird (db.system=firebird)
- pgx/v4 (db.system=postgresql)
- pgx/v5 (db.system=postgresql)
- postgres (db.system=postgresql)
- ql (db.system=ql)
- redshift (db.system=redshift)
- snowflake (db.system=snowflake)
- sqlite3 (db.system=sqlite)
- sqlserver (db.system=mssql; both sql.Open and sql.OpenDB MSI paths)
- yugabytedb (db.system=yugabytedb)
Previously instrumented (committed separately):
- clickhouse, cockroachdb, mysql, sqlite
Excluded drivers (not using database/sql):
- cassandra (gocql), mongodb (mongo.Client), neo4j (neo4j.Driver),
rqlite (gorqlite), spanner (cloud.google.com/go/spanner)
sqlcipher is intentionally excluded: go-sqlcipher/v4 does not implement
driver.ExecerContext, causing database/sql to fall back to Prepare+Exec
which only prepares the first statement in a multi-statement query.
This breaks NoTxWrap mode (BEGIN; ...; COMMIT; migrations). The driver
must be kept with plain sql.Open until upstream adds ExecerContext.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
go-sqlcipher/v4 implements the deprecated driver.Execer interface but not driver.ExecerContext. Without ExecerContext, database/sql falls back to Prepare+Exec which only compiles the first statement in a multi-statement query (SQLite's sqlite3_prepare_v2 behaviour), breaking NoTxWrap migrations such as "BEGIN; CREATE TABLE ...; COMMIT;". Add execerContextDriver and execerContextConn adapter types that promote driver.Execer → driver.ExecerContext at the driver level. The wrapped driver is registered once under a private name and then passed to otelsql.Open so SQL-level spans are emitted with db.system="sqlite". All sqlcipher tests including TestNoTxWrap pass. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… tracing Replace cluster.CreateSession() with otelgocql.NewSessionWithTracing() so every gocql query, batch operation, and connection attempt emits an OpenTelemetry span as a child of the surrounding migrate-level spans. The otelgocql observer pattern instruments the cluster before the session is created, meaning the *gocql.Session returned is a standard unmodified session — all tracing is transparent. Note: WithInstance() accepts a pre-existing *gocql.Session and cannot retroactively add observers; callers that construct their own session should set QueryObserver/BatchObserver/ConnectObserver on the cluster before calling cluster.CreateSession() using otelgocql directly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace raw attribute.String("db.system", ...) calls with typed constants
from go.opentelemetry.io/otel/semconv/v1.40.0. Semconv v1.40.0 renamed
the attribute key from db.system to db.system.name and updated several
values to match the canonical OTel semantic conventions spec.
Attribute key change (all drivers):
db.system → db.system.name
Attribute value changes:
firebird: "firebird" → semconv.DBSystemNameFirebirdSQL ("firebirdsql")
sqlserver: "mssql" → semconv.DBSystemNameMicrosoftSQLServer ("microsoft.sql_server")
redshift: "redshift" → semconv.DBSystemNameAWSRedshift ("aws.redshift")
Values unchanged but now constants:
clickhouse → DBSystemNameClickHouse, cockroachdb → DBSystemNameCockroachDB,
mysql → DBSystemNameMySQL, postgresql → DBSystemNamePostgreSQL,
sqlite → DBSystemNameSQLite
No semconv constant defined for: ql, snowflake, yugabytedb — these use
DBSystemNameKey.String("...") to at least use the correct attribute key.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…migration The test was checking for attribute key "db.system" but semconv v1.40.0 renamed it to "db.system.name" (DBSystemNameKey). Update the lookup and the assertion message to match the new key. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Migrate the S3 source driver from github.com/aws/aws-sdk-go (v1) to github.com/aws/aws-sdk-go-v2, then instrument all S3 API calls using go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws. Key changes: - Replace github.com/aws/aws-sdk-go/service/s3/s3iface.S3API with a local s3APIClient interface (ListObjects + GetObject), which enables SDK v2 compatibility and keeps WithInstance testable with a fake - session.NewSession() + s3.New(sess) → awsconfig.LoadDefaultConfig(ctx) + s3.NewFromConfig(cfg) - otelaws.AppendMiddlewares(&cfg.APIOptions) instruments the aws.Config so every S3 operation emits an OTel span automatically - ListObjectsWithContext / GetObjectWithContext → ListObjects / GetObject - aws.StringValue → aws.ToString; s3.Object (v1) → types.Object (v2) - Update s3_test.go fakeS3 to implement the new SDK v2 interface Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Wrap every outgoing HTTP client with otelhttp.NewTransport so that all
API calls made by the source drivers produce child OTel spans.
bitbucket: cl.HttpClient.Transport = otelhttp.NewTransport(http.DefaultTransport)
go-bitbucket uses a plain http.Client; auth headers are
injected per-request, not via a custom transport.
github: no-auth path: replace nil (DefaultClient) with an
otelhttp-wrapped client.
oauth2 path: inject the otelhttp-wrapped base client via
context.WithValue(ctx, oauth2.HTTPClient, base) so the
chain is oauth2.Transport → otelhttp.Transport → DefaultTransport.
github_ee: wrap the whole BasicAuthTransport:
otelhttp.NewTransport(tr) so the chain is
otelhttp.Transport → BasicAuthTransport → http.Transport(TLS).
gitlab: pass &http.Client{Transport: otelhttp.NewTransport(...)}
to gitlab.NewClient instead of nil.
httpfs is not instrumented here: it wraps an http.FileSystem interface
which is a file-system abstraction (e.g. http.Dir, embed.FS) and makes
no outgoing HTTP requests. Transport instrumentation belongs in the
http.FileSystem implementation provided by the caller.
Upgrade otelhttp v0.61.0 → v0.68.0 (aligns with otel v1.43.0).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/mongo/otelmongo and attach otelmongo.NewMonitor() as a CommandMonitor on the client options in Open(): options.Client().ApplyURI(dsn).SetMonitor(otelmongo.NewMonitor()) This causes every MongoDB command (find, insert, update, delete, aggregate, runCommand, …) to emit an OTel span as a child of the surrounding migrate operation span. WithInstance() accepts a pre-built *mongo.Client and cannot retroactively attach a monitor; callers that use WithInstance() directly should set the monitor themselves when constructing the client. Also upgrades go.mongodb.org/mongo-driver v1.7.5 → v1.17.9 (required by the otelmongo contrib package). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc stats handler instrumentation to both Google Cloud drivers. database/spanner: pass option.WithGRPCDialOption(grpc.WithStatsHandler( otelgrpc.NewClientHandler())) to sdb.NewDatabaseAdminClient and spanner.NewClient so all DDL admin and data RPCs emit OTel spans. source/google_cloud_storage: same option injected into storage.NewClient so GCS object list and read operations appear as child spans. Both drivers use the stats handler approach (grpc.WithStatsHandler) rather than the deprecated interceptor API, consistent with otelgrpc guidance. otelgrpc and google.golang.org/grpc promoted from indirect to direct deps. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Three bugs found in code review:
1. otelAttrs() in migrate.go used the pre-semconv-v1.40.0 key "db.system"
while every other file in this branch uses DBSystemNameKey ("db.system.name").
Fix: import semconv and call semconv.DBSystemNameKey.String(...).
2. Migrate.otelMeter was stored in the struct after construction but never
accessed again — the meter is only needed to create otelInstruments.
Fix: remove the otelMeter field; use a local variable in newCommon().
3. migrationRunDuration histogram was recorded (with a ~0 duration) even
when migr.Body == nil, polluting the histogram for schema-only migrations
that have no SQL to execute.
Fix: move the Record call inside the if migr.Body != nil block so the
metric is only emitted when a database Run actually occurred.
Simplification: tracerName and meterName constants in otel.go had identical
values. Replace both with a single instrumentationName constant.
Update otel_test.go to reference instrumentationName and remove the now-
deleted otelMeter field access.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds end-to-end OpenTelemetry observability across migrate operations and driver interactions, leveraging the OTel API so telemetry is automatically emitted when host applications configure global providers.
Changes:
- Introduces core OTel helpers and adds tracing/metrics around public
migrateoperations. - Adds transparent OTel wrappers for
database.Driverandsource.Driver, plus per-driver native instrumentation (otelsql/otelhttp/otelgrpc/otelaws/otelmongo/otelgocql). - Propagates
context.Contextacross driver APIs and updates CLI, tests, and examples accordingly (including aws_s3 SDK v1 → v2).
Reviewed changes
Copilot reviewed 89 out of 90 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| README.md | Documents new OpenTelemetry behavior and usage. |
| otel.go | Adds shared tracer/meter setup and metric instruments. |
| internal/cli/main.go | Passes context into migrate construction/close. |
| internal/cli/commands.go | Passes context through CLI command execution. |
| source/driver.go | Adds context.Context to the source driver interface and Open. |
| source/migration.go | Threads context through Migrations helpers. |
| source/oteldriver.go | Adds OTel spans for ReadUp/ReadDown. |
| source/oteldriver_test.go | Tests source OTel wrapper span emission/attributes. |
| source/testing/testing.go | Updates shared source-driver test helpers for context. |
| source/stub/stub.go | Updates stub source driver for context-based interface. |
| source/stub/stub_test.go | Updates stub source tests for context. |
| source/pkger/pkger.go | Updates pkger source driver for context API. |
| source/pkger/pkger_test.go | Updates pkger tests for context. |
| source/iofs/iofs.go | Updates iofs driver for context API. |
| source/iofs/example_test.go | Updates iofs example to pass context. |
| source/httpfs/driver.go | Updates httpfs driver Open signature for context. |
| source/httpfs/driver_test.go | Updates httpfs tests for context. |
| source/httpfs/partial_driver.go | Updates httpfs partial driver for context API. |
| source/httpfs/partial_driver_test.go | Updates httpfs partial driver tests for context. |
| source/google_cloud_storage/storage.go | Adds ctx propagation and gRPC OTel instrumentation for GCS source. |
| source/google_cloud_storage/storage_test.go | Updates GCS source test for context. |
| source/godoc_vfs/vfs.go | Updates godoc_vfs source driver for context API. |
| source/godoc_vfs/vfs_test.go | Updates godoc_vfs tests for context. |
| source/godoc_vfs/vfs_example_test.go | Updates godoc_vfs example for context. |
| source/go_bindata/go-bindata.go | Updates bindata source driver for context API. |
| source/go_bindata/go-bindata_test.go | Updates bindata tests for context. |
| source/github/github.go | Adds ctx propagation and otelhttp-instrumented HTTP client. |
| source/github/github_test.go | Updates GitHub source tests for context. |
| source/github_ee/github_ee.go | Adds ctx propagation and otelhttp instrumentation. |
| source/github_ee/github_ee_test.go | Updates GitHub EE source tests for context. |
| source/gitlab/gitlab.go | Adds ctx propagation and otelhttp instrumentation. |
| source/gitlab/gitlab_test.go | Updates GitLab source tests for context. |
| source/bitbucket/bitbucket.go | Adds ctx propagation and otelhttp instrumentation. |
| source/bitbucket/bitbucket_test.go | Updates Bitbucket source tests for context. |
| source/aws_s3/s3.go | Migrates aws_s3 source to AWS SDK v2 + otelaws + ctx propagation. |
| source/aws_s3/s3_test.go | Updates aws_s3 tests for SDK v2 and context. |
| database/driver.go | Adds context.Context to the database driver interface and Open. |
| database/driver_test.go | Updates database driver tests for context. |
| database/oteldriver.go | Adds OTel CLIENT spans for database driver operations. |
| database/oteldriver_test.go | Tests database OTel wrapper span emission/attributes. |
| database/testing/testing.go | Updates shared database-driver test helpers for context. |
| database/testing/migrate_testing.go | Updates migrate-through-db-driver tests for context. |
| database/stub/stub.go | Updates stub database driver for context API. |
| database/stub/stub_test.go | Updates stub database tests for context. |
| database/cassandra/cassandra.go | Adds ctx propagation and otelgocql instrumentation. |
| database/cassandra/cassandra_test.go | Updates Cassandra DB tests for context. |
| database/clickhouse/clickhouse.go | Adds ctx propagation and otelsql instrumentation. |
| database/clickhouse/clickhouse_test.go | Updates ClickHouse DB tests for context. |
| database/cockroachdb/cockroachdb_test.go | Updates CockroachDB DB tests for context. |
| database/firebird/firebird.go | Adds ctx propagation and otelsql instrumentation. |
| database/firebird/firebird_test.go | Updates Firebird DB tests for context. |
| database/mongodb/mongodb.go | Adds ctx propagation and otelmongo instrumentation. |
| database/mongodb/mongodb_test.go | Updates MongoDB DB tests for context. |
| database/mysql/mysql.go | Adds ctx propagation and otelsql instrumentation. |
| database/mysql/mysql_test.go | Updates MySQL DB tests for context. |
| database/neo4j/neo4j.go | Adds ctx propagation (no per-driver OTel due to driver constraints). |
| database/neo4j/neo4j_test.go | Updates Neo4j DB tests for context. |
| database/ql/ql.go | Adds ctx propagation and otelsql instrumentation. |
| database/ql/ql_test.go | Updates ql DB tests for context. |
| database/redshift/redshift.go | Adds ctx propagation and otelsql instrumentation. |
| database/rqlite/rqlite.go | Adds ctx propagation to rqlite DB driver APIs. |
| database/rqlite/rqlite_test.go | Updates rqlite DB tests for context. |
| database/snowflake/snowflake.go | Adds ctx propagation and otelsql instrumentation. |
| database/spanner/spanner.go | Adds ctx propagation and otelgrpc instrumentation. |
| database/spanner/spanner_test.go | Updates Spanner DB tests for context. |
| database/sqlcipher/sqlcipher_test.go | Updates sqlcipher DB tests for context. |
| database/sqlite/sqlite.go | Adds ctx propagation and otelsql instrumentation. |
| database/sqlite/sqlite_test.go | Updates sqlite DB tests for context. |
| database/sqlite3/sqlite3.go | Adds ctx propagation and otelsql instrumentation. |
| database/sqlite3/sqlite3_test.go | Updates sqlite3 DB tests for context. |
| database/sqlserver/sqlserver_test.go | Updates SQLServer DB tests for context. |
| database/yugabytedb/yugabytedb_test.go | Updates YugabyteDB DB tests for context. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…tibilities - github.com/aws/aws-sdk-go-v2/feature/s3/manager: v1.11.33 -> v1.22.15 - github.com/snowflakedb/gosnowflake: v1.6.19 -> v1.19.1 Both packages used AWS SDK v2 fields (ContentLength, BucketKeyEnabled, PartNumber) that changed from value types to pointer types in newer SDK versions, causing build failures. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- database/mysql: use PingContext(ctx) instead of Ping() in WithInstance so cancellations and timeouts propagate consistently - source/google_cloud_storage: store *storage.Client in struct, close it in Close() and on loadMigrations error to prevent resource leaks - database/spanner: return error instead of log.Fatal when NewClient fails; close adminClient on error to avoid resource leak; remove unused log import - README: fix attribute key db.system -> db.system.name (semconv v1.40) - README: add context import and pass ctx to migrate.New in OTel example so the snippet compiles with the updated API Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The go directive was unintentionally bumped to 1.25.0 as a side-effect
of adding OTel dependencies. Root causes identified and resolved:
- github.com/XSAM/otelsql v0.42.0 → v0.41.0 (required go 1.25)
- go.opentelemetry.io/otel and related packages v1.43.0 → v1.40.0
(v1.42.0+ requires go 1.25)
- go.opentelemetry.io/contrib/instrumentation/* v0.68.0 → v0.64.0
(v0.65.0+ requires go 1.25)
- semconv import path updated from v1.40.0 → v1.39.0 (semconv/v1.40.0
sub-package only exists in otel module v1.43.0+; v1.39.0 provides
identical db.system.name attribute key)
- golang.org/x/{net,sync,sys,term,text} pinned to last Go 1.24
compatible versions (v0.50.0, v0.19.0, v0.41.0, v0.40.0, v0.34.0)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 89 out of 90 changed files in this pull request and generated 9 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- otel_test.go: extract span name string literals into constants (spanNameUp, spanNameDown, spanNameRunMigration) to fix goconst - database/mongodb/mongodb_test.go: replace deprecated DecodeBytes() with Raw() (SA1019/staticcheck) - database/sqlcipher/sqlcipher.go: add nolint:staticcheck on intentional driver.Execer usages; the deprecated interface is required because go-sqlcipher/v4 does not implement ExecerContext - database/oteldriver_test.go: remove unused *dStub.Stub second return value from newTestDriver and update all call sites (unparam) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- README.md: fix db.system → db.system.name in database span table - otel.go: call otel.Handle(err) on instrument creation errors instead of silently discarding them (doc comment already promised this) - migrate.go: use attribute.Int64 for uint version fields to avoid int overflow on 32-bit platforms - migrate.go: sanitize database.Error in otelSpanSetError to avoid leaking migration SQL into trace span status descriptions - database/oteldriver.go: same SQL-leak fix in endSpan; add errors import - source/oteldriver.go: use attribute.Int64 for uint version fields - source/oteldriver_test.go: assert span.Status().Code != codes.Error directly rather than comparing full sdktrace.Status struct - source/pkger/pkger.go: fix import grouping (stdlib before third-party) - source/google_cloud_storage/storage.go: merge context into stdlib group Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds end-to-end OpenTelemetry observability to
golang-migrate. Zero breaking changes — all instrumentation is automatic when a global SDK provider is configured.Note
This PR is based on #1132 and requires the changes from that PR to work.
What's instrumented
Core (
migrate.go)Every public entry point emits an INTERNAL span with shared attributes (
db.system.name,migrate.source):migrate.up/migrate.downmigrate.directionmigrate.migrate/migrate.forcemigrate.versionmigrate.stepsmigrate.direction,migrate.stepsmigrate.runmigrate.run_migrationmigrate.version,migrate.target_version,migrate.direction,migrate.identifiermigrate.dropMetrics (OpenTelemetry metric instruments):
migrate.migrations.appliedInt64Counter{migration}migrate.migrations.failedInt64Counter{migration}migrate.migration.run.durationFloat64HistogramsDatabase drivers — transparent wrapper (
database/oteldriver.go)database.NewOTelDriverwraps anydatabase.Driverand emits CLIENT spans for every operation (db.lock,db.unlock,db.run,db.set_version,db.version,db.drop). Applied automatically inside all fourNew*constructors.Source drivers — transparent wrapper (
source/oteldriver.go)source.NewOTelDriverwraps anysource.Driverand emits INTERNAL spans forsource.read_upandsource.read_down. Applied automatically in all constructors.os.ErrNotExistis not treated as an error (expected "no migration here" signal).Per-driver instrumentation
Library-native OTel instrumentation using the appropriate contrib package:
otelsqlotelsql.Openwraps the registered SQL driverotelsqlExecerContextadapter (go-sqlcipher/v4 only implements deprecateddriver.Execer)otelgocqlotelgocql.NewSessionWithTracingotelmongooptions.Client().SetMonitor(otelmongo.NewMonitor())otelgrpcoption.WithGRPCDialOption(grpc.WithStatsHandler(otelgrpc.NewClientHandler()))otelawsotelaws.AppendMiddlewares(&cfg.APIOptions)— also migrates aws_s3 from SDK v1 → v2otelhttpotelhttp.NewTransportinjected as the HTTP client transportotelgrpcNot instrumented:
neo4j(v1 driver has no OTel API; v5 migration is a separate effort),rqlite(gorqlite's HTTP client is unexported — no injection point).Attributes
Attribute keys follow semconv v1.39.0 (
db.system.nameper the rename fromdb.system). Numeric version attributes (migrate.version,migrate.target_version) are recorded asInt64to avoid overflow on 32-bit platforms.Error handling in spans
When a span is set to error status,
database.Errorvalues are sanitized: only the underlyingOrigErris used as the span status description, preventing migration SQL/query excerpts from leaking into traces. The full error (including query context) is still attached viaRecordErrorfor diagnostic use.Trace topology
Dependency changes
go.opentelemetry.io/otel+ SDK (v1.40.0),github.com/XSAM/otelsql(v0.41.0),otelgocql,otelmongo,otelaws,otelhttp,otelgrpcgo.mongodb.org/mongo-driverv1.7.5 → v1.17.9,aws-sdk-go-v2v1.xotelgrpc,google.golang.org/grpc,google.golang.org/api/optionpromoted from indirect to direct