mirror of
https://github.com/element-hq/synapse
synced 2024-07-03 05:53:36 +00:00
Time CPU time spent in each log context
This commit is contained in:
parent
40da1f200d
commit
43349a7b43
|
@ -77,7 +77,7 @@ def request_handler(request_handler):
|
||||||
global _next_request_id
|
global _next_request_id
|
||||||
request_id = "%s-%s" % (request.method, _next_request_id)
|
request_id = "%s-%s" % (request.method, _next_request_id)
|
||||||
_next_request_id += 1
|
_next_request_id += 1
|
||||||
with LoggingContext(request_id) as request_context:
|
with LoggingContext(request_id, True) as request_context:
|
||||||
request_context.request = request_id
|
request_context.request = request_id
|
||||||
with request.processing():
|
with request.processing():
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -16,10 +16,16 @@ from twisted.internet import defer
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
import logging
|
import logging
|
||||||
|
from resource import getrusage, RUSAGE_SELF
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_cpu_time():
|
||||||
|
return getrusage(RUSAGE_SELF).ru_utime * 1000
|
||||||
|
|
||||||
|
|
||||||
class LoggingContext(object):
|
class LoggingContext(object):
|
||||||
"""Additional context for log formatting. Contexts are scoped within a
|
"""Additional context for log formatting. Contexts are scoped within a
|
||||||
"with" block. Contexts inherit the state of their parent contexts.
|
"with" block. Contexts inherit the state of their parent contexts.
|
||||||
|
@ -27,7 +33,10 @@ class LoggingContext(object):
|
||||||
name (str): Name for the context for debugging.
|
name (str): Name for the context for debugging.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = ["parent_context", "name", "__dict__"]
|
__slots__ = [
|
||||||
|
"parent_context", "name", "__dict__", "cpu_time", "_current_cpu_time",
|
||||||
|
"_log_time"
|
||||||
|
]
|
||||||
|
|
||||||
thread_local = threading.local()
|
thread_local = threading.local()
|
||||||
|
|
||||||
|
@ -42,11 +51,20 @@ class LoggingContext(object):
|
||||||
def copy_to(self, record):
|
def copy_to(self, record):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def resume(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
pass
|
||||||
|
|
||||||
sentinel = Sentinel()
|
sentinel = Sentinel()
|
||||||
|
|
||||||
def __init__(self, name=None):
|
def __init__(self, name=None, log_time=False):
|
||||||
self.parent_context = None
|
self.parent_context = None
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.cpu_time = 0
|
||||||
|
self._current_cpu_time = 0
|
||||||
|
self._log_time = log_time
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s@%x" % (self.name, id(self))
|
return "%s@%x" % (self.name, id(self))
|
||||||
|
@ -62,6 +80,7 @@ class LoggingContext(object):
|
||||||
raise Exception("Attempt to enter logging context multiple times")
|
raise Exception("Attempt to enter logging context multiple times")
|
||||||
self.parent_context = self.current_context()
|
self.parent_context = self.current_context()
|
||||||
self.thread_local.current_context = self
|
self.thread_local.current_context = self
|
||||||
|
self.resume()
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, type, value, traceback):
|
||||||
|
@ -79,9 +98,24 @@ class LoggingContext(object):
|
||||||
self.thread_local.current_context,
|
self.thread_local.current_context,
|
||||||
self
|
self
|
||||||
)
|
)
|
||||||
|
self.pause()
|
||||||
|
|
||||||
|
if self._log_time:
|
||||||
|
logger.info("Elapsed CPU time: %d %r", self.cpu_time, self.name)
|
||||||
|
|
||||||
self.thread_local.current_context = self.parent_context
|
self.thread_local.current_context = self.parent_context
|
||||||
self.parent_context = None
|
self.parent_context = None
|
||||||
|
|
||||||
|
def resume(self):
|
||||||
|
if self._log_time:
|
||||||
|
self._current_cpu_time = _get_cpu_time()
|
||||||
|
|
||||||
|
def pause(self):
|
||||||
|
if self._log_time:
|
||||||
|
now = _get_cpu_time()
|
||||||
|
self.cpu_time += now - self._current_cpu_time
|
||||||
|
self._current_cpu_time = now
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
"""Delegate member lookup to parent context"""
|
"""Delegate member lookup to parent context"""
|
||||||
return getattr(self.parent_context, name)
|
return getattr(self.parent_context, name)
|
||||||
|
@ -121,15 +155,24 @@ class PreserveLoggingContext(object):
|
||||||
exited. Used to restore the context after a function using
|
exited. Used to restore the context after a function using
|
||||||
@defer.inlineCallbacks is resumed by a callback from the reactor."""
|
@defer.inlineCallbacks is resumed by a callback from the reactor."""
|
||||||
|
|
||||||
__slots__ = ["current_context"]
|
__slots__ = ["current_context", "inner_context"]
|
||||||
|
|
||||||
|
def __init__(self, inner_context=LoggingContext.sentinel):
|
||||||
|
object.__setattr__(self, "inner_context", inner_context)
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
"""Captures the current logging context"""
|
"""Captures the current logging context"""
|
||||||
self.current_context = LoggingContext.current_context()
|
self.current_context = LoggingContext.current_context()
|
||||||
LoggingContext.thread_local.current_context = LoggingContext.sentinel
|
LoggingContext.thread_local.current_context = self.inner_context
|
||||||
|
|
||||||
|
self.current_context.pause()
|
||||||
|
self.inner_context.resume()
|
||||||
|
|
||||||
def __exit__(self, type, value, traceback):
|
def __exit__(self, type, value, traceback):
|
||||||
"""Restores the current logging context"""
|
"""Restores the current logging context"""
|
||||||
|
self.inner_context.pause()
|
||||||
|
self.current_context.resume()
|
||||||
|
|
||||||
LoggingContext.thread_local.current_context = self.current_context
|
LoggingContext.thread_local.current_context = self.current_context
|
||||||
|
|
||||||
if self.current_context is not LoggingContext.sentinel:
|
if self.current_context is not LoggingContext.sentinel:
|
||||||
|
@ -164,8 +207,7 @@ class _PreservingContextDeferred(defer.Deferred):
|
||||||
|
|
||||||
def _wrap_callback(self, f):
|
def _wrap_callback(self, f):
|
||||||
def g(res, *args, **kwargs):
|
def g(res, *args, **kwargs):
|
||||||
with PreserveLoggingContext():
|
with PreserveLoggingContext(self._log_context):
|
||||||
LoggingContext.thread_local.current_context = self._log_context
|
|
||||||
res = f(res, *args, **kwargs)
|
res = f(res, *args, **kwargs)
|
||||||
return res
|
return res
|
||||||
return g
|
return g
|
||||||
|
|
Loading…
Reference in a new issue