Scope manager using LogContexts

We piggy-back our tracer scopes by using log context.
The current log context gives us the current scope. If new scope is
created we create a stack of scopes in the context.
pull/5544/head
Jorik Schellekens 2019-06-21 12:10:20 +01:00
parent 5afd89a546
commit b43e3af744
2 changed files with 93 additions and 2 deletions

View File

@ -164,6 +164,7 @@ class LoggingContext(object):
"usage_start",
"main_thread", "alive",
"request", "tag",
"active_scope"
]
thread_local = threading.local()
@ -215,6 +216,7 @@ class LoggingContext(object):
self.request = None
self.tag = ""
self.alive = True
self.active_scope = None
self.parent_context = parent_context
@ -299,10 +301,12 @@ class LoggingContext(object):
another LoggingContext
"""
# 'request' is the only field we currently use in the logger, so that's
# all we need to copy
# we track the current request
record.request = self.request
# we also track the current active_scope:
record.active_scope = self.active_scope
def start(self):
if threading.current_thread() is not self.main_thread:
logger.warning("Started logcontext %s on different thread", self)

View File

@ -0,0 +1,87 @@
from .logcontext import LoggingContext
from opentracing import ScopeManager, Scope
import logging
logger = logging.getLogger(__name__)
class LogContextScopeManager(ScopeManager):
_homeserver_whitelist = ["*"]
_user_whitelist = ["*"]
def __init__(self, config):
# Set the whitelists
logger.info(config.tracer_config)
_homeserver_whitelist = config.tracer_config["homeserver_whitelist"]
_user_whitelist = config.tracer_config["user_whitelist"]
@property
def active(self):
"""
Returns the currently active Scope which can be used to access the
currently active Scope.span.
If there is a non-null Scope, its wrapped Span
becomes an implicit parent of any newly-created Span at
Tracer.start_active_span() time.
Return:
(Scope) : the Scope that is active, or None if not
available.
"""
ctx = LoggingContext.current_context()
if ctx is LoggingContext.sentinel or ctx.active_scope is None:
return None
else:
return ctx.active_scope
def activate(self, span, finish_on_close):
"""
Makes a Span active.
Args
span (Span): the span that should become active.
finish_on_close (Boolean): whether Span should be automatically
finished when Scope.close() is called.
Return:
Scope to control the end of the active period for
*span*. It is a programming error to neglect to call
Scope.close() on the returned instance.
"""
logger.info("activating scope")
ctx = LoggingContext.current_context()
if ctx is LoggingContext.sentinel:
# We don't want this scope to affect.
logger.warning("Tried to activate scope outside of loggingcontext")
return Scope(None, span)
scope = _LogContextScope(self, span, finish_on_close)
self._set_logcontext_scope(scope, ctx)
return scope
def _set_logcontext_scope(self, scope, ctx=None):
if ctx is None:
ctx = LoggingContext.current_context()
ctx.active_scope = scope
def request_from_whitelisted_homeserver(self, request):
pass
def user_whitelisted(self, request):
pass
class _LogContextScope(Scope):
def __init__(self, manager, span, finish_on_close):
super(_LogContextScope, self).__init__(manager, span)
self._finish_on_close = finish_on_close
self._to_restore = manager.active
def close(self):
if self.manager.active is not self:
logger.warning("Tried to close a none active scope!")
return
self.manager._set_logcontext_scope(self._to_restore)
if self._finish_on_close:
self.span.finish()