Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

Igreh
Copy link

@Igreh Igreh commented Jul 10, 2025

Adds tracing support to DramatiqIntegration #3454

Adds tracing support to DramatiqIntegration getsentry#3454
@Igreh Igreh requested a review from a team as a code owner July 10, 2025 16:52
Copy link
Member

@szokeasaurusrex szokeasaurusrex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @Igreh, I took a quick glance at your PR – at a high level this seems reasonable; however, before I do a full review, I would appreciate if you could please add some tests for these changes, since we need tests before we can consider merging this.

@@ -85,20 +89,27 @@ class SentryMiddleware(Middleware): # type: ignore[misc]
DramatiqIntegration.
"""

# type: contextvars.ContextVar[Transaction]
_transaction = contextvars.ContextVar("_transaction", default=None)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we using a ContextVar here, instead of just a simple instance variable on the SentryMiddleware?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To isolate variable between threads:

  1. Dramatiq can be started in multithreading mode:
    dramatiq --processes 1 --threads 5 ...
  2. And I was inspired by official middleware:
    CurrentMessageMiddleware

I will try recheck if it's actually needed

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed.
One SentryMiddleware instance will be shared between threads. So, isolating is necessary.
Previous (actually current) realisation adds _scope_manager to message, but I think ContextVar is much cleaner solution

Copy link

codecov bot commented Jul 14, 2025

Codecov Report

❌ Patch coverage is 84.61538% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.55%. Comparing base (5a122b5) to head (39e3a50).
⚠️ Report is 10 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
sentry_sdk/integrations/dramatiq.py 84.21% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4571      +/-   ##
==========================================
+ Coverage   84.47%   84.55%   +0.07%     
==========================================
  Files         158      158              
  Lines       16506    16535      +29     
  Branches     2865     2868       +3     
==========================================
+ Hits        13944    13981      +37     
+ Misses       1712     1706       -6     
+ Partials      850      848       -2     
Files with missing lines Coverage Δ
sentry_sdk/consts.py 99.33% <100.00%> (+<0.01%) ⬆️
sentry_sdk/integrations/dramatiq.py 83.16% <84.21%> (-0.59%) ⬇️

... and 5 files with indirect coverage changes

@Igreh
Copy link
Author

Igreh commented Jul 15, 2025

Hi @Igreh, I took a quick glance at your PR – at a high level this seems reasonable; however, before I do a full review, I would appreciate if you could please add some tests for these changes, since we need tests before we can consider merging this.

Hi!
Thanks for reply. I'm not very familiar about what should be tested exactly for now (transaction was successfully started? or what objects/props must be created? and etc ) but I will take a look and try to do my best =)
If you have any advice - would be very helpful

Edit:
Or I just need to cover one missed line?

@sentrivana
Copy link
Contributor

Hey @Igreh, it'd be good to have "end-to-end" (i.e., not unit tests) for the different tracing code paths. Stuff like:

  • the happy path (if everything works fine, you get the transaction and it has the data you expect it to have)
  • how it behaves if there's an error (a transaction still gets sent, and it has the correct status, etc.; maybe also check if the user's program still behaves as expected -- the exception bubbles up if it should bubble up, etc.)
  • trace propagation (i.e., the transaction picks up propagation headers/vars if present) -- I think this might still be missing in your PR

...and/or whatever you consider important so that when the test suite is run and ends up green, you'd have a reasonable amount of confidence that tracing in the Dramatiq integration is working.

You can have a look at some of these similar integrations and their test suites (e.g. arq, huey) for inspiration.

Thanks for working on this! Let us know if you need any help.

- add trace propagation
- set dramatiq_task_id as tag instead of extra
- new tests
- fix mypy issues

Issue: getsentry#3454
@Igreh
Copy link
Author

Igreh commented Jul 15, 2025

Hi @sentrivana !
Thanks for your reply. It was very helpful.
I believe I was able to solve propagation issue (see last commit)
Also, I've changed the way dramatiq_task_id is stored - now as tag (like in celery). It's actually very convenient to find transaction by ID.
New tests were added (huey integration I used for inspiration).
One thing I can't understand for now: mechanism.type of error event is "logging" instead of "dramatiq". https://github.com/getsentry/sentry-python/pull/4571/files#diff-ed170393871d90a02937ffecacd1b736805e6ea3c43e5549fd0df9bab883709eR82
Disabling LoggingIntegration fixes it (and actually it's the way we use sentry) but I suppose the general solution must work on defaults)
Probably, I have to dig deeper to dramatiq source code to understand what's happening... Not sure but I will keep investigating

@Igreh
Copy link
Author

Igreh commented Jul 21, 2025

Hi @sentrivana !
Things are more complicated than I expected... =)

I'm using (and testing) my current integration on real project and
we're experiencing different side effects, but I'm curious about one thing for now:
Retried transactions must be connected by the same trace? Is any sentry agreement for such issue?
Retrying in terms of Dramatiq means requeuing message and it means baggage is propagated also. Bug or feature ? )

Failed task with 3 retries might look like this:
screen_2025-07-21_13-55-15

@sentrivana
Copy link
Contributor

sentrivana commented Jul 22, 2025

Hey again 👋🏻 Thanks for your time on this!

One thing I can't understand for now: mechanism.type of error event is "logging" instead of "dramatiq". https://github.com/getsentry/sentry-python/pull/4571/files#diff-ed170393871d90a02937ffecacd1b736805e6ea3c43e5549fd0df9bab883709eR82
Disabling LoggingIntegration fixes it (and actually it's the way we use sentry) but I suppose the general solution must work on defaults)

What you're seeing is likely dramatiq logging the error when it happens, and our LoggingIntegration picking it up. In case that happens, our deduplication logic (in DedupeIntegration) drops the second (in this case better) event coming directly from the integration.

What you can do is add an ignore_logger("<logger-name>") to the integration, see for example here where we were solving the same issue for strawberry-graphql. This will tell the LoggingIntegration to skip capturing events from that specific logger, so the actual events coming from the specialized integration should get through.

(I know you're not working on the error part of the integration in this PR but it's still a good improvement so feel free to include it.)

I'm using (and testing) my current integration on real project and
we're experiencing different side effects, but I'm curious about one thing for now:
Retried transactions must be connected by the same trace? Is any sentry agreement for such issue?
Retrying in terms of Dramatiq means requeuing message and it means baggage is propagated also. Bug or feature ? )

Not sure off the top of my head how this works in our other task queue integrations, but my hunch is that retries should be under one trace.

@antonpirker antonpirker added the New Integration Integrating with a new framework or library label Sep 11, 2025
cursor[bot]

This comment was marked as outdated.

Igreh and others added 2 commits September 15, 2025 11:39
)

- import ContextVar from utils for python3.6 support
- do not import type "R" from dramatiq package because it was introduced only in
  newer version of dramatiq
- fix mypy settings to ignore missing imports
- fix tox.ini to include aiocontextvars for py3.6
cursor[bot]

This comment was marked as outdated.

- Start new trace in case of retrying task. Such decision makes life
easier to investigate failed transactions in complicated traces.
- also fix logging issue in tests

Issue: getsentry#3454
@Igreh
Copy link
Author

Igreh commented Sep 16, 2025

Good day everyone!
Sorry for long delay but now I'm back and going to complete this task)

Last patches are aimed to solve (I hope) all current issues:

  • py36 support (ContextVar). aiocontextvars as new deps for tox.
  • typing issues: incorrect import (type R was absent in earlier versions of dramatiq)
  • fix test (ignore logger)

Not sure off the top of my head how this works in our other task queue integrations, but my hunch is that retries should be under one trace.

I decided to not include retries under one trace. As mentioned in commit: "Start new trace in case of retrying task. Such decision makes life easier to investigate failed transactions in complicated traces.".
As example: one transaction may include 2 or more execution of the same task. If one or more failed and dramatiq starts retrying them then trace will include huge amount of task calls. Understanding what should have happened and what actually happened becomes an extremely difficult task. The sequence of calls (at least visually) is disrupted. It's really easier to find all retries by dramatiq_message_id (which is now became tag)

Let me know if anything needs to be improved or reworked. Thanks in advance!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New Integration Integrating with a new framework or library
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants