-
-
Save simon-weber/7755289 to your computer and use it in GitHub Desktop.
import tornado | |
class RequestContextHandler(tornado.web.RequestHandler): | |
def _execute(self, transforms, *args, **kwargs): | |
# following the example of: | |
# https://github.com/bdarnell/tornado_tracing/blob/master/tornado_tracing/recording.py | |
global_data = {} # add whatever here, e.g. self.request | |
with tornado.stack_context.StackContext(functools.partial(ThreadRequestContext, **global_data)): | |
super(RequestContextHandler, self)._execute(transforms, *args, **kwargs) | |
# elsewhere, use ThreadRequestContext.data => a dict |
import threading | |
class ThreadRequestContext(object): | |
"""A context manager that saves some per-thread state globally. | |
Intended for use with Tornado's StackContext. | |
Provide arbitrary data as kwargs upon creation, | |
then use ThreadRequestContext.data to access it. | |
""" | |
_state = threading.local() | |
_state.data = {} | |
class __metaclass__(type): | |
# property() doesn't work on classmethods, | |
# see http://stackoverflow.com/q/128573/1231454 | |
@property | |
def data(cls): | |
if not hasattr(cls._state, 'data'): | |
return {} | |
return cls._state.data | |
def __init__(self, **data): | |
self._data = data | |
def __enter__(self): | |
self._prev_data = self.__class__.data | |
self.__class__._state.data = self._data | |
def __exit__(self, *exc): | |
self.__class__._state.data = self._prev_data | |
del self._prev_data | |
return False |
For which version of Python and Tornado is this for? I'm trying to use this and that just completely fails. The RequestThreadContext.data throws a NameError: data is not a property of the class. The metaclass seems just to not work. I tried to replace it with a class method and change data for data() in my code. It works, but the thread local information is not transmitted across method boundaries. Use of internal undocumented Tornado method (_execute, saw that nowhere) and funky metaclass stuff is likely to bind this to very specific environments.
I'm using Python 3.4.3 and Tornado 3.2.
Hey, sorry for missing these comments -- I didn't realize github doesn't notify on gist comments and mentions don't work. Shoot me a tweet to let me know if you post something new.
likely to bind this to very specific environments.
Ah, yeah. This is working for me in python 2.7.x + tornado 3.2.2, but I haven't tested it elsewhere.
Can you add a practical example of how to use this?
I hook this into a root logging filter, so all logging from the application can have the user id prepended when it's available.
Not work well with coroutine
Those who come by here may want to try https://gist.github.com/virtuald/50bf7cacdc8cfb05e323f350539f0efa instead.
For some reason when I try and use this gist (tornado 4.1) I get this exception:
When I update line 13 to include a
return
I don't get the exception anymore:You think this is the correct fix? Perhaps we can update the gist to reflect this.