|
| 1 | +from tornado.ioloop import IOLoop |
1 | 2 | from tornado.stack_context import StackContextInconsistentError, _state |
2 | 3 |
|
3 | 4 | from ...context import Context |
@@ -59,20 +60,39 @@ def active(cls): |
59 | 60 | """ |
60 | 61 | Return the ``Context`` from the current execution flow. This method can be |
61 | 62 | used inside a Tornado coroutine to retrieve and use the current tracing context. |
| 63 | + If used in a separated Thread, the `_state` thread-local storage is used to |
| 64 | + propagate the current Active context from the `MainThread`. |
62 | 65 | """ |
63 | | - for ctx in reversed(_state.contexts[0]): |
64 | | - if isinstance(ctx, cls) and ctx.active: |
65 | | - return ctx.context |
| 66 | + io_loop = getattr(IOLoop._current, 'instance', None) |
| 67 | + if io_loop is None: |
| 68 | + # if a Tornado loop is not available, it means that this method |
| 69 | + # has been called from a synchronous code, so we can rely in a |
| 70 | + # thread-local storage |
| 71 | + return getattr(_state, '__datadog_context', None) |
| 72 | + else: |
| 73 | + # we're inside a Tornado loop so the TracerStackContext is used |
| 74 | + for ctx in reversed(_state.contexts[0]): |
| 75 | + if isinstance(ctx, cls) and ctx.active: |
| 76 | + return ctx.context |
66 | 77 |
|
67 | 78 | @classmethod |
68 | 79 | def activate(cls, ctx): |
69 | 80 | """ |
70 | 81 | Set the active ``Context`` for this async execution. If a ``TracerStackContext`` |
71 | 82 | is not found, the context is discarded. |
| 83 | + If used in a separated Thread, the `_state` thread-local storage is used to |
| 84 | + propagate the current Active context from the `MainThread`. |
72 | 85 | """ |
73 | | - for stack_ctx in reversed(_state.contexts[0]): |
74 | | - if isinstance(stack_ctx, cls) and stack_ctx.active: |
75 | | - stack_ctx.context = ctx |
| 86 | + io_loop = getattr(IOLoop._current, 'instance', None) |
| 87 | + if io_loop is None: |
| 88 | + # because we're outside of an asynchronous execution, we store |
| 89 | + # the current context in a thread-local storage |
| 90 | + setattr(_state, '__datadog_context', ctx) |
| 91 | + else: |
| 92 | + # we're inside a Tornado loop so the TracerStackContext is used |
| 93 | + for stack_ctx in reversed(_state.contexts[0]): |
| 94 | + if isinstance(stack_ctx, cls) and stack_ctx.active: |
| 95 | + stack_ctx.context = ctx |
76 | 96 |
|
77 | 97 |
|
78 | 98 | def run_with_trace_context(func, *args, **kwargs): |
|
0 commit comments