2017-06-15 5 views
0

私は、トルネードの要求レベルのコンテキストを設定する方法を探しています。 これは、すべてのログ行(例えばuser_idのような)でいくつかの要求属性を出力する目的でログを出力するのに便利です。 私はweb.RequestHandlerのコンテキストを設定し、この要求が呼び出された他のコルーチンにアクセスしたいと思います。竜巻の要求レベルのコンテキストを使用

class WebRequestHandler(web.RequestHandler): 
    @gen.coroutine 
    def post(self): 
     RequestContext.test_mode = self.application.settings.get('test_mode', False) 
     RequestContext.corr_id = self.request.header.get('X-Request-ID') 

     result = yield some_func() 

     self.write(result) 


@gen.coroutine 
def some_func() 
    if RequestContext.test_mode: 
     print "In test mode" 

    do more async calls 

現在、私は、コードのすべての部分は、右のコンテキストでモニタリングとロギングを行うことができますこの方法を下流に呼び出して、すべての非同期関数にcontextオブジェクト(値がdict)を渡します。 私はよりクリーンでシンプルなソリューションを探しています。

おかげ

アレックス

答えて

0

要求コンテキストの概念が本当に潜在的に同時要求の数百があるかもしれないという単純な事実のために(あなたが大量のトラフィックを持っている場合は特に)、非同期フレームワークでよく保持していませんどの「コンテキスト」を使用するかを判断することが難しくなります。これは、Flask、Falcon、Djangoなどのシーケンシャルフレームワークで動作します。リクエストが1つずつ処理され、どのリクエストを処理しているかを簡単に判断できるからです。

要求の開始と終了の間の機能を処理する好ましい方法は、それぞれprepareon_finishを上書きすることです。

class WebRequestHandler(web.RequestHandler): 

    def prepare(self): 
     print('Logging...prepare') 
     if self.application.settings.get('test_mode', False): 
      print("In test mode") 
     print('X-Request-ID: {0}'.format(self.request.header.get('X-Request-ID'))) 

    @gen.coroutine 
    def post(self): 
     result = yield some_func() 
     self.write(result) 

    def on_finish(self): 
     print('Logging...on_finish') 

簡単な解決策は、リクエストのコンテキストを表すオブジェクトを作成し、それをログ機能に渡すことです。例:

class RequestContext(object): 
    """ 
    Hold request context 
    """ 

class WebRequestHandler(web.RequestHandler): 

    @gen.coroutine 
    def post(self): 
     # create new context obj and fill w/ necessary parameters 
     request_context = RequestContext() 
     request_context.test_mode = self.application.settings.get('test_mode', False) 
     request_context.corr_id = self.request.header.get('X-Request-ID') 

     # pass context objects into coroutine 
     result = yield some_func(request_context) 

     self.write(result) 


@gen.coroutine 
def some_func(request_context) 
    if request_context.test_mode: 
     print "In test mode" 

    # do more async calls 
+0

現在のところ、コンテキストオブジェクト(値付きのdict)をすべての非同期関数呼び出しにプッシュすることで、 'RequestContext'概念を実装しています。 トラフィックが多い場合でも正常に動作します。 Tornadoは 'StackContext'を' yield'から再開できるように管理しています。要求内のすべての 'yield'呼び出しに見える何らかの' GlobalStackContext'を作成する方法があることを望みます。 – AlexV

関連する問題