otelsql Documentation

repository·main·Indexed 19 days ago

https://github.com/xsam/otelsql

An OpenTelemetry instrumentation library for Go's database/sql package. otelsql provides traces and metrics for database operations and connection statistics, including support for SQL commenting to inject trace context into queries. It offers flexible configuration via SpanOptions, custom SpanNameFormatter, and AttributesGetter to control observability overhead and metadata.

Tokens
9K
Snippets
24
Records
38
Agent score
64%

What's inside otelsql

  1. How otelsql handles error type attribution

    main

    When database operations fail, otelsql automatically populates the error.type attribute to assist in debugging. The attribution logic follows these rules:

    1. Standard driver errors: Specific handling for database/sql/driver.ErrBadConn, database/sql/driver.ErrSkip, and database/sql/driver.ErrRemoveArgument.
    2. Custom errors: Uses the fully qualified type name (e.g., github.com/your/package.CustomError).
    3. Built-in errors: Uses the type name (e.g., *errors.errorString for errors created via errors.New()).
  2. Configure otelsql with Options

    main
    You can customize instrumentation behavior using otelsql.Option. One useful feature is WithSQLCommenter, which enables adding context propagation to SQL queries via comments.
  3. Access Jaeger and Prometheus UIs in the example

    main

    Once the Docker Compose services are running and the client service has finished its execution, you can view the instrumentation results at the following endpoints:

    • Jaeger UI (Traces): http://localhost:16686
    • Prometheus UI (Metrics): http://localhost:9090
  4. Instrument database/sql with otelsql

    main

    The otelsql package provides four ways to instrument database/sql: otelsql.Open, otelsql.OpenDB, otelsql.Register, and otelsql.WrapDriver.

    To instrument a database and collect connection statistics metrics (from Go's sql.DBStats), use otelsql.Open followed by otelsql.RegisterDBStatsMetrics. You can pass otelsql.WithAttributes to include semantic conventions like semconv.DBSystemMySQL.

    db, err := otelsql.Open("mysql", mysqlDSN, otelsql.WithAttributes(
    	semconv.DBSystemMySQL,
    ))
    if err != nil {
    	panic(err)
    }
    
    reg, err := otelsql.RegisterDBStatsMetrics(db, otelsql.WithAttributes(
    	semconv.DBSystemMySQL,
    ))
    if err != nil {
    	panic(err)
    }
    defer func() {
    	_ = db.Close()
    	_ = reg.Unregister()
    }()
  5. Run the database/sql instrumentation stdout example using Docker Compose

    main

    This example demonstrates a MySQL client using database/sql with instrumentation. The client prints trace data to stdout and serves metrics data via a Prometheus client.

    To run the full environment, ensure you have Docker Compose V2 installed, then follow these steps:

    1. Start the services: Run the following command to bring up all necessary services (MySQL, client, etc.) in detached mode.
    2. Verify results: Check the logs of the client service to observe the instrumented trace data being printed to stdout.
    3. Cleanup: Shut down the services when finished.
    # Start the services
    docker compose up -d
    
    # Check the client logs for trace data
    docker compose logs client
    
    # Shut down the services
    docker compose down
  6. Run the OpenTelemetry Collector example with Docker Compose

    main

    This example demonstrates a MySQL client using database/sql with otelsql instrumentation. It shows how to export trace data to Jaeger and metrics data to Prometheus via an OpenTelemetry Collector.

    To run the full stack (MySQL, OpenTelemetry Collector, Jaeger, Prometheus, and the instrumented client), use Docker Compose.

    Prerequisites:

    Workflow:

    1. Start the services.
    2. Monitor the client service logs to ensure the workload completes.
    3. Access the visualization UIs to inspect traces and metrics.
    4. Shut down the environment.
    # Start all services in the background
    docker compose up -d
    
    # Monitor the client logs to ensure the example execution finishes
    docker compose logs client
    
    # Shut down the services when finished
    docker compose down
  7. Understand how otelsql instrumented connections work

    main

    The otConn type is an instrumented wrapper around a standard driver.Conn. It implements several database/sql/driver interfaces (such as Pinger, ExecerContext, QueryerContext, ConnPrepareContext, and ConnBeginTx) to provide OpenTelemetry observability.

    When you use an instrumented connection, otelsql automatically:

    1. Records Metrics: Captures method calls and errors using the configured instruments.
    2. Creates Spans: Generates traces for database operations (like ExecContext, QueryContext, PrepareContext, and BeginTx) based on your SpanOptions configuration.
    3. Applies SQL Commenting: Uses the configured SQLCommenter to inject comments into queries.
    4. Handles Errors: Automatically records errors into the active OpenTelemetry span.

    Note that if the underlying driver does not implement a specific interface (e.g., driver.Pinger), otelsql gracefully skips instrumentation for that specific method.

  8. Configure SQLCommenter for context propagation

    main

    SQLCommenter allows injecting trace context into SQL statements as comments, enabling distributed tracing across database boundaries.

    To use it, you must enable it via WithSQLCommenter(true). You can also specify a custom propagator using WithTextMapPropagator(propagator). If no propagator is provided, the global text map propagator is used.

    Warning: These options are EXPERIMENTAL and may change or be removed in future releases.

    Example transformation: SELECT * from FOO becomes SELECT * from FOO /*traceparent='...',tracestate='...'*/

    // Enable SQLCommenter with a custom propagator
    otelsql.WithSQLCommenter(true),
    otelsql.WithTextMapPropagator(myPropagator),
  9. How otConnector works as a database/sql driver wrapper

    main

    The otConnector is an internal implementation of the driver.Connector and io.Closer interfaces. It acts as a middleware layer that wraps an existing driver.Connector.

    When Connect(ctx) is called on an otConnector:

    1. It records metrics for the connection attempt.
    2. It optionally creates an OpenTelemetry span if SpanOptions.OmitConnectorConnect is false and the method passes the configured filters.
    3. It delegates the actual connection to the underlying driver.Connector.
    4. It wraps the resulting driver.Conn into an instrumented connection via newConn.

    This allows otelsql to intercept the connection lifecycle to provide observability (traces and metrics) without modifying the underlying database driver.

  10. Deploy the otel-collector example via Docker Compose

    main

    The example/otel-collector/docker-compose.yaml file provides a complete environment to demonstrate otelsql instrumentation. It orchestrates a MySQL database, an OpenTelemetry Collector, Prometheus for metrics, Jaeger for traces, and a sample client application.

    To use this setup, ensure you have the following files in the same directory as the docker-compose.yaml:

    • otel-collector.yaml: Configuration for the OpenTelemetry Collector.
    • prometheus.yaml: Configuration for Prometheus.
    • Dockerfile: The build context for the client service (located at the repository root via ../..).
    # Run the stack using docker-compose
    docker-compose up
  11. Configure otelsql using functional options

    main

    The otelsql package uses a functional options pattern to configure instrumentation behavior. You can pass multiple Option arguments to the instrumentation setup functions (like Open or Register) to customize tracer providers, meter providers, attributes, and more.

    Commonly used options include:

    • WithTracerProvider(provider): Sets a custom trace.TracerProvider. Defaults to the global provider.
    • WithMeterProvider(provider): Sets a custom metric.MeterProvider. Defaults to the global provider.
    • WithAttributes(attributes...): Adds static attributes to every span and measurement. Multiple calls append attributes rather than overwriting them.
    • WithSQLCommenter(enabled): Enables/disables SQLCommenter for context propagation via SQL comments. Note: This is EXPERIMENTAL.
    import (
    	"go.opentelemetry.io/otel/attribute"
    	"go.opentelemetry.io/otel/trace"
    	"github.com/xsam/otelsql"
    )
    
    // Example of applying options
    // (Assuming an instrumentation setup function exists in the package)
    // otelsql.Open(driverName, dataSourceName, 
    //     otelsql.WithTracerProvider(myTracerProvider),
    //     otelsql.WithAttributes(attribute.String("env", "production")),
    //     otelsql.WithSQLCommenter(true),
    // )