Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
from __future__ import absolute_import

try:
    from typing import Any
except ImportError:
    pass

from supertenant.consts import (
    INTEGRATION_MODULE_PYTHON_PROCESSTASK,
    RESOURCE_TYPE_PROCESSTASK,
    SPAN_TYPE_SERVER_REQUEST,
)
from supertenant.supermeter.logger import IntegrationModuleLog

_log = IntegrationModuleLog(INTEGRATION_MODULE_PYTHON_PROCESSTASK)

try:
    import atexit
    import os
    import signal
    import sys

    from supertenant.supermeter import _get_brain
    from supertenant.supermeter.data.base import new_base_data
    from supertenant.supermeter.managers.processtask.process_name import get_process_name
    from supertenant.supermeter.scope_manager import scope_manager

    _log.instrumentation_success("")

    SIGTERM_STRATEGY_DEFAULT = 0
    SIGTERM_STRATEGY_FORCE = 1
    SIGTERM_STRATEGY_DISABLE = 2

    sigterm_strategy_var = os.environ.get("SUPERTENANT_SUPERMETER_SIGTERM_STRATEGY", "default").lower()
    sigterm_strategy = SIGTERM_STRATEGY_DEFAULT
    if sigterm_strategy_var in ("y", "yes", "true", "force", "1", "t"):
        sigterm_strategy = SIGTERM_STRATEGY_FORCE
    elif sigterm_strategy_var in ("n", "no", "false", "f", "2", "disable"):
        sigterm_strategy = SIGTERM_STRATEGY_DISABLE
    elif sigterm_strategy_var in ("default", "d", "def"):
        sigterm_strategy = SIGTERM_STRATEGY_DEFAULT
    else:
        _log.error(
            "SUPERTENANT_SUPERMETER_SIGTERM_STRATEGY environment variable has an unsupported value, using default"
        )

    data = new_base_data(RESOURCE_TYPE_PROCESSTASK, INTEGRATION_MODULE_PYTHON_PROCESSTASK, dict())
    data.set_span_type(SPAN_TYPE_SERVER_REQUEST)
    data.set_integration_module_resource_id(get_process_name())

    span_id, _d, _ = scope_manager.open_span(SPAN_TYPE_SERVER_REQUEST, data.get_tags())

    if span_id is not None:
        # set up exit hooks only if we managed to open a span (which means brain is working, etc.)

        def _close_span_and_shutdown():
            # type: () -> None
            global span_id
            # if span_id is None it means we're shutting down.
            if span_id is not None:
                result = scope_manager.close_span(span_id, dict())
                span_id = None
                _log.debug("_close_span_and_shutdown hook", {"result": result})
                brain = _get_brain()
                if brain is not None:
                    brain.shutdown()

        atexit.register(_close_span_and_shutdown)
        _log.debug("registered atexit hook")

        # signal handling is always tricky. since we're in "serverless" mode we're the first ones (hopefully) to be
        # registering a signal handler, so we'll catch SIGTERM if happens and the application didn't register its own
        # handler, and then we're responsible for calling the previous handler, but since the previous handler can be
        # None, we need to re-raise the signal so the process's status code will show that it died from SIGTERM.
        # If the application registers its own handler, the problem is split into two: if it wants to call the
        # previous handler, then it'll call us and then we need to transparently call the original handler (if exists).
        # If it doesn't call the previous handler then it's ok, as long as the application will exit gracefully and then
        # our atexit handler will get called (from Python or Brain).
        _sigterm_default_handler = signal.getsignal(signal.SIGTERM)
        if sigterm_strategy == SIGTERM_STRATEGY_FORCE or (
            sigterm_strategy == SIGTERM_STRATEGY_DEFAULT and _sigterm_default_handler in (None, signal.SIG_DFL)
        ):

            def _sigterm_handler(*args, **kwargs):
                # type: (Any, Any) -> None
                global span_id, _sigterm_default_handler
                we_should_handle_it = signal.getsignal(signal.SIGTERM) == _sigterm_handler
                _close_span_and_shutdown()
                if we_should_handle_it:
                    # restore the original sigterm handler. note that someone can send another signal while we're at it.
                    signal.signal(signal.SIGTERM, _sigterm_default_handler)
                    # re-raise the signal so the previous handler can catch it.
                    os.kill(os.getpid(), signal.SIGTERM)  # py2.7 can't use signal.raise_signal (available from py3.3)
                else:
                    if callable(_sigterm_default_handler):
                        _sigterm_default_handler(*args, **kwargs)
                        return
                    if _sigterm_default_handler == signal.SIG_IGN:
                        return
                    sys.exit(0)

            signal.signal(signal.SIGTERM, _sigterm_handler)
            _log.debug("registered SIGTERM handler")
    else:
        _log.warn("failed to open span")
except Exception as e:
    _log.instrumentation_failed("", {"exc": e})