OpenTelemetry instrumentation for database/sql



Go Report Card Documentation

It is an OpenTelemetry instrumentation for Golang database/sql, a port from

It can only instrument traces for the present.


$ go get


Feature Description Status Reason
Rows, RowsClose If set to true, will enable the creation of spans on corresponding calls. Enabled by default We need to know the status of Rows
Query If set to true, will enable recording of sql queries in spans. Enabled by default db.statement will need this, which is a required attribute.
Ping If set to true, will enable the creation of spans on Ping requests. Implemented Ping has context argument, but it might no needs to record.
RowsNext If set to true, will enable the creation of events on corresponding calls. This can result in many events. Implemented It provides more visibility.
DisableErrSkip If set to true, will suppress driver.ErrSkip errors in spans. Implemented ErrSkip error might annoying
RowsAffected, LastInsertID If set to true, will enable the creation of spans on RowsAffected/LastInsertId calls. Dropped Don't know its use cases. We might add this later based on the users' feedback.
QueryParams If set to true, will enable recording of parameters used with parametrized queries. Dropped It will cause high cardinality values and security problems.
AllowRoot If set to true, will allow ocsql to create root spans in absence of existing spans or even context. Dropped I don't think traces data have meaning without context.


See example

Why port this?

Based on this comment, OpenTelemetry SIG team like to see broader usage and community consensus on an approach before they commit to the level of support that would be required of a package in contrib. But it is painful for users without a stable version, and they have to use replacement in go.mod to use this instrumentation.

Therefore, I host this module independently for convenience and make improvements based on users' feedback.

  • Allow for greater configurability

    Allow for greater configurability

    Problem Statement

    Hi! Thanks for this great solution. Current issue is sheer volume of spans for requests that result in many DB queries. Here is a small fraction of spans emitted by a traced request, for example.

    Screen Shot 2022-01-02 at 12 49 14 PM

    Concretely, my issues are

    1. I've set DisableSkipErr to true, however the spans representing the skipped operations (in this case, the sql.conn.Query spans) are still recorded. Given that the operation is skipped, I don't see much use for these spans and would love an option to omit them from tracing entirely

    2. I don't want the sql.conn.reset_session spans. Would be great to have an option to omit these.

    3. I am debating whether or not I find the sql.conn.prepare spans useful. I think I would like an option to omit them as well.

    In short, I really just want a single span per query/statement, in this case it would be the sql.stmt.query spans. I know many others may want finer grained detail, but in my case the utility of this library is often just to see the queries themselves as well as the timing -- the other spans are more useful in cases where my DB is having issues, in which case I would likely just roll out a quick config change to enable everything and begin debugging there.

    Proposed Solution

    Additional config values to

    • OmitSkipErr value to omit a span with a skipped error completely (if DisableSkipErr is also set to `true

    • OmitResetSession to omit sql.conn.reset_session spans

    • OmitConnPrepare to omit sql.conn.prepare spans.


    the alternative would be to do nothing and not give fined grained control over what's traced.

    Prior Art

    existing config values such as Ping and DisableErrSkip

    opened by irl-segfault 10
  • Spans named after corresponding methods make graph too busy

    Spans named after corresponding methods make graph too busy

    I am using otelsql to send traces to AWS X-RAY through opentelemetry. In the X-RAY console I see seperate nodes for each methods. For example I see seperate nodes for sql.conn.reset_session, sql.conn.prepare, sql.conn.reset_session, sql.stmt.query, and sql.rows. What I am looking after is for X-RAY to create one node with a given name that has multiple spans. But when using different names for each method the graph became too busy.

    opened by mostafafarzaneh 6
  • Feature Request: sqlcommenter support?

    Feature Request: sqlcommenter support?

    I read that Sqlcommenter merged into OpenTelemetry.

    I have database connection code that I have already instrumented with

    	wrappedDriverName, err := otelsql.Register(

    and I am wondering if adding sqlcomment is redundant or if it would provide additional value?

    opened by StevenACoffman 5
  • Database connection contention spans

    Database connection contention spans

    Problem Statement

    We're conducting a performance testing and we saw that most of the time is consumed in between the API call and the actual query.

    We don't know yet where the problem is but we have two suspicions:

    1. The database is rate limiting or taking more time to connect due to this contention.
    2. There is a limit in the database/sql and the pool is locking the current query until another connection is released.

    Proposed Solution

    Add more spans to the driver so that it also registers traces for the connection opening times as well as internal locking times. I don't know if it's even possible.


    Logging :D

    opened by glerchundi 5
  • Add an option to tag spans with SQL query args

    Add an option to tag spans with SQL query args

    Hi @XSAM,

    This is a follow-up to, though were you not interested in merging it, I'll be happy to untangle the git history from those other changes.

    This introduces an additional configuration option that enables to tag the SQL queries with their values, so anyone looking at the traces can also see the values.

    Here is a screenshot of what it looks like: (see db.args.$1)


    If that's good for you, I'll also update the README 🙏

    Requires #115 to be merged first, albeit the changes are not really related, but as we did it this way, I'd rather check with you before reworking the PR if that's really needed.

    opened by jhchabran 4
  • toggleable tracing via SpanMethodOptions

    toggleable tracing via SpanMethodOptions

    ~~Hi, this is a proposal to the issue

    this PR allows toggling database operations. this leaves on instrumentation config the decision of choosing which operation/method to trace. this is an initial implementation and serves as presentation of a possible approach to the functionality.

    By default, operations must be explicitly configured

    If you agree with the solution, I would move forward to add tests and implement the check for the remaining methods. Any suggestion is welcome.


    func main() {
    	driverName, err := otelsql.Register("postgres",
    			DisableErrSkip: true,
    	if err != nil {
    opened by wesleyvicthor 4
  • Add WithContextualAttributes option

    Add WithContextualAttributes option

    This option enables dynamic attribute generation from a context. During query execution, the context is passed to each of these functions and the resulting attributes are attached to the span.

    opened by alexgenco 4
  • sql.conn.reset_session


    Hey, I am using this in my application. Nice work! An issue is, I am seeing constantly a sql.conn.reset_session span. Not sure what it is, but it seems to be happening on each Ping? Very spammy. Should this span be disabled when Ping's are disabled?

    opened by DejeroDaniel 4
  • Access to the underlying connection when using `WrapDriver`

    Access to the underlying connection when using `WrapDriver`

    Problem Statement

    database/sql.Conn#Raw() allows us to get the underlying driver's connection. We use this in some existing code to get a *pgx.Conn for CopyFrom functionality (via pgx/v4/stdlib.Conn#Conn()).

    However, when using otelsql.WrapDriver, Raw() yields an *otelsql.otConn instead of a *pgx/v4/stdlib.Conn. That has a field Conn, set to the *pgx/v4/stdlib.Conn, but since otConn isn't exported, I can't do a type assertion on it to get the underlying connection - if I want to do CopyFrom, I have to resort to reflect, which I'd rather not do.

    Going to the underlying connection bypasses telemetry for that specific call, which is non-optimal, but being able to introduce observability into the rest of the application would still be a win :sweat_smile:

    Proposed Solution

    Add this to conn.go:

    func (o *otConn) Conn() driver.Conn {
        return o.Conn

    (well, sort of, the Conn field would need to be renamed).

    I can then declare an interface to get it instead of using reflect:

    type Conner interface {
        Conn() driver.Conn
    conn.Raw(func(driverConn interface{}) error {
    	if c, ok := driverConn.(Conner) {
    		pc := c.Conn().(*stdlib_pgx.Conn).Conn() // yuck, but no reflect
    		fmt.Printf("%T\n", pc)


    There's a few possiblities; ideally, that Raw call would never return the otConn, but I don't know if that's possible.

    We could export the otConn type so type assertions are possible.

    We could implement Raw on the otConn in some way?

    We could make CopyFrom available in some other way. It's actually *pgx.Tx#CopyFrom that I'm after in the end, but I saw no reasonable way to go from the otTx to a *pgx.Tx

    Prior Art


    Additional Context

    This is actually a conversion from instrumentedsql to otelsql. The former had the same issue, but we just forked it internally and made a commit that exported the connection type. I'd rather not do that again with an active project :sweat_smile: .

    opened by nick-kentik 3
  • Opening lots of connections uses up all available slots

    Opening lots of connections uses up all available slots


    {"error":"failed to register otel driver: unable to register driver, all slots have been taken","level":"warning","msg":"Failed indexing, retrying in 30s","time":"2022-03-23T11:38:21Z"}

    We have a service that opens a number of connections inside a backoff, correctly closing a connection before opening a new one. However, the stdlib doesn't offer a Unregister method for an SQL driver, which means each time we are opening a new connection with otelsql we are taking up a new slot. Eventually we run out without restarting the service. looks to be exactly what I'm after, specifically...

    OpenDB opens a database using a Connector, allowing drivers to bypass a string based data source name.


    • OS: k8s
    • Architecture: x86
    • Go Version: [e.g. 1.18]
    • otelsql version: 1.12

    Steps To Reproduce

    I can create an example if helpful, but it's effectively a for loop that is greater than >maxDriverSlot where a connection is opened & then closed.

    Expected behaviour

    otelsql to implement the Connector driver so that OpenDB can be used.

    opened by rcrowe 3
  • SpanOption DisableQuery

    SpanOption DisableQuery

    Hi, this PR attempts to cover the DisableQuery functionality, this time as opposed #25, it makes only the attribute not set.

    It tries to cover the expected functionality by #22

    opened by wesleyvicthor 3
  • Error when using mssql and table-valued parameters

    Error when using mssql and table-valued parameters

    Hello! Thanks for all the great work on otelsql, it's been a pleasure to use.


    I'm getting the following error when using and mssql.TVP parameter:

    sql: converting argument with name "TVP" type: unsupported type mssql.TVP, a struct

    The problem is that mssql doesn't implement CheckNamedValue(*NamedValue) error for Stmt, only for Conn. otelsql on the other hand, implements it on both Stmt and Conn, but then returns driver.ErrSkip in otStmt.CheckNamedValue if the underlying Stmt doesn't implement CheckNamedValue which causes the issue.

    In my opinion it would be more fair wrapping if otStmt.CheckNamedValue falls back to the underlying Conn.CheckNamedValue when Stmt.CheckNamedValue is not implemented. But then the otStmt needs to have the Conn as a field.

    I'm happy to submit a PR is it makes sense.

    opened by glebteterin 1
  • Rely solely on the trace provider to get the tracer

    Rely solely on the trace provider to get the tracer

    Hi! We've recently been using in our codebase otelsql to modernise some old SQL tracing code and it's been working well :)

    One thing that got in the way is that otelsql caches the tracer when it's initialised, which creates for a us a chicken and egg problem: our tracing code requires reading some setting from the database, but setting up the database driver requires tracing, leading otelsql to use the wrong tracer if we didn't change anything.

    The present PR instead relies fully on the otel code to handle caching the tracer, and simply calls the tracing provider whenever it needs one.

    I think this class of problem may be common in the context of legacy apps whose init layer is a bit more complicated than usual.

    We have ran this code in production for a few weeks now, without observing any issue. Please tell me if you think there is a better way of handling this or if I can modify the code more to your liking.

    opened by jhchabran 4
  • IN Queries Failing w/ OTEL Configured

    IN Queries Failing w/ OTEL Configured

    Not sure if this is a bug or I'm doing something wrong here...

    When I add tracing like so:

    driver, err := otelsql.Register("postgres", "postgres")
    if err != nil {
       return nil, fmt.Errorf("registering Postgres driver for instrumentation: %v", err)
    pgConnection, err := sqlx.Connect(driver, pgOpts)

    I'm getting errors only with IN queries that I construct like so:

    query, args, err := sqlx.In(getTeamsForEnvsQuery, envIds)
    if err != nil {
        return nil, errors.Wrap(err, "error creating 'IN' query")
    var results []TeamEnvResult
    if err = t.SelectContext(ctx, &results, t.Rebind(query), args...); err != nil {
        return nil, errors.Wrap(err, "error querying team table for teamIds")

    where getTeamsForEnvsQuery is:

    SELECT as "environmentId", p."teamId"
    FROM product p
    JOIN environment e ON e."productId" =
    WHERE IN (?)

    (using as my postgres client)

    When I forget about otelsql and just register the driver like so i get no errors and everything runs smoothly:

    pgConnection, err := sqlx.Connect("postgres" /*driver name*/, pgOpts)

    Am I doing something wrong here? Or is this an issue?

    opened by mnotti 4
  • v0.17.1(Dec 13, 2022)

  • v0.17.0(Oct 21, 2022)

    0.17.0 - 2022-10-21

    ⚠️ Notice ⚠️

    The minimum supported Go version is 1.18.


    • Go 1.19 to supported versions. (#118)
    • WithAttributesGetter option provides additional attributes on spans creation. (#125)


    • Upgrade OTel to version 1.10.0. (#119)

    • Upgrade OTel to version 1.11.0/0.32.3. (#122)

    • Upgrade OTel to version 1.11.1/0.33.0. (#126)

      This OTel release contains a feature that the exporter now adds a unit suffix to metric names. This can be disabled using the WithoutUnits() option added to that package.


    • Support for Go 1.17. Support is now only for Go 1.18 and Go 1.19. (#123)
    Source code(tar.gz)
    Source code(zip)
  • v0.16.0(Aug 25, 2022)

    0.16.0 - 2022-08-25


    • WithSQLCommenter option to enable context propagation for database by injecting a comment into SQL statements. (#112)

      This is an experimental feature and may be changed or removed in a later release.


    • Upgrade OTel to version 1.9.0. (#113)
    Source code(tar.gz)
    Source code(zip)
  • v0.15.0(Jul 11, 2022)

    0.15.0 - 2022-07-11

    ⚠️ Notice ⚠️

    The minimum supported Go version is 1.17.

    This update contains a breaking change of the removal of SpanOptions.AllowRoot.


    • SpanOptions to suppress creation of spans. (#87, #102)

      • OmitConnResetSession
      • OmitConnPrepare
      • OmitConnQuery
      • OmitRows
      • OmitConnectorConnect
    • Function Raw to otConn to return the underlying driver connection. (#100)


    • Upgrade OTel to v1.7.0. (#91)
    • Upgrade OTel to version 1.8.0/0.31.0. (#105)


    • Support for Go 1.16. Support is now only for Go 1.17 and Go 1.18. (#99)
    • SpanOptions.AllowRoot. (#101)
    Source code(tar.gz)
    Source code(zip)
  • v0.14.1(Apr 7, 2022)

  • v0.14.0(Apr 5, 2022)

    0.14.0 - 2022-04-05

    ⚠️ Notice ⚠️

    This update is a breaking change of Open, OpenDB, Register, WrapDriver and RegisterDBStatsMetrics methods. Code instrumented with these methods will need to be modified.


    • Remove dbSystem parameter from all exported functions. (#80)
    Source code(tar.gz)
    Source code(zip)
  • v0.13.0(Apr 4, 2022)

    0.13.0 - 2022-04-04


    • Add metrics support. (#74)
    • Add Open and OpenDB methods to instrument database/sql. (#77)


    • Upgrade OTel to v1.6.0/v0.28.0. (#74)
    • Upgrade OTel to v1.6.1. (#76)
    Source code(tar.gz)
    Source code(zip)
  • v0.12.0(Mar 18, 2022)

    0.12.0 - 2022-03-18


    • Covering connector's connect method with span. (#66)
    • Add Go 1.18 to supported versions. (#69)


    • Upgrade OTel to v1.5.0. (#67)
    Source code(tar.gz)
    Source code(zip)
  • v0.11.0(Feb 22, 2022)

  • v0.10.0(Dec 13, 2021)

  • v0.9.0(Nov 5, 2021)

  • v0.8.0(Oct 13, 2021)

  • v0.7.0(Sep 21, 2021)

  • v0.6.0(Sep 6, 2021)

    0.6.0 - 2021-09-06


    • Added RecordError to SpanOption. (#23)
    • Added DisableQuery to SpanOption. (#26)


    • Upgrade OTel to v1.0.0-RC3. (#29)
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Aug 2, 2021)

  • v0.4.0(Jun 25, 2021)

  • v0.3.0(May 13, 2021)


    • Add AllowRoot option to prevent backward incompatible. (#13)


    • Upgrade to v0.20.0 of (#8)
    • otelsql will not create root spans in absence of existing spans by default. (#13)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(Mar 28, 2021)

  • v0.2.0(Mar 24, 2021)

  • v0.1.0(Mar 23, 2021)

    This is the first release of otelsql. It contains instrumentation for trace and depends on OTel 0.18.0.


    • Instrumentation for trace.
    • CI files.
    • Example code for a basic usage.
    • Apache-2.0 license.
    Source code(tar.gz)
    Source code(zip)
Sam Xie
Sam Xie
OpenTelemetry instrumentations for Go

OpenTelemetry instrumentations for Go Instrumentation Package Metrics Traces database/sql ✔️ ✔️ GORM ✔️ ✔️ sqlx ✔️ ✔️ logrus ✔️ Zap ✔️ Contributing To

Uptrace 139 Dec 26, 2022
Distributed tracing using OpenTelemetry and ClickHouse

Distributed tracing backend using OpenTelemetry and ClickHouse Uptrace is a dist

Uptrace 1.3k Jan 2, 2023
write APIs using direct SQL queries with no hassle, let's rethink about SQL

SQLer SQL-er is a tiny portable server enables you to write APIs using SQL query to be executed when anyone hits it, also it enables you to define val

Mohammed Al Ashaal 2k Jan 7, 2023
Parses a file and associate SQL queries to a map. Useful for separating SQL from code logic

goyesql This package is based on nleof/goyesql but is not compatible with it any more. This package introduces support for arbitrary tag types and cha

null 0 Oct 20, 2021
Go-sql-reader - Go utility to read the externalised sql with predefined tags

go-sql-reader go utility to read the externalised sql with predefined tags Usage

null 0 Jan 25, 2022
sqlx is a library which provides a set of extensions on go's standard database/sql library

sqlx is a library which provides a set of extensions on go's standard database/sql library. The sqlx versions of sql.DB, sql.TX, sql.Stmt, et al. all leave the underlying interfaces untouched, so that their interfaces are a superset on the standard ones. This makes it relatively painless to integrate existing codebases using database/sql with sqlx.

Jason Moiron 13.1k Jan 7, 2023
Dumpling is a fast, easy-to-use tool written by Go for dumping data from the database(MySQL, TiDB...) to local/cloud(S3, GCP...) in multifarious formats(SQL, CSV...).

?? Dumpling Dumpling is a tool and a Go library for creating SQL dump from a MySQL-compatible database. It is intended to replace mysqldump and mydump

PingCAP 267 Nov 9, 2022
Additions to Go's database/sql for super fast performance and convenience.

gocraft/dbr (database records) gocraft/dbr provides additions to Go's database/sql for super fast performance and convenience. $ go get -u

null 1.7k Jan 1, 2023
Interceptors for database/sql

sqlmw sqlmw provides an absurdly simple API that allows a caller to wrap a database/sql driver with middleware. This provides an abstraction similar t

null 434 Dec 27, 2022
Scan database/sql rows directly to structs, slices, and primitive types

Scan Scan standard lib database rows directly to structs or slices. For the most comprehensive and up-to-date docs see the godoc Examples Multiple Row

Brett Jones 331 Dec 28, 2022
Prometheus metrics for Go database/sql via VictoriaMetrics/metrics

sqlmetrics Prometheus metrics for Go database/sql via VictoriaMetrics/metrics Features Simple API. Easy to integrate. Install Go version 1.16+ go get

cristaltech 22 Dec 16, 2022
Attach hooks to any database/sql driver

sqlhooks Attach hooks to any database/sql driver. The purpose of sqlhooks is to provide a way to instrument your sql statements, making really easy to

Gustavo Chaín 599 Jan 6, 2023
A go Library for scan database/sql rows to struct、slice、other types. And it support multiple databases connection management

ploto A go Library for scan database/sql rows to struct、slice、other types. And it support multiple databases connection management It's not an ORM. wo

solar 3 Nov 3, 2022
Go database/sql

Go database/sql 源码阅读 基于 release-branch.go1.17 Benchmark 连接池测试 简单介绍 database/sql 库,包括结构体和主要的方法 介绍主要函数的调用逻辑 用OneNote看源码:Link 介绍最近几个版本的commit changes 结合实

x509 0 Dec 18, 2021
Sqlbench runs benchmarks on an SQL database

sqlbench runs benchmarks on an SQL database. Right now this works for PostgreSQL

Martin Tournoij 2 Oct 13, 2022
Lightweight SQL database written in Go for prototyping and playing with text (CSV, JSON) data

gopicosql Lightweight SQL database written in Go for prototyping and playing wit

null 2 Jul 27, 2022
BigQuery database/sql golang driver

BigQuery SQL Driver This library is compatible with Go 1.17+ Please refer to CHA

Viant, Inc 7 Dec 7, 2022
A minimal, single-table No-SQL database.

SimpleDB SimpleDB is a very basic No-SQL database format for long-term data storage in Golang. It is WIP, has a LOT of drawbacks, and definitely is no

Konnor Klashinsky 0 Jan 16, 2022
A go package to add support for data at rest encryption if you are using the database/sql.

go-lockset A go package to add support for data at rest encryption if you are using the database/sql to access your database. Installation In your Gol

Bartlomiej Mika 0 Jan 30, 2022