Skip to content

Commit 03fdd95

Browse files
author
Patrick van der Wal
committed
Add OpenTelemetry tracing to on_message
- extract trace context from the AMQP message headers and wrap the handler call in a consumer span, no-op without a configured OpenTelemetry backend - new dependency opentelemetry-api, span attributes follow the messaging semantic conventions - packaging modernized to pyproject.toml + uv, Debian packaging removed, Python floor now 3.9, pika constrained to >=1.3.2,<1.4
1 parent 179861d commit 03fdd95

18 files changed

Lines changed: 583 additions & 70 deletions

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ nosetests.xml
3535
.project
3636
.pydevproject
3737
.idea
38+
39+
# uv
40+
.venv/

CHANGELOG.md

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,32 @@
1-
<h1>Changelog</h1>
2-
<h2>1.7.1</h2>
3-
Remove the `stop_ioloop_on_close` argument since this is no longer in `pika>=1.0.0`.
4-
Since removing this argument will change behaviour on version still using `pika<1.0.0`
5-
make sure we require at least `pika>1.0.0` in setup.py so people installing this new
6-
version will not have changed behaviour.
1+
# Changelog
2+
3+
All notable changes to this project will be documented in this file.
4+
5+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7+
8+
## [1.8.0] - 2026-07-30
9+
10+
### Added
11+
- OpenTelemetry tracing support: `on_message` extracts trace context from the AMQP message headers and wraps the handler call in a consumer span, so handling continues the publisher's trace (see the eventsender 1.3.0 counterpart). Messages without trace headers start a trace of their own
12+
- `opentelemetry-api` dependency. Without a configured OpenTelemetry backend all tracing calls are no-ops and behaviour is unchanged
13+
- First test suite, run with `uv run pytest tests`
14+
- `pyproject.toml` with uv support, replacing the legacy packaging files
15+
- Tracing and test-running sections to the README
16+
17+
### Changed
18+
- pika constraint from `>=1.0.0` to `>=1.3.2,<1.4`
19+
- Minimum Python version is now 3.9, enforced via `requires-python` so installs on older interpreters keep resolving 1.7.4
20+
- README usage example to Python 3 syntax
21+
22+
### Removed
23+
- `setup.py`, `setup.cfg` and `MANIFEST.in`, replaced by `pyproject.toml`
24+
- Obsolete Python 2 Debian packaging (nothing builds or consumes it anymore)
25+
26+
## [1.7.1] - 2021-04-22
27+
28+
### Removed
29+
- The `stop_ioloop_on_close` argument since this is no longer in `pika>=1.0.0`
30+
31+
### Changed
32+
- Require at least `pika>=1.0.0` in setup.py, since removing the `stop_ioloop_on_close` argument would change behaviour on versions still using `pika<1.0.0`

MANIFEST.in

Lines changed: 0 additions & 1 deletion
This file was deleted.

README.rst

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Example:
1717
1818
1919
def handler(event):
20-
print "Got event:", event
20+
print("Got event:", event)
2121
2222
2323
def main():
@@ -35,6 +35,22 @@ Example:
3535
main()
3636
3737
38+
Tracing
39+
-------
40+
For every consumed message the consumer extracts OpenTelemetry trace context from the
41+
AMQP message headers and wraps the handler call in a consumer span, continuing the
42+
publisher's trace when the message carries one (messages without trace headers simply
43+
start a trace of their own). This only depends on ``opentelemetry-api``, for applications
44+
without a configured OpenTelemetry backend all tracing calls are no-ops and the behaviour
45+
is unchanged. To get the spans into your tracing backend, configure an OpenTelemetry SDK
46+
in your application (for example by enabling the Sentry SDK's OpenTelemetry support).
47+
48+
49+
Running tests
50+
-------------
51+
Install `uv <https://docs.astral.sh/uv/>`_ and run ``uv run pytest tests``.
52+
53+
3854
=====
3955
About
4056
=====
@@ -44,5 +60,3 @@ fast and secure Magento hosting and scalable cluster hosting.
4460
Check out our `Github page <https://github.com/ByteInternet>`_ for more open source software or `our site <https://www.byte.nl>`_
4561
to learn about our products and technologies. Look interesting? Reach out about joining `the team <https://www.byte.nl/vacatures>`_.
4662
Or just drop by for a cup of excellent coffee if you're in town!
47-
48-
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/ByteInternet/python-events/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/ByteInternet/python-events/?branch=master)

amqpconsumer/events.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22
import pika
33
import json
44

5+
from opentelemetry import propagate, trace
6+
57
logger = logging.getLogger(__name__)
68

9+
tracer = trace.get_tracer('amqpconsumer')
10+
711

812
class EventConsumer(object):
913
"""Basic consumer with event loop for RabbitMQ events.
@@ -297,7 +301,21 @@ def on_message(self, _, basic_deliver, properties, body):
297301
except ValueError:
298302
logger.warning('Discarding message containing invalid json: %s', body)
299303
else:
300-
self._handler(decoded)
304+
event_type = decoded.get('type') if isinstance(decoded, dict) else None
305+
context = propagate.extract(properties.headers or {})
306+
with tracer.start_as_current_span(
307+
'process {}'.format(event_type or self._queue),
308+
kind=trace.SpanKind.CONSUMER,
309+
context=context) as span:
310+
span.set_attribute('messaging.system', 'rabbitmq')
311+
span.set_attribute('messaging.operation.name', 'process')
312+
span.set_attribute('messaging.operation.type', 'process')
313+
span.set_attribute('messaging.destination.name', self._queue)
314+
if basic_deliver.routing_key:
315+
span.set_attribute('messaging.rabbitmq.destination.routing_key', basic_deliver.routing_key)
316+
if event_type:
317+
span.set_attribute('event.type', str(event_type))
318+
self._handler(decoded)
301319

302320
self.acknowledge_message(basic_deliver.delivery_tag)
303321

debian/compat

Lines changed: 0 additions & 1 deletion
This file was deleted.

debian/control

Lines changed: 0 additions & 15 deletions
This file was deleted.

debian/copyright

Lines changed: 0 additions & 1 deletion
This file was deleted.

debian/python-amqpconsumer.docs

Lines changed: 0 additions & 1 deletion
This file was deleted.

debian/python-amqpconsumer.examples

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)