{"id":1004,"library":"opentelemetry-instrumentation-dbapi","title":"OpenTelemetry DBAPI Instrumentation","description":"The `opentelemetry-instrumentation-dbapi` library provides OpenTelemetry tracing for Python applications interacting with databases via libraries that adhere to the Python Database API Specification v2.0 (PEP 249). It's part of the `opentelemetry-python-contrib` project, which typically follows a monthly release cadence. The current version, `0.61b0`, signifies that it is still in beta, and while functional, its API or behavior may be subject to change. This instrumentation offers core functionality for database tracing, and while users often prefer framework or ORM-specific instrumentations, it can be used directly when those are not available.","status":"active","version":"0.61b0","language":"python","source_language":"en","source_url":"https://github.com/open-telemetry/opentelemetry-python-contrib","tags":["opentelemetry","instrumentation","database","dbapi","tracing","sql"],"install":[{"cmd":"pip install opentelemetry-instrumentation-dbapi opentelemetry-sdk mysql-connector-python","lang":"bash","label":"Install with a sample DBAPI driver"}],"dependencies":[{"reason":"Required for OpenTelemetry API interfaces (e.g., TracerProvider).","package":"opentelemetry-api","optional":false},{"reason":"Required for OpenTelemetry SDK components (e.g., TracerProvider implementation, SpanProcessor, Exporter).","package":"opentelemetry-sdk","optional":false},{"reason":"This instrumentation wraps existing database drivers (e.g., psycopg2, mysql-connector-python). One must be installed separately.","package":"Python DBAPI 2.0 compliant driver","optional":false}],"imports":[{"note":"The DbApiInstrumentor class is not directly exposed or the primary way to enable instrumentation; 'trace_integration' and 'wrap_connect' are the public functions.","wrong":"from opentelemetry.instrumentation.dbapi import DbApiInstrumentor","symbol":"trace_integration","correct":"from opentelemetry.instrumentation.dbapi import trace_integration"}],"quickstart":{"code":"import os\nimport mysql.connector\nfrom opentelemetry import trace\nfrom opentelemetry.sdk.trace import TracerProvider\nfrom opentelemetry.sdk.trace.export import ConsoleSpanExporter, SimpleSpanProcessor\nfrom opentelemetry.instrumentation.dbapi import trace_integration\n\n# Configure OpenTelemetry SDK\nresource = {\"service.name\": os.environ.get('OTEL_SERVICE_NAME', 'dbapi-example')}\ntracer_provider = TracerProvider.from_resource_attributes(resource)\ntracer_provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))\ntrace.set_tracer_provider(tracer_provider)\n\n# Get a tracer\ntracer = trace.get_tracer(__name__)\n\n# Instrument the database connector (e.g., mysql.connector)\n# Pass the module, the name of its connect method, and the database system identifier\ntrace_integration(mysql.connector, \"connect\", \"mysql\")\n\ntry:\n    # Establish a connection using the instrumented module\n    connection = mysql.connector.connect(\n        host=os.environ.get('MYSQL_HOST', 'localhost'),\n        user=os.environ.get('MYSQL_USER', 'root'),\n        password=os.environ.get('MYSQL_PASSWORD', 'password'),\n        database=os.environ.get('MYSQL_DATABASE', 'testdb')\n    )\n\n    with tracer.start_as_current_span(\"db-operations\"):\n        cursor = connection.cursor()\n        cursor.execute(\"CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255))\")\n        cursor.execute(\"INSERT INTO users (name) VALUES ('Alice')\")\n        connection.commit()\n        cursor.execute(\"SELECT * FROM users\")\n        result = cursor.fetchall()\n        print(f\"Fetched result: {result}\")\n        cursor.close()\n\nexcept Exception as e:\n    print(f\"An error occurred: {e}\")\nfinally:\n    if 'connection' in locals() and connection.is_connected():\n        connection.close()\n    print(\"Application finished.\")\n","lang":"python","description":"This quickstart demonstrates how to set up the OpenTelemetry Python SDK with a `ConsoleSpanExporter` and then apply `opentelemetry-instrumentation-dbapi` to `mysql.connector`. It traces database operations, including connection, table creation, insertion, and selection, ensuring that these actions generate spans visible in the console. Environment variables are used for database credentials for a runnable example."},"warnings":[{"fix":"Regularly review the `opentelemetry-python-contrib` CHANGELOG for specific instrumentation packages and adapt your code to new APIs or semantic conventions. Pin major versions in `requirements.txt`.","message":"OpenTelemetry Python contrib packages, including `opentelemetry-instrumentation-dbapi`, are often in beta (indicated by `b0` suffix). This means API changes and breaking modifications can occur between minor versions without strict adherence to semantic versioning until a stable `1.0.0` release. Semantic conventions, which define attribute names and structures, also evolve and may require updates to instrumentation configurations. For example, the `db.statement` attribute's inclusion of sqlcomment became opt-in in previous versions.","severity":"breaking","affected_versions":"All beta versions (`<1.0.0`)"},{"fix":"Always verify the exact name of the connection function for your specific DBAPI driver by checking its documentation or source code. Use the correct string in the `trace_integration` or `wrap_connect` call.","message":"Incorrectly identifying the `connect` method name for your DBAPI driver is a common mistake. For instance, `pyodbc`'s connection function is `connect`, not `Connection`. Using the wrong method name will result in instrumentation failing silently or partially.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Enable `sqlcommenter` by setting `enable_commenter=True` in the `trace_integration` or `wrap_connect` call: `trace_integration(module, 'connect', 'database_system', enable_commenter=True)`. Further configuration can be done via `commenter_options`.","message":"The `sqlcommenter` feature, which enriches SQL queries with OpenTelemetry context for better database-side observability, is disabled by default. If not explicitly enabled, trace context will not be appended to SQL queries, hindering end-to-end trace correlation if the database logs are consumed by an observability backend.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Consider deploying with a single worker for metrics, or explore programmatic instrumentation specifically for metrics in a multi-worker setup. Alternatively, use workarounds like Prometheus with direct OTLP export, as detailed in OpenTelemetry Python troubleshooting guides.","message":"When using pre-forking servers (e.g., Gunicorn with multiple workers), OpenTelemetry automatic instrumentation, especially for metrics, can lead to inconsistencies. The forking process can create issues with background threads and locks in SDK components like `PeriodicExportingMetricReader`, potentially causing missing or incorrect metrics.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure you are using a recent version of `opentelemetry-instrumentation-dbapi` where this issue has been addressed. As of `0.61b0`, this should be resolved. If upgrading is not an option, verify generated spans thoroughly and apply alternative suppression logic if necessary.","message":"In some older versions (e.g., `0.53b1`), the `opentelemetry-instrumentation-dbapi` might not correctly respect the `suppress_instrumentation` context manager. This can lead to spans being generated even when you intend to suppress them.","severity":"gotcha","affected_versions":"<=0.53b1 (fix introduced in #3460)"},{"fix":"Update `TracerProvider` instantiation from `TracerProvider.from_resource_attributes(resource)` to `TracerProvider(resource=resource)`. Regularly review the `opentelemetry-sdk` CHANGELOG for specific API changes and adapt your code accordingly. Pin major versions of OpenTelemetry packages in `requirements.txt` to mitigate unexpected breaking changes.","message":"The `TracerProvider.from_resource_attributes` class method was removed in `opentelemetry-sdk` version `1.15.0`. This is a breaking API change that requires updating how `TracerProvider` instances are created, from using a class method to directly passing the resource to the constructor. This highlights a general risk of breaking API changes in core OpenTelemetry Python SDK packages before their `1.0.0` stable release.","severity":"breaking","affected_versions":"opentelemetry-sdk >= 1.15.0 (when using older API methods)"}],"env_vars":null,"last_verified":"2026-05-12T22:30:38.178Z","next_check":"2026-06-27T00:00:00.000Z","problems":[{"fix":"Ensure all necessary OpenTelemetry packages are installed in the correct environment using `pip install opentelemetry-distro[otlp] opentelemetry-instrumentation-dbapi` (or specific instrumentation for your database driver like `opentelemetry-instrumentation-psycopg2`). If still facing issues, verify the Python environment and check for namespace conflicts.","cause":"This error typically occurs when the OpenTelemetry instrumentation packages, including `opentelemetry-instrumentation-dbapi`, are not installed in the Python environment where your application is running, or due to namespace package conflicts.","error":"ModuleNotFoundError: No module named 'opentelemetry.instrumentation'"},{"fix":"This specific issue has been a known bug in older versions of `opentelemetry-instrumentation-dbapi` related to how it wrapped `MySQLdb` connections. Ensure you are using the latest compatible versions of `opentelemetry-instrumentation-dbapi` and `MySQLdb`/`mysqlclient`. If the issue persists, consider using a different MySQL driver if possible, or consult the OpenTelemetry GitHub issues for potential workarounds or newer fixes.","cause":"When using `opentelemetry-instrumentation-dbapi` with `MySQLdb` (or `mysqlclient`), the instrumented connection object might be prematurely closed or appear unusable after being wrapped, leading to this error when database operations are attempted.","error":"MySQLdb._exceptions.OperationalError: (2006, '') (database is gone)"},{"fix":"Replace the incorrect connect method name in `trace_integration`. For `pyodbc`, use `trace_integration(pyodbc, \"connect\", \"odbc\")` to correctly instrument the connection.","cause":"The `trace_integration` function requires the *name* of the connect method for the DB-API 2.0 compliant module, not the connection class name. For `pyodbc`, the connect method is typically named `connect`, not `Connection`.","error":"trace_integration(pyodbc, \"Connection\", \"odbc\") not tracing"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":null,"quickstart_tag":null,"pypi_latest":"0.62b1","cli_name":"","install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.25,"mem_mb":8.1,"disk_size":"27.5M"},{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.26,"mem_mb":8.1,"disk_size":"27.3M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.5,"import_time_s":0.18,"mem_mb":8.1,"disk_size":"89M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":8.1,"disk_size":"127M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.34,"mem_mb":9.3,"disk_size":"30.5M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.39,"mem_mb":9.3,"disk_size":"30.3M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3.3,"import_time_s":0.3,"mem_mb":9.3,"disk_size":"92M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.29,"mem_mb":9.3,"disk_size":"130M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.55,"mem_mb":12.3,"disk_size":"22.1M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.58,"mem_mb":12.3,"disk_size":"21.9M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3,"import_time_s":0.53,"mem_mb":12.3,"disk_size":"83M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.54,"mem_mb":12.3,"disk_size":"121M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.18,"mem_mb":6.2,"disk_size":"21.8M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":6.2,"disk_size":"21.5M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":3,"import_time_s":0.19,"mem_mb":6.2,"disk_size":"83M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":6.2,"disk_size":"121M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":7.3,"disk_size":"26.5M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.21,"mem_mb":7.3,"disk_size":"26.3M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":"wheel","failure_reason":null,"install_time_s":4,"import_time_s":0.19,"mem_mb":7.3,"disk_size":"117M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":7.3,"disk_size":"117M"}]},"quickstart_checks":{"last_tested":"2026-04-24","tag":null,"tag_description":null,"results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}