MySQL Connector/Python Developer Guide

9.2 Telemetry Support

MySQL Server added OpenTelemetry support in MySQL Enterprise Edition version 8.1.0, which is a commercial product. OpenTelemetry tracing support was added in Connector/Python 8.1.0.

Introduction to OpenTelemetry

OpenTelemetry is an observability framework and toolkit designed to create and manage telemetry data such as traces, metrics, and logs. Visit What is OpenTelemetry? for an explanation of what OpenTelemetry offers.

Connector/Python only supports tracing, so this guide does not include information about metric and log signals.

Installing Telemetry Support

Install the OpenTelemetry API, SDK, and OTLP Exporter packages on the system along with Connector/Python. Optionally use the [telemetry] shortcut when installing the mysql-connector-python pip package to pull in specific OpenTelemetry versions as defined by the connector.

Manual installation:

pip install opentelemetry-api
pip install opentelemetry-sdk
pip install opentelemetry-exporter-otlp-proto-http
pip install mysql-connector-python

Or pass in [telemetry] when installing Connector/Python to perform the same actions except it installs a specific and tested OpenTelemetry version, which for Connector/Python 9.0.0 is OpenTelemetry v1.18.0:

pip install mysql-connector-python[telemetry]

Connector/Python 8.1.0 through 8.4.0 included an [opentelemetry] option that installed a bundled version of the OpenTelemetry SDK/API libraries. Doing so in those versions was not recommended.

Instrumentation

For instrumenting an application, Connector/Python utilizes the official OpenTelemetry SDK to initialize OpenTelemetry, and the official OpenTelemetry API to instrument the application's code. This emits telemetry from the application and from utilized libraries that include instrumentation.

An application can be instrumented as demonstrated by this generic example:

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.export import ConsoleSpanExporter

provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)

with tracer.start_as_current_span("app"):
    my_app()

To better understand and get started using OpenTelemetry tracing for Python, see the official OpenTelemetry Python Instrumentation guide.

MySQL Connector/Python

Connector/Python includes a MySQL instrumentor to instrument MySQL connections. This instrumentor provides an API and usage similar to OpenTelemetry's own MySQL package named opentelemetry-instrumentation-mysql.

An exception is raised if a system does not support OpenTelemetry when attempting to use the instrumentor.

An example that utilizes the system's OpenTelemetry SDK/API and implements tracing with MySQL Connector/Python:

import os
import mysql.connector

# An instrumentor that comes with mysql-connector-python
from mysql.connector.opentelemetry.instrumentation import (
    MySQLInstrumentor as OracleMySQLInstrumentor,
)

# Loading SDK from the system
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.trace.export import ConsoleSpanExporter

provider = TracerProvider()
processor = BatchSpanProcessor(ConsoleSpanExporter())
provider.add_span_processor(processor)
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)

config = {
    "host": "127.0.0.1",
    "user": "root",
    "password": os.environ.get("password"),
    "use_pure": True,
    "port": 3306,
    "database": "test",
}

# Global instrumentation: all connection objects returned by
# mysql.connector.connect will be instrumented.
OracleMySQLInstrumentor().instrument()

with tracer.start_as_current_span("client_app"):
    with mysql.connector.connect(**config) as cnx:
        with cnx.cursor() as cur:
            cur.execute("SELECT @@version")
            _ = cur.fetchall()

Morphology of the Emitted Traces

A trace generated by the Connector/Python instrumentor contains one connection span, and zero or more query spans as described in the rest of this section.

Connection Span

  • Time from connection initialization to the moment the connection ends. The span is named connection.

  • If the application does not provide a span, the connection span generated is a ROOT span, originating in the connector.

  • If the application does provide a span, the query span generated is a CHILD span, originating in the connector.

Query Span

  • Time from when an SQL statement is requested (on the connector side) to the moment the connector finishes processing the server's reply to this statement.

  • A query span is created for each query request sent to the server. If the application does not provide a span, the query span generated is a ROOT span, originating in the connector.

  • If the application does provide a span, the query span generated is a CHILD span, originating in the connector.

  • The query span is linked to the existing connection span of the connection the query was executed.

  • Query attributes with prepared statements is supported as of MySQL Enterprise Edition 8.3.0.

  • Query spans for the connection object is supported as of Connector/Python 8.3.0, which includes methods such as commit(), rollback(), and cmd_change_user().

Context Propagation

By default, the trace context of the span in progress (if any) is propagated to the MySQL server.

Propagation has no effect when the MySQL server either disabled or does not support OpenTelemetry (the trace context is ignored by the server), however, when connecting to a server with OpenTelemetry enabled and configured, the server processes the propagated traces and creates parent-child relationships between the spans from the connector and those from the server. In other words, this provides trace continuity.

Note

Context propagation with prepared statements is supported as of MySQL Enterprise Edition 8.3.0.

  • The trace context is propagated for statements with query attributes defined in the MySQL client/server protocol, such as COM_QUERY.

    The trace context is not propagated for statements without query attributes defined in the MySQL client/server protocol, statements such as COM_PING.

  • Trace context propagation is done via query attributes where a new attribute named "traceparent" is defined. Its value is based on the current span context. For details on how this value is computed, read the traceparent header W3C specification.

    If the "traceparent" query attribute is manually set for a query, then it is not be overwritten by the connector; it's assumed that it provides OTel context intended to forward to the server.

Disabling Trace Context Propagation

The boolean connection property named otel_context_propagation is True by default. Setting it to False disables context propagation.

Since otel_context_propagation is a connection property that can be changed after a connection is established (a connection object is created), setting such property to False does not have an effect over the spans generated during the connection phase. In other words, spans generated during the connection phase are always propagated since otel_context_propagation is True by default.

This implementation is distinct from the implementation provided through the MySQL client library (or the related telemetry_client client-side plugin).