title: How to use request_id while logging in asynchronous functions?
body: <p>In asynchronous functions, every logger statement is getting their own request_id.</p>
  
  <pre><code>import logging
  log = logging.getLogger('test_logger')
  
  def sync_fun():
      log.info("test 1")
      log.info("test 2")
      log.info("test 3")
  
  @after_response.enable
  def async_fun():
      log.info("test 1")
      log.info("test 2")
      log.info("test 3")    
  
  output of sync_fun:
  [06/Nov/2019 10:42:00.234] [None] [130C6C47F1E24164AAC0440C719630] [INFO] Test 1
  [06/Nov/2019 10:42:00.234] [None] [130C6C47F1E24164AAC0440C719630] [INFO] Test 2
  [06/Nov/2019 10:42:00.234] [None] [130C6C47F1E24164AAC0440C719630] [INFO] Test 3
  </code></pre>
  
  <p>130C6C47F1E24164AAC0440C719630 is a request_id and it's common for all logger statements.</p>
  
  <pre><code>output of async_fun:
  [06/Nov/2019 10:42:00.234] [None] [AB352B8F2DF9459ABDD2FBF51EB05F] [INFO] Test 1
  [06/Nov/2019 10:42:00.234] [None] [V9E9B6DF5F9C442195EA7C1379FBFA] [INFO] Test 2
  [06/Nov/2019 10:42:00.234] [None] [DCA311A92724443C9AD7E951288917] [INFO] Test 3
  </code></pre>
  
  <p>async_fun is an asynchronous function and request ids are different for all logger statements.</p>
  
  <p><strong>How do i get the same request_id for each logger statements in asynchronous function.</strong></p>
  
  <p>I have created logging filter. Here i am generating request_id. And same request id is used while logging.</p>
  
  <pre><code>from threading import local
  _thread_locals = local()
  
  class LoggingMiddleware(object):
      def process_request(self, request):
          if request.user.username:
              _thread_locals.user = request.user.username
              _thread_locals.user_email = request.user.email
              _thread_locals.user_id = request.user.id
          #assign request id to all requests (to track cron requests also)
          _thread_locals.request_id = str(uuid.uuid4().get_hex().upper()[0:30])
  
  
      def process_response(self, request, response):
          if hasattr(_thread_locals, 'user'):
              del _thread_locals.user
          if hasattr(_thread_locals, 'request_id'):
              del _thread_locals.request_id
          if hasattr(_thread_locals, 'user_email'):
              del _thread_locals.user_email
          if hasattr(_thread_locals, 'user_id'):
              del _thread_locals.user_id
          return response
  
      def process_exception(self, request, exception):
          logger.exception('unhandled error - ')
  
  def get_current_user_details():
      user_details = {
          'username': getattr(_thread_locals, 'user', None),
          'email' : getattr(_thread_locals, 'user_email', None),
          'id' : getattr(_thread_locals, 'user_id', None)
      }
      return user_details
  
  def get_current_user():
      return getattr(_thread_locals, 'user', None)
  
  def get_current_request_id():
      return getattr(_thread_locals, 'request_id', None)
  
  class RequestIDFilter(logging.Filter):
      def filter(self, record):
          current_user = get_current_user()
          current_request_id = get_current_request_id()
          record.user = current_user if current_user else None
          record.request_id = current_request_id if current_request_id else str(uuid.uuid4().get_hex().upper()[0:30])
          return True
  </code></pre>