Canonical pattern for storing global request data with StackContext

743 views
Skip to first unread message

Simon Weber

unread,
Dec 2, 2013, 2:17:01 PM12/2/13
to python-...@googlegroups.com
I'm looking to make some Tornado request data available globally for logging context. There have been a few previous discussions on this topic, and it looks like a StackContext is the solution:
For posterity's sake, can we document the right way to go about this? Here's my attempt, based on reading the previous topics: https://gist.github.com/simon-weber/7755289. Can somebody please look this over?

For what it's worth, I'm well aware that keeping this data global isn't great practice, but I think logging context is a reasonable motivation.

Ben Darnell

unread,
Dec 3, 2013, 11:23:51 AM12/3/13
to Tornado Mailing List
On Mon, Dec 2, 2013 at 2:17 PM, Simon Weber <swe...@gmail.com> wrote:
I'm looking to make some Tornado request data available globally for logging context. There have been a few previous discussions on this topic, and it looks like a StackContext is the solution:
For posterity's sake, can we document the right way to go about this? Here's my attempt, based on reading the previous topics: https://gist.github.com/simon-weber/7755289. Can somebody please look this over?

This looks correct to me. One question: why use a property on the metaclass instead of a @classmethod on the ThreadRequestContext class?

-Ben
 

For what it's worth, I'm well aware that keeping this data global isn't great practice, but I think logging context is a reasonable motivation.

--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornad...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Simon Weber

unread,
Dec 3, 2013, 11:49:00 AM12/3/13
to python-...@googlegroups.com, b...@bendarnell.com
That's how I had originally wrote it, but property() doesn't work out of the box with class methods. As for why I chose the metaclass solution instead of rewriting property(), I just think the former makes more sense (by following the instance < class < metaclass hierarchy).

Anywho, good to hear I got it mostly correct! Thanks for looking it over.

I've just got a few quick things I'm specifically concerned about:
  • my understanding of StackContexts is that they're a way to hook entering/exiting Tornado "context switches". Based on this, is there any way to "re-enter" a Context? i.e. are __enter__/__exit__ guaranteed to be called one time each?
  • will this work with async Handlers?
  • will the Contexts be free for garbage collection after the request is finished?
  • is there any sane way to test this? I was thinking I'd have to make my own IOLoop implementation to force ordering of events and verify the global data while single-stepping through them.

Ben Darnell

unread,
Dec 3, 2013, 11:59:52 AM12/3/13
to Simon Weber, Tornado Mailing List
On Tue, Dec 3, 2013 at 11:49 AM, Simon Weber <swe...@gmail.com> wrote:
That's how I had originally wrote it, but property() doesn't work out of the box with class methods. As for why I chose the metaclass solution instead of rewriting property(), I just think the former makes more sense (by following the instance < class < metaclass hierarchy).


Ah, got it.
 
Anywho, good to hear I got it mostly correct! Thanks for looking it over.

I've just got a few quick things I'm specifically concerned about:
  • my understanding of StackContexts is that they're a way to hook entering/exiting Tornado "context switches". Based on this, is there any way to "re-enter" a Context? i.e. are __enter__/__exit__ guaranteed to be called one time each?

Each StackContext instance will only be entered/exited once; a new StackContext object will be created for each "context switch"
 
  • will this work with async Handlers?

Yes; that's the whole point.  
 
  • will the Contexts be free for garbage collection after the request is finished?

Yes.  More precisely, the StackContext instances should be freed as soon as their exit method is called and a new set of contexts has been allocated.  The context factory (i.e. the functools.partial you pass to the initial StackContext object, which holds a reference to the data payload) will be collectable once all the callbacks that might restore this context have been collected.
 
  • is there any sane way to test this? I was thinking I'd have to make my own IOLoop implementation to force ordering of events and verify the global data while single-stepping through them.

You shouldn't need a custom IOLoop implementation to force event ordering - you can interleave events in a deterministic order with the standard IOLoop methods.  It's a delicate process though and I'd probably recommend just trusting that the underlying StackContext implementation works instead of spending too much time testing this in your own application.  See https://github.com/facebook/tornado/blob/master/tornado/test/stack_context_test.py

-Ben

Simon Weber

unread,
Dec 3, 2013, 12:04:47 PM12/3/13
to python-...@googlegroups.com, Simon Weber, b...@bendarnell.com
Great; thanks so much for the speedy replies!
Reply all
Reply to author
Forward
0 new messages