OpenTelemetry mysqlclient Instrumentation
This library provides OpenTelemetry automatic instrumentation for the `mysqlclient` Python package, enabling tracing of database operations. It is part of the `opentelemetry-python-contrib` project, which maintains various community-contributed instrumentations. The current version is 0.62b0, and releases generally align with the `opentelemetry-python` core and contrib release cadence, often in beta stages.
Warnings
- breaking The inclusion of SQLCommenter data in the `db.statement` span attribute became opt-in. This was a breaking change introduced around OpenTelemetry Python Contrib v0.49b0 / OpenTelemetry Python SDK v1.28.0.
- gotcha Enabling SQLCommenter (`enable_commenter=True`) can cause severe performance penalties if you are using `mysqlclient` cursors with `prepared=True` (prepared statements). SQLCommenter appends unique comments to queries, effectively defeating the purpose of prepared statements by making each query unique, forcing re-preparation by the database.
- gotcha This instrumentation typically requires `mysqlclient` versions less than 3 for full compatibility. Check the `requires_dist` metadata on PyPI or the `opentelemetry-python-contrib` documentation for the exact compatible version range.
- gotcha OpenTelemetry Semantic Conventions are continually evolving. Older versions of instrumentations might emit deprecated attributes. Future major versions of OpenTelemetry Python or its instrumentations may switch to new semantic conventions by default, which can break analysis tools if not configured correctly.
Install
-
pip install opentelemetry-instrumentation-mysqlclient -
pip install mysqlclient -
pip install opentelemetry-sdk opentelemetry-exporter-otlp-proto-http
Imports
- MySQLClientInstrumentor
from opentelemetry.instrumentation.mysqlclient import MySQLClientInstrumentor
Quickstart
import os
import MySQLdb
from opentelemetry import trace
from opentelemetry.sdk.resources import Resource
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import ConsoleSpanExporter, BatchSpanProcessor
from opentelemetry.instrumentation.mysqlclient import MySQLClientInstrumentor
# 1. Configure OpenTelemetry Tracer Provider
resource = Resource.create({"service.name": "mysqlclient-app"})
provider = TracerProvider(resource=resource)
span_processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(span_processor)
trace.set_tracer_provider(provider)
# 2. Instrument mysqlclient
# Optional: enable_commenter=True for SQLCommenter support
# MySQLClientInstrumentor().instrument(enable_commenter=True)
MySQLClientInstrumentor().instrument()
# 3. Use mysqlclient as usual
DB_HOST = os.environ.get('MYSQL_HOST', 'localhost')
DB_USER = os.environ.get('MYSQL_USER', 'root')
DB_PASSWORD = os.environ.get('MYSQL_PASSWORD', 'password') # Use environment variables for auth
DB_NAME = os.environ.get('MYSQL_DB', 'test_db')
try:
# Wrap database operations within a span for clearer context
with trace.get_tracer(__name__).start_as_current_span("db_operations"):
cnx = MySQLdb.connect(
host=DB_HOST,
user=DB_USER,
password=DB_PASSWORD,
database=DB_NAME
)
cursor = cnx.cursor()
# Example DDL and DML operations
cursor.execute("DROP TABLE IF EXISTS test_table")
cursor.execute("CREATE TABLE test_table (id INT, name VARCHAR(255))")
cursor.execute("INSERT INTO test_table (id, name) VALUES (1, 'OpenTelemetry')")
cnx.commit()
cursor.execute("SELECT * FROM test_table")
for row in cursor.fetchall():
print(f"Fetched: {row}")
cursor.close()
cnx.close()
print("MySQL operations completed successfully and should be traced.")
except MySQLdb.Error as err:
print(f"Error: {err}")
current_span = trace.get_current_span()
current_span.record_exception(err)
current_span.set_status(trace.Status(trace.StatusCode.ERROR, description=str(err)))
finally:
# Ensure exporter is shut down to flush any buffered spans
provider.shutdown()