Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug: tornado "in io loop" logic (python2.7) #1353

Closed
zhammer opened this issue Apr 12, 2020 · 4 comments
Closed

bug: tornado "in io loop" logic (python2.7) #1353

zhammer opened this issue Apr 12, 2020 · 4 comments

Comments

@zhammer
Copy link
Contributor

zhammer commented Apr 12, 2020

(disclaimer: i don't think this really deserves a fix but want to flag for the team and justify my venturing down this rabbit hole)

bug

discovered some interesting behavior with the tornado stack context for python2.7, where just making a tornado.ioloop.IOLoop in synchronous code destroyed my current ddtrace context.

# python2.7
# ddtrace==0.36.1
# tornado==4.5.3

from __future__ import print_function
from tornado.ioloop import IOLoop
import ddtrace

ddtrace.patch(False, tornado=True)

print("before:", ddtrace.tracer.get_call_context())  # prints a call context
IOLoop.current()
print("after:", ddtrace.tracer.get_call_context())  # prints None

on further investigation i found that a lot of TracerStackContext relies on TracerStackContext._has_io_loop, which according to the documentation should tell us if we're "inside" an event loop:

def _has_io_loop(self):
"""Helper to determine if we are currently in an IO loop"""
return getattr(IOLoop._current, 'instance', None) is not None

from what i can tell, that logic doesn't check if we're in an event loop, it just checks if there is an event loop. that's why calling IOLoop.current() confuses the script I posted:

fix attempt

i experimented with a fix here: master...seatgeek:zh-tornado-loop following some discussion on this tornado issue: tornadoweb/tornado#2070

ironically i actually prefer the current behavior (where TracerStackContext always thinks it's in an IOLoop if there is one) so you can more easily do sync -> async propagation like this

@tornado.gen.coroutine
def make_child():
    return self.tracer.trace("child")

with TracerStackContext():
    parent = self.tracer.trace("parent")
    child = tornado.ioloop.IOLoop.current().run_sync(make_child)

assert child.parent_id == parent.span_id

regardless i wanted to raise to you all in case other folks get confused.

@Kyle-Verhoog
Copy link
Member

@zhammer thanks for digging into this! Haven't got a chance to read through this thoroughly, but just wanted to give a quick shout-out 😄

It does seem like it's a bug that simply making a new ioloop destroys the current context 😕.

@zhammer
Copy link
Contributor Author

zhammer commented Apr 28, 2020

hey @Kyle-Verhoog ! i just saw this in the 0.37.0 release notes:

Fix task context management for asyncio in Python <3.7 (#1353)

is there a PR that fixed this issue?

@Kyle-Verhoog
Copy link
Member

That's so strange that #1353 was included in that line 🤔

We use a script to generate those comments... strange... anyway the corresponding PR should have been #1352.

Sorry about that!

@Kyle-Verhoog
Copy link
Member

Thanks again for the report Zach, I'm going to close this issue out as I don't think we're going to get to this with it being a Python 2.7-specific issue. Please reopen if it's something you'd like to addressed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants