Propagate profiler info into BatchNotifier threads

While working on improving the osprofiler report in neutron I'm finding
various places where the profiling can be extended by propagating the
profiler info further then before.

This change starts to profile BatchNotifier threads (e.g. various
callbacks to nova) when the code starting the thread was already
profiled (it's not at the moment, but that will be another change).

In this change we use osprofiler.profiler.clean(). Since that has became
part of the public interface of osprofiler in version 2.3.0, we bump
osprofiler version to 2.3.0 both in lower-constraints and requirements.

Change-Id: Ibd08e097b6f8457c50f8ba9e4a63b96e7e3182bc
Partial-Bug: #1833674
This commit is contained in:
Bence Romsics
2019-06-20 12:10:21 +02:00
parent ba436615b0
commit 45e59e3a18
6 changed files with 106 additions and 3 deletions

View File

@@ -43,6 +43,7 @@ from oslo_config import cfg
from oslo_db import exception as db_exc
from oslo_log import log as logging
from oslo_utils import excutils
from osprofiler import profiler
import pkg_resources
import neutron
@@ -917,3 +918,47 @@ class Timer(object):
@property
def delta_time_sec(self):
return (datetime.datetime.now() - self.start).total_seconds()
def _collect_profiler_info():
p = profiler.get()
if p:
return {
"hmac_key": p.hmac_key,
"base_id": p.get_base_id(),
"parent_id": p.get_id(),
}
def spawn(func, *args, **kwargs):
"""As eventlet.spawn() but with osprofiler initialized in the new threads
osprofiler stores the profiler instance in thread local storage, therefore
in new threads (including eventlet threads) osprofiler comes uninitialized
by default. This spawn() is a stand-in replacement for eventlet.spawn()
but we re-initialize osprofiler in threads spawn()-ed.
"""
profiler_info = _collect_profiler_info()
@functools.wraps(func)
def wrapper(*args, **kwargs):
if profiler_info:
profiler.init(**profiler_info)
return func(*args, **kwargs)
return eventlet.spawn(wrapper, *args, **kwargs)
def spawn_n(func, *args, **kwargs):
"""See spawn() above"""
profiler_info = _collect_profiler_info()
@functools.wraps(func)
def wrapper(*args, **kwargs):
if profiler_info:
profiler.init(**profiler_info)
return func(*args, **kwargs)
return eventlet.spawn_n(wrapper, *args, **kwargs)