|
| 1 | +sqlcommenter |
| 2 | +============ |
| 3 | + |
| 4 | +This is an example of how to use OpenTelemetry Python instrumention with |
| 5 | +sqlcommenter to enrich database query statements with contextual information. |
| 6 | +For more information on sqlcommenter concepts, see: |
| 7 | + |
| 8 | +* `Semantic Conventions - Database Spans <https://github.com/open-telemetry/semantic-conventions/blob/main/docs/database/database-spans.md#sql-commenter>`_ |
| 9 | +* `sqlcommenter <https://google.github.io/sqlcommenter/>`_ |
| 10 | + |
| 11 | +The source files of this example are available `here <https://github.com/open-telemetry/opentelemetry-python/tree/main/docs/examples/sqlcommenter/>`_. |
| 12 | +This example uses Docker to manage a database server and OpenTelemetry collector. |
| 13 | + |
| 14 | +Run MySQL server |
| 15 | +---------------- |
| 16 | + |
| 17 | +A running MySQL server with general logs enabled will store query statements with context resulting from the sqlcommenter feature enabled in this example. |
| 18 | + |
| 19 | +.. code-block:: sh |
| 20 | +
|
| 21 | + cd books_database |
| 22 | + docker build -t books-db . |
| 23 | + docker run -d --name books-db -p 3366:3306 books-db |
| 24 | + cd .. |
| 25 | +
|
| 26 | +Check that the run is working and the general log is available: |
| 27 | + |
| 28 | +.. code-block:: sh |
| 29 | +
|
| 30 | + docker exec -it books-db tail -f /var/log/general.log |
| 31 | +
|
| 32 | +Run OpenTelemetry Collector |
| 33 | +--------------------------- |
| 34 | + |
| 35 | +Running the OpenTelemetry collector will show the MySQL instrumentor's |
| 36 | +comment-in-span-attribute feature, which this example has also enabled. |
| 37 | + |
| 38 | +.. code-block:: sh |
| 39 | +
|
| 40 | + docker run \ |
| 41 | + -p 4317:4317 \ |
| 42 | + -v $(pwd)/collector-config.yaml:/etc/otel/config.yaml \ |
| 43 | + otel/opentelemetry-collector-contrib:latest |
| 44 | +
|
| 45 | +Run the sqlcommenter example |
| 46 | +---------------------------- |
| 47 | + |
| 48 | +Set up and activate a Python virtual environment. Install these |
| 49 | +dependencies of the sqlcommenter example: |
| 50 | + |
| 51 | +.. code-block:: sh |
| 52 | +
|
| 53 | + pip install opentelemetry-sdk \ |
| 54 | + opentelemetry-exporter-otlp-proto-grpc \ |
| 55 | + opentelemetry-instrumentation-mysql \ |
| 56 | + mysql-connector-python |
| 57 | +
|
| 58 | +Then, run this script, which instruments all mysql-connector calls with |
| 59 | +two sqlcommenter features opted in. |
| 60 | + |
| 61 | +.. code-block:: sh |
| 62 | +
|
| 63 | + python instrumented_query.py |
| 64 | +
|
| 65 | +Note that OpenTelemetry instrumentation with sqlcommenter is also |
| 66 | +available for other Python database client drivers/object relation |
| 67 | +mappers (ORMs). See full list at `instrumentation`_. |
| 68 | + |
| 69 | +.. _instrumentation: https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation |
| 70 | + |
| 71 | +Check MySQL server general log and spans for sqlcomment |
| 72 | +------------------------------------------------------- |
| 73 | + |
| 74 | +After running the query script, check the MySQL general log contents: |
| 75 | + |
| 76 | +.. code-block:: sh |
| 77 | +
|
| 78 | + docker exec -it books-db tail -f /var/log/general.log |
| 79 | +
|
| 80 | +For each instrumented ``SELECT`` call, a query was made and logged with |
| 81 | +a sqlcomment appended. For example: |
| 82 | + |
| 83 | +.. code:: |
| 84 | +
|
| 85 | + 2025-09-02T18:49:06.981980Z 186 Query SELECT * FROM authors WHERE id = 1 /*db_driver='mysql.connector%%3A9.4.0',dbapi_level='2.0',dbapi_threadsafety=1,driver_paramstyle='pyformat',mysql_client_version='9.4.0',traceparent='00-2c45248f2beefdd9688b0a94eb4ac9ee-4f3af9a825aae9b1-01'*/ |
| 86 | +
|
| 87 | +In the running OpenTelemetry collector, you'll also see one span per |
| 88 | +``SELECT`` call. Each of those span's trace ID and span ID will |
| 89 | +correspond to a query log sqlcomment. With the comment-in-attribute |
| 90 | +feature enabled, the span's ``db.statement`` attribute will also contain |
| 91 | +the sqlcomment. For example: |
| 92 | + |
| 93 | +.. code:: |
| 94 | +
|
| 95 | + ScopeSpans #0 |
| 96 | + ScopeSpans SchemaURL: https://opentelemetry.io/schemas/1.11.0 |
| 97 | + InstrumentationScope opentelemetry.instrumentation.mysql 0.57b0 |
| 98 | + Span #0 |
| 99 | + Trace ID : 2c45248f2beefdd9688b0a94eb4ac9ee |
| 100 | + Parent ID : |
| 101 | + ID : 4f3af9a825aae9b1 |
| 102 | + Name : SELECT |
| 103 | + Kind : Client |
| 104 | + Start time : 2025-09-02 18:49:06.982341 +0000 UTC |
| 105 | + End time : 2025-09-02 18:49:06.98463 +0000 UTC |
| 106 | + Status code : Unset |
| 107 | + Status message : |
| 108 | + Attributes: |
| 109 | + -> db.system: Str(mysql) |
| 110 | + -> db.name: Str(books) |
| 111 | + -> db.statement: Str(SELECT * FROM authors WHERE id = %s /*db_driver='mysql.connector%%3A9.4.0',dbapi_level='2.0',dbapi_threadsafety=1,driver_paramstyle='pyformat',mysql_client_version='9.4.0',traceparent='00-2c45248f2beefdd9688b0a94eb4ac9ee-4f3af9a825aae9b1-01'*/) |
| 112 | + -> db.user: Str(books) |
| 113 | + -> net.peer.name: Str(localhost) |
| 114 | + -> net.peer.port: Int(3366) |
| 115 | +
|
| 116 | +
|
| 117 | +References |
| 118 | +---------- |
| 119 | + |
| 120 | +* `OpenTelemetry Project <https://opentelemetry.io/>`_ |
| 121 | +* `OpenTelemetry Collector <https://github.com/open-telemetry/opentelemetry-collector>`_ |
| 122 | +* `OpenTelemetry MySQL instrumentation <https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation/opentelemetry-instrumentation-mysql>`_ |
| 123 | +* `Semantic Conventions - Database Spans <https://github.com/open-telemetry/semantic-conventions/blob/main/docs/database/database-spans.md#sql-commenter>`_ |
| 124 | +* `sqlcommenter <https://google.github.io/sqlcommenter/>`_ |
0 commit comments