From f7706fe1595b5ad2617fd567678ca30d76f0da37 Mon Sep 17 00:00:00 2001 From: Peter Giacomo Lombardo Date: Wed, 18 Dec 2019 15:19:25 +0000 Subject: [PATCH 1/3] Add uWSGI postfork hook support --- instana/__init__.py | 3 +++ instana/hooks/__init__.py | 0 instana/hooks/hook_uwsgi.py | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+) create mode 100644 instana/hooks/__init__.py create mode 100644 instana/hooks/hook_uwsgi.py diff --git a/instana/__init__.py b/instana/__init__.py index 476e0df0..03a26c19 100644 --- a/instana/__init__.py +++ b/instana/__init__.py @@ -53,6 +53,7 @@ def boot_agent(): import instana.singletons + # Instrumentation if "INSTANA_DISABLE_AUTO_INSTR" not in os.environ: # Import & initialize instrumentation if sys.version_info >= (3, 5, 3): @@ -81,6 +82,8 @@ def boot_agent(): from .instrumentation import urllib3 from .instrumentation.django import middleware + # Hooks + from .hooks import hook_uwsgi if "INSTANA_MAGIC" in os.environ: pkg_resources.working_set.add_entry("/tmp/instana/python") diff --git a/instana/hooks/__init__.py b/instana/hooks/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/instana/hooks/hook_uwsgi.py b/instana/hooks/hook_uwsgi.py new file mode 100644 index 00000000..d74bcfed --- /dev/null +++ b/instana/hooks/hook_uwsgi.py @@ -0,0 +1,18 @@ +from __future__ import absolute_import + +from ..log import logger +from ..singletons import agent + +try: + import uwsgidecorators + + @uwsgidecorators.postfork + def uwsgi_handle_fork(): + """ This is our uWSGI hook to detect and act when worker processes are forked off. """ + logger.debug("Handling uWSGI fork...") + agent.handle_fork() + + logger.debug("Applied uWSGI hooks") +except ImportError as e: + logger.debug('uwsgi hooks: decorators not available') + pass \ No newline at end of file From 6866d159a40a9853543620b0ededa3cad3e61fc7 Mon Sep 17 00:00:00 2001 From: Peter Giacomo Lombardo Date: Thu, 19 Dec 2019 10:41:17 +0000 Subject: [PATCH 2/3] Immediate reset on fork and hook cleanup --- instana/agent.py | 2 +- instana/fsm.py | 8 ++------ instana/hooks/hook_uwsgi.py | 25 ++++++++++++++++++------- 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/instana/agent.py b/instana/agent.py index dca1da33..9db01f38 100644 --- a/instana/agent.py +++ b/instana/agent.py @@ -154,7 +154,7 @@ def announce(self, discovery): """ try: url = self.__discovery_url() - logger.debug("making announce request to %s", url) + # logger.debug("making announce request to %s", url) response = None response = self.client.put(url, data=to_json(discovery), diff --git a/instana/fsm.py b/instana/fsm.py index 62149887..e1b7c80f 100644 --- a/instana/fsm.py +++ b/instana/fsm.py @@ -90,12 +90,8 @@ def reset(self): :return: void """ - logger.debug("State machine being reset. Will schedule new announce cycle 6 seconds from now.") - - self.timer = t.Timer(6, self.fsm.lookup) - self.timer.daemon = True - self.timer.name = self.THREAD_NAME - self.timer.start() + logger.debug("State machine being reset. Will start a new announce cycle.") + self.fsm.lookup() def lookup_agent_host(self, e): self.agent.should_threads_shutdown.clear() diff --git a/instana/hooks/hook_uwsgi.py b/instana/hooks/hook_uwsgi.py index d74bcfed..65b641a6 100644 --- a/instana/hooks/hook_uwsgi.py +++ b/instana/hooks/hook_uwsgi.py @@ -1,18 +1,29 @@ +""" +The uwsgi and uwsgidecorators packages are added automatically to the Python environment +when running under uWSGI. Here we attempt to detect the presence of these packages and +then use the appropriate hooks. +""" from __future__ import absolute_import from ..log import logger from ..singletons import agent try: + import uwsgi import uwsgidecorators - @uwsgidecorators.postfork - def uwsgi_handle_fork(): - """ This is our uWSGI hook to detect and act when worker processes are forked off. """ - logger.debug("Handling uWSGI fork...") - agent.handle_fork() + logger.warn("uWSGI options: %s", uwsgi.opt) - logger.debug("Applied uWSGI hooks") + if 'lazy-apps' not in uwsgi.opt or uwsgi.opt['lazy-apps'] is not True: + @uwsgidecorators.postfork + def uwsgi_handle_fork(): + """ This is our uWSGI hook to detect and act when worker processes are forked off. """ + logger.debug("Handling uWSGI fork...") + agent.handle_fork() + + logger.debug("Applied uWSGI hooks") + else: + logger.debug("uWSGI lazy-apps enabled. Not applying postfork hooks") except ImportError as e: logger.debug('uwsgi hooks: decorators not available') - pass \ No newline at end of file + pass From f55e32dc5c3593e7cc46301aad70002eca822e69 Mon Sep 17 00:00:00 2001 From: Peter Giacomo Lombardo Date: Thu, 19 Dec 2019 12:30:26 +0000 Subject: [PATCH 3/3] More refinements: add thread disabled warning --- instana/hooks/hook_uwsgi.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/instana/hooks/hook_uwsgi.py b/instana/hooks/hook_uwsgi.py index 65b641a6..5af1a27a 100644 --- a/instana/hooks/hook_uwsgi.py +++ b/instana/hooks/hook_uwsgi.py @@ -10,11 +10,20 @@ try: import uwsgi - import uwsgidecorators + logger.debug("uWSGI options: %s", uwsgi.opt) - logger.warn("uWSGI options: %s", uwsgi.opt) + opt_master = uwsgi.opt.get('master', False) + opt_lazy_apps = uwsgi.opt.get('lazy-apps', False) + + if uwsgi.opt.get('enable-threads', False) is False: + logger.warn("Required: uWSGI threads are not enabled. " + + "Please enable by using the uWSGI --enable-threads option.") + + if opt_master and opt_lazy_apps is False: + # --master is supplied in uWSGI options (otherwise uwsgidecorators package won't be available) + # When --lazy-apps is True, this postfork hook isn't needed + import uwsgidecorators - if 'lazy-apps' not in uwsgi.opt or uwsgi.opt['lazy-apps'] is not True: @uwsgidecorators.postfork def uwsgi_handle_fork(): """ This is our uWSGI hook to detect and act when worker processes are forked off. """ @@ -23,7 +32,7 @@ def uwsgi_handle_fork(): logger.debug("Applied uWSGI hooks") else: - logger.debug("uWSGI lazy-apps enabled. Not applying postfork hooks") + logger.debug("uWSGI --master=%s --lazy-apps=%s: postfork hooks not applied", opt_master, opt_lazy_apps) except ImportError as e: - logger.debug('uwsgi hooks: decorators not available') + logger.debug('uwsgi hooks: decorators not available: %s', e) pass