예제 #1
0
def test_is_recording(enabled, recording, is_recording):
    c = Config(inline_dict={
        "enabled": enabled,
        "recording": recording,
        "service_name": "foo"
    })
    assert c.is_recording is is_recording
예제 #2
0
def test_tag_with_non_string_value():
    requests_store = Tracer(lambda: [],
                            lambda: [],
                            lambda *args: None,
                            config=Config(),
                            agent=None)
    t = requests_store.begin_transaction("test")
    elasticapm.tag(foo=1)
    requests_store.end_transaction(200, "test")
    assert t.labels == {"foo": "1"}
예제 #3
0
def test_tag_transaction():
    requests_store = Tracer(lambda: [], lambda: [], lambda *args: None, Config(), None)
    transaction = requests_store.begin_transaction("test")
    elasticapm.tag(foo="bar")
    transaction.tag(baz="bazzinga")
    requests_store.end_transaction(200, "test")

    assert transaction.labels == {"foo": "bar", "baz": "bazzinga"}
    transaction_dict = transaction.to_dict()
    assert transaction_dict["context"]["tags"] == {"foo": "bar", "baz": "bazzinga"}
예제 #4
0
def test_config_precedence():
    #  precedence order: environment, inline dict, config dict
    with mock.patch.dict("os.environ", {"ELASTIC_APM_SERVICE_NAME": "bar"}):
        config = Config(
            {"SERVICE_NAME": "foo", "SECRET_TOKEN": "secret", "COLLECT_LOCAL_VARIABLES": "all"},
            inline_dict={"secret_token": "notsecret", "service_name": "baz"},
        )

    assert config.service_name == "bar"
    assert config.secret_token == "notsecret"
    assert config.collect_local_variables == "all"
def test_config_precedence():
    #  precendece order: config dict, environment, default dict
    with mock.patch.dict('os.environ', {
        'ELASTIC_APM_SERVICE_NAME': 'bar',
        'ELASTIC_APM_SECRET_TOKEN': 'secret'
    }):
        config = Config({
            'SERVICE_NAME': 'foo',
        }, default_dict={'secret_token': 'notsecret'})

    assert config.service_name == 'foo'
    assert config.secret_token == 'secret'
예제 #6
0
def test_label_with_allowed_non_string_value():
    requests_store = Tracer(lambda: [], lambda: [], lambda *args: None,
                            Config(), None)
    t = requests_store.begin_transaction("test")
    elasticapm.label(foo=1, bar=True, baz=1.1, bazzinga=decimal.Decimal("1.1"))
    requests_store.end_transaction(200, "test")
    assert t.labels == {
        "foo": 1,
        "bar": True,
        "baz": 1.1,
        "bazzinga": decimal.Decimal("1.1")
    }
예제 #7
0
def test_label_with_not_allowed_non_string_value():
    class SomeType(object):
        def __str__(self):
            return "ok"

        def __unicode__(self):
            return u"ok"

    requests_store = Tracer(lambda: [], lambda: [], lambda *args: None, Config(), None)
    t = requests_store.begin_transaction("test")
    elasticapm.label(foo=SomeType())
    requests_store.end_transaction(200, "test")
    assert t.labels == {"foo": "ok"}
예제 #8
0
    def __init__(self, config=None, **defaults):
        # configure loggers first
        cls = self.__class__
        self.logger = logging.getLogger('%s.%s' % (cls.__module__, cls.__name__))
        self.error_logger = logging.getLogger('elasticapm.errors')
        self.state = ClientState()

        self.instrumentation_store = None
        self.processors = []
        self.filter_exception_types_dict = {}
        self._send_timer = None
        self._transports = {}
        self._service_info = None

        self.config = Config(config, default_dict=defaults)
        if self.config.errors:
            for msg in self.config.errors.values():
                self.error_logger.error(msg)
            self.config.disable_send = True
            return

        self._transport_class = import_string(self.config.transport_class)

        for exc_to_filter in (self.config.filter_exception_types or []):
            exc_to_filter_type = exc_to_filter.split(".")[-1]
            exc_to_filter_module = ".".join(exc_to_filter.split(".")[:-1])
            self.filter_exception_types_dict[exc_to_filter_type] = exc_to_filter_module

        self.processors = [import_string(p) for p in self.config.processors] if self.config.processors else []

        self.instrumentation_store = TransactionsStore(
            lambda: self._get_stack_info_for_trace(
                stacks.iter_stack_frames(),
                library_frame_context_lines=self.config.source_lines_span_library_frames,
                in_app_frame_context_lines=self.config.source_lines_span_app_frames,
                with_locals=self.config.collect_local_variables in ('all', 'transactions'),
                locals_processor_func=lambda local_var: varmap(lambda k, v: shorten(
                    v,
                    list_length=self.config.local_var_list_max_length,
                    string_length=self.config.local_var_max_length,
                ), local_var)
            ),
            collect_frequency=self.config.flush_interval,
            sample_rate=self.config.transaction_sample_rate,
            max_spans=self.config.transaction_max_spans,
            max_queue_size=self.config.max_queue_size,
            ignore_patterns=self.config.transactions_ignore_patterns,
        )
        self.include_paths_re = stacks.get_path_regex(self.config.include_paths) if self.config.include_paths else None
        self.exclude_paths_re = stacks.get_path_regex(self.config.exclude_paths) if self.config.exclude_paths else None
        compat.atexit_register(self.close)
def test_config_defaults_dict():
    config = Config(default_dict={
        'service_name': 'foo',
        'secret_token': 'bar',
        'server_url': 'http://example.com:1234',
        'service_version': '1',
        'hostname': 'localhost',
        'flush_interval': '5',
    })

    assert config.service_name == 'foo'
    assert config.secret_token == 'bar'
    assert config.server_url == 'http://example.com:1234'
    assert config.service_version == '1'
    assert config.hostname == 'localhost'
    assert config.flush_interval == 5
예제 #10
0
def test_config_dict():
    config = Config({
        'SERVICE_NAME': 'foo',
        'SECRET_TOKEN': 'bar',
        'SERVER_URL': 'http://example.com:1234',
        'SERVICE_VERSION': 1,
        'HOSTNAME': 'localhost',
        'FLUSH_INTERVAL': '5'
    })

    assert config.service_name == 'foo'
    assert config.secret_token == 'bar'
    assert config.server_url == 'http://example.com:1234'
    assert config.service_version == '1'
    assert config.hostname == 'localhost'
    assert config.flush_interval == 5
예제 #11
0
def test_config_dict():
    config = Config({
        'SERVICE_NAME': 'foo',
        'SECRET_TOKEN': 'bar',
        'SERVER_URL': 'http://example.com:1234',
        'APP_VERSION': 1,
        'HOSTNAME': 'localhost',
        'TRACES_SEND_FREQ': '5'
    })

    assert config.service_name == 'foo'
    assert config.secret_token == 'bar'
    assert config.server_url == 'http://example.com:1234'
    assert config.app_version == '1'
    assert config.hostname == 'localhost'
    assert config.transaction_send_frequency == 5
예제 #12
0
def test_config_dict():
    config = Config({
        "SERVICE_NAME": "foo",
        "SECRET_TOKEN": "bar",
        "SERVER_URL": "http://example.com:1234",
        "SERVICE_VERSION": 1,
        "HOSTNAME": "localhost",
        "API_REQUEST_TIME": "5s",
    })

    assert config.service_name == "foo"
    assert config.secret_token == "bar"
    assert config.server_url == "http://example.com:1234"
    assert config.service_version == "1"
    assert config.hostname == "localhost"
    assert config.api_request_time == 5000
예제 #13
0
def test_config_defaults_dict():
    config = Config(
        default_dict={
            'service_name': 'foo',
            'secret_token': 'bar',
            'server_url': 'http://example.com:1234',
            'app_version': '1',
            'hostname': 'localhost',
            'transaction_send_frequency': '5',
        })

    assert config.service_name == 'foo'
    assert config.secret_token == 'bar'
    assert config.server_url == 'http://example.com:1234'
    assert config.app_version == '1'
    assert config.hostname == 'localhost'
    assert config.transaction_send_frequency == 5
예제 #14
0
def test_config_inline_dict():
    config = Config(
        inline_dict={
            "service_name": "foo",
            "secret_token": "bar",
            "server_url": "http://example.com:1234",
            "service_version": "1",
            "hostname": "localhost",
            "api_request_time": "5s",
        })

    assert config.service_name == "foo"
    assert config.secret_token == "bar"
    assert config.server_url == "http://example.com:1234"
    assert config.service_version == "1"
    assert config.hostname == "localhost"
    assert config.api_request_time == 5000
예제 #15
0
def test_config_dict():
    config = Config(
        {
            "SERVICE_NAME": "foo",
            "SECRET_TOKEN": "bar",
            "SERVER_URL": "http://example.com:1234",
            "SERVICE_VERSION": 1,
            "HOSTNAME": "localhost",
            "FLUSH_INTERVAL": "5",
        }
    )

    assert config.service_name == "foo"
    assert config.secret_token == "bar"
    assert config.server_url == "http://example.com:1234"
    assert config.service_version == "1"
    assert config.hostname == "localhost"
    assert config.flush_interval == 5
예제 #16
0
def test_config_environment():
    with mock.patch.dict('os.environ', {
        'ELASTIC_APM_SERVICE_NAME': 'foo',
        'ELASTIC_APM_SECRET_TOKEN': 'bar',
        'ELASTIC_APM_SERVER_URL': 'http://example.com:1234',
        'ELASTIC_APM_SERVICE_VERSION': '1',
        'ELASTIC_APM_HOSTNAME': 'localhost',
        'ELASTIC_APM_FLUSH_INTERVAL': '5',
        'ELASTIC_APM_AUTO_LOG_STACKS': 'false',
    }):
        config = Config()

        assert config.service_name == 'foo'
        assert config.secret_token == 'bar'
        assert config.server_url == 'http://example.com:1234'
        assert config.service_version == '1'
        assert config.hostname == 'localhost'
        assert config.flush_interval == 5
        assert config.auto_log_stacks == False
예제 #17
0
def test_config_environment():
    with mock.patch.dict(
            'os.environ', {
                'ELASTIC_APM_SERVICE_NAME': 'foo',
                'ELASTIC_APM_SECRET_TOKEN': 'bar',
                'ELASTIC_APM_SERVER_URL': 'http://example.com:1234',
                'ELASTIC_APM_APP_VERSION': '1',
                'ELASTIC_APM_HOSTNAME': 'localhost',
                'ELASTIC_APM_TRACES_SEND_FREQ': '5',
                'ELASTIC_APM_AUTO_LOG_STACKS': 'false',
            }):
        config = Config()

        assert config.service_name == 'foo'
        assert config.secret_token == 'bar'
        assert config.server_url == 'http://example.com:1234'
        assert config.app_version == '1'
        assert config.hostname == 'localhost'
        assert config.transaction_send_frequency == 5
        assert config.auto_log_stacks == False
예제 #18
0
def test_config_environment():
    with mock.patch.dict(
            "os.environ",
        {
            "ELASTIC_APM_SERVICE_NAME": "foo",
            "ELASTIC_APM_SECRET_TOKEN": "bar",
            "ELASTIC_APM_SERVER_URL": "http://example.com:1234",
            "ELASTIC_APM_SERVICE_VERSION": "1",
            "ELASTIC_APM_HOSTNAME": "localhost",
            "ELASTIC_APM_API_REQUEST_TIME": "5s",
            "ELASTIC_APM_AUTO_LOG_STACKS": "false",
        },
    ):
        config = Config()

        assert config.service_name == "foo"
        assert config.secret_token == "bar"
        assert config.server_url == "http://example.com:1234"
        assert config.service_version == "1"
        assert config.hostname == "localhost"
        assert config.api_request_time == 5000
        assert config.auto_log_stacks is False
예제 #19
0
def test_config_environment():
    with mock.patch.dict(
        "os.environ",
        {
            "ELASTIC_APM_SERVICE_NAME": "foo",
            "ELASTIC_APM_SECRET_TOKEN": "bar",
            "ELASTIC_APM_SERVER_URL": "http://example.com:1234",
            "ELASTIC_APM_SERVICE_VERSION": "1",
            "ELASTIC_APM_HOSTNAME": "localhost",
            "ELASTIC_APM_FLUSH_INTERVAL": "5",
            "ELASTIC_APM_AUTO_LOG_STACKS": "false",
        },
    ):
        config = Config()

        assert config.service_name == "foo"
        assert config.secret_token == "bar"
        assert config.server_url == "http://example.com:1234"
        assert config.service_version == "1"
        assert config.hostname == "localhost"
        assert config.flush_interval == 5
        assert config.auto_log_stacks == False
예제 #20
0
    def __init__(self, config=None, **inline):
        # configure loggers first
        cls = self.__class__
        self.logger = logging.getLogger("%s.%s" %
                                        (cls.__module__, cls.__name__))
        self.error_logger = logging.getLogger("elasticapm.errors")

        self.tracer = None
        self.processors = []
        self.filter_exception_types_dict = {}
        self._service_info = None

        self.config = Config(config, inline_dict=inline)
        if self.config.errors:
            for msg in self.config.errors.values():
                self.error_logger.error(msg)
            self.config.disable_send = True

        headers = {
            "Content-Type": "application/x-ndjson",
            "Content-Encoding": "gzip",
            "User-Agent": "elasticapm-python/%s" % elasticapm.VERSION,
        }

        if self.config.secret_token:
            headers["Authorization"] = "Bearer %s" % self.config.secret_token
        transport_kwargs = {
            "metadata": self._build_metadata(),
            "headers": headers,
            "verify_server_cert": self.config.verify_server_cert,
            "timeout": self.config.server_timeout,
            "max_flush_time": self.config.api_request_time / 1000.0,
            "max_buffer_size": self.config.api_request_size,
        }
        self._transport = import_string(self.config.transport_class)(
            compat.urlparse.urljoin(self.config.server_url,
                                    constants.EVENTS_API_PATH),
            **transport_kwargs)

        for exc_to_filter in self.config.filter_exception_types or []:
            exc_to_filter_type = exc_to_filter.split(".")[-1]
            exc_to_filter_module = ".".join(exc_to_filter.split(".")[:-1])
            self.filter_exception_types_dict[
                exc_to_filter_type] = exc_to_filter_module

        self.processors = [import_string(p) for p in self.config.processors
                           ] if self.config.processors else []

        if platform.python_implementation() == "PyPy":
            # PyPy introduces a `_functools.partial.__call__` frame due to our use
            # of `partial` in AbstractInstrumentedModule
            skip_modules = ("elasticapm.", "_functools")
        else:
            skip_modules = ("elasticapm.", )

        self.tracer = Tracer(
            frames_collector_func=lambda: list(
                stacks.iter_stack_frames(start_frame=inspect.currentframe(),
                                         skip_top_modules=skip_modules)),
            frames_processing_func=lambda frames: self.
            _get_stack_info_for_trace(
                frames,
                library_frame_context_lines=self.config.
                source_lines_span_library_frames,
                in_app_frame_context_lines=self.config.
                source_lines_span_app_frames,
                with_locals=self.config.collect_local_variables in
                ("all", "transactions"),
                locals_processor_func=lambda local_var: varmap(
                    lambda k, v: shorten(
                        v,
                        list_length=self.config.local_var_list_max_length,
                        string_length=self.config.local_var_max_length,
                    ),
                    local_var,
                ),
            ),
            queue_func=self.queue,
            sample_rate=self.config.transaction_sample_rate,
            max_spans=self.config.transaction_max_spans,
            span_frames_min_duration=self.config.span_frames_min_duration,
            ignore_patterns=self.config.transactions_ignore_patterns,
        )
        self.include_paths_re = stacks.get_path_regex(
            self.config.include_paths) if self.config.include_paths else None
        self.exclude_paths_re = stacks.get_path_regex(
            self.config.exclude_paths) if self.config.exclude_paths else None
        compat.atexit_register(self.close)
예제 #21
0
    def __init__(self, config=None, **inline):
        # configure loggers first
        cls = self.__class__
        self.logger = get_logger("%s.%s" % (cls.__module__, cls.__name__))
        self.error_logger = get_logger("elasticapm.errors")

        self.tracer = None
        self.processors = []
        self.filter_exception_types_dict = {}
        self._service_info = None

        config = Config(config, inline_dict=inline)
        if config.errors:
            for msg in config.errors.values():
                self.error_logger.error(msg)
            config.disable_send = True
        self.config = VersionedConfig(config, version=None)

        # Insert the log_record_factory into the logging library
        # The LogRecordFactory functionality is only available on python 3.2+
        if compat.PY3 and not self.config.disable_log_record_factory:
            record_factory = logging.getLogRecordFactory()
            # Only way to know if it's wrapped is to create a log record
            throwaway_record = record_factory(__name__, logging.DEBUG, __file__, 252, "dummy_msg", [], None)
            if not hasattr(throwaway_record, "elasticapm_labels"):
                self.logger.debug("Inserting elasticapm log_record_factory into logging")

                # Late import due to circular imports
                import elasticapm.handlers.logging as elastic_logging

                new_factory = elastic_logging.log_record_factory(record_factory)
                logging.setLogRecordFactory(new_factory)

        headers = {
            "Content-Type": "application/x-ndjson",
            "Content-Encoding": "gzip",
            "User-Agent": "elasticapm-python/%s" % elasticapm.VERSION,
        }

        if self.config.secret_token:
            headers["Authorization"] = "Bearer %s" % self.config.secret_token
        transport_kwargs = {
            "metadata": self._build_metadata(),
            "headers": headers,
            "verify_server_cert": self.config.verify_server_cert,
            "server_cert": self.config.server_cert,
            "timeout": self.config.server_timeout,
            "max_flush_time": self.config.api_request_time / 1000.0,
            "max_buffer_size": self.config.api_request_size,
            "processors": self.load_processors(),
        }
        self._api_endpoint_url = compat.urlparse.urljoin(
            self.config.server_url if self.config.server_url.endswith("/") else self.config.server_url + "/",
            constants.EVENTS_API_PATH,
        )
        self._transport = import_string(self.config.transport_class)(self._api_endpoint_url, **transport_kwargs)

        for exc_to_filter in self.config.filter_exception_types or []:
            exc_to_filter_type = exc_to_filter.split(".")[-1]
            exc_to_filter_module = ".".join(exc_to_filter.split(".")[:-1])
            self.filter_exception_types_dict[exc_to_filter_type] = exc_to_filter_module

        if platform.python_implementation() == "PyPy":
            # PyPy introduces a `_functools.partial.__call__` frame due to our use
            # of `partial` in AbstractInstrumentedModule
            skip_modules = ("elasticapm.", "_functools")
        else:
            skip_modules = ("elasticapm.",)

        self.tracer = Tracer(
            frames_collector_func=lambda: list(
                stacks.iter_stack_frames(
                    start_frame=inspect.currentframe(), skip_top_modules=skip_modules, config=self.config
                )
            ),
            frames_processing_func=lambda frames: self._get_stack_info_for_trace(
                frames,
                library_frame_context_lines=self.config.source_lines_span_library_frames,
                in_app_frame_context_lines=self.config.source_lines_span_app_frames,
                with_locals=self.config.collect_local_variables in ("all", "transactions"),
                locals_processor_func=lambda local_var: varmap(
                    lambda k, v: shorten(
                        v,
                        list_length=self.config.local_var_list_max_length,
                        string_length=self.config.local_var_max_length,
                        dict_length=self.config.local_var_dict_max_length,
                    ),
                    local_var,
                ),
            ),
            queue_func=self.queue,
            config=self.config,
            agent=self,
        )
        self.include_paths_re = stacks.get_path_regex(self.config.include_paths) if self.config.include_paths else None
        self.exclude_paths_re = stacks.get_path_regex(self.config.exclude_paths) if self.config.exclude_paths else None
        self._metrics = MetricsRegistry(
            self.config.metrics_interval / 1000.0, self.queue, ignore_patterns=self.config.disable_metrics
        )
        for path in self.config.metrics_sets:
            self._metrics.register(path)
        if self.config.breakdown_metrics:
            self._metrics.register("elasticapm.metrics.sets.breakdown.BreakdownMetricSet")
        compat.atexit_register(self.close)
        if self.config.central_config:
            self._config_updater = IntervalTimer(
                update_config, 1, "eapm conf updater", daemon=True, args=(self,), evaluate_function_interval=True
            )
            self._config_updater.start()
        else:
            self._config_updater = None
예제 #22
0
def test_capture_body_mapping(val, expected):
    c = Config(inline_dict={"capture_body": val})
    assert c.capture_body == expected
예제 #23
0
def test_get_transaction():
    requests_store = Tracer(lambda: [], lambda: [], lambda *args: None,
                            VersionedConfig(Config(), "1"), None)
    t = requests_store.begin_transaction("test")
    assert t == execution_context.get_transaction()
예제 #24
0
    def __init__(self, config=None, **inline):
        # configure loggers first
        cls = self.__class__
        self.logger = get_logger("%s.%s" % (cls.__module__, cls.__name__))
        self.error_logger = get_logger("elasticapm.errors")

        self._pid = None
        self._thread_starter_lock = threading.Lock()
        self._thread_managers = {}

        self.tracer = None
        self.processors = []
        self.filter_exception_types_dict = {}
        self._service_info = None

        self.check_python_version()

        config = Config(config, inline_dict=inline)
        if config.errors:
            for msg in config.errors.values():
                self.error_logger.error(msg)
            config.disable_send = True
        if config.service_name == "python_service":
            self.logger.warning(
                "No custom SERVICE_NAME was set -- using non-descript default 'python_service'"
            )
        self.config = VersionedConfig(config, version=None)

        # Insert the log_record_factory into the logging library
        # The LogRecordFactory functionality is only available on python 3.2+
        if compat.PY3 and not self.config.disable_log_record_factory:
            record_factory = logging.getLogRecordFactory()
            # Only way to know if it's wrapped is to create a log record
            throwaway_record = record_factory(__name__, logging.DEBUG,
                                              __file__, 252, "dummy_msg", [],
                                              None)
            if not hasattr(throwaway_record, "elasticapm_labels"):
                self.logger.debug(
                    "Inserting elasticapm log_record_factory into logging")

                # Late import due to circular imports
                import elasticapm.handlers.logging as elastic_logging

                new_factory = elastic_logging.log_record_factory(
                    record_factory)
                logging.setLogRecordFactory(new_factory)

        headers = {
            "Content-Type": "application/x-ndjson",
            "Content-Encoding": "gzip",
            "User-Agent": "elasticapm-python/%s" % elasticapm.VERSION,
        }

        transport_kwargs = {
            "headers": headers,
            "verify_server_cert": self.config.verify_server_cert,
            "server_cert": self.config.server_cert,
            "timeout": self.config.server_timeout,
            "processors": self.load_processors(),
        }
        self._api_endpoint_url = compat.urlparse.urljoin(
            self.config.server_url if self.config.server_url.endswith("/") else
            self.config.server_url + "/",
            constants.EVENTS_API_PATH,
        )
        transport_class = import_string(self.config.transport_class)
        self._transport = transport_class(self._api_endpoint_url, self,
                                          **transport_kwargs)
        self.config.transport = self._transport
        self._thread_managers["transport"] = self._transport

        for exc_to_filter in self.config.filter_exception_types or []:
            exc_to_filter_type = exc_to_filter.split(".")[-1]
            exc_to_filter_module = ".".join(exc_to_filter.split(".")[:-1])
            self.filter_exception_types_dict[
                exc_to_filter_type] = exc_to_filter_module

        if platform.python_implementation() == "PyPy":
            # PyPy introduces a `_functools.partial.__call__` frame due to our use
            # of `partial` in AbstractInstrumentedModule
            skip_modules = ("elasticapm.", "_functools")
        else:
            skip_modules = ("elasticapm.", )

        self.tracer = Tracer(
            frames_collector_func=lambda: list(
                stacks.iter_stack_frames(start_frame=inspect.currentframe(),
                                         skip_top_modules=skip_modules,
                                         config=self.config)),
            frames_processing_func=lambda frames: self.
            _get_stack_info_for_trace(
                frames,
                library_frame_context_lines=self.config.
                source_lines_span_library_frames,
                in_app_frame_context_lines=self.config.
                source_lines_span_app_frames,
                with_locals=self.config.collect_local_variables in
                ("all", "transactions"),
                locals_processor_func=lambda local_var: varmap(
                    lambda k, v: shorten(
                        v,
                        list_length=self.config.local_var_list_max_length,
                        string_length=self.config.local_var_max_length,
                        dict_length=self.config.local_var_dict_max_length,
                    ),
                    local_var,
                ),
            ),
            queue_func=self.queue,
            config=self.config,
            agent=self,
        )
        self.include_paths_re = stacks.get_path_regex(
            self.config.include_paths) if self.config.include_paths else None
        self.exclude_paths_re = stacks.get_path_regex(
            self.config.exclude_paths) if self.config.exclude_paths else None
        self._metrics = MetricsRegistry(self)
        for path in self.config.metrics_sets:
            self._metrics.register(path)
        if self.config.breakdown_metrics:
            self._metrics.register(
                "elasticapm.metrics.sets.breakdown.BreakdownMetricSet")
        if self.config.prometheus_metrics:
            self._metrics.register(
                "elasticapm.metrics.sets.prometheus.PrometheusMetrics")
        self._thread_managers["metrics"] = self._metrics
        compat.atexit_register(self.close)
        if self.config.central_config:
            self._thread_managers["config"] = self.config
        else:
            self._config_updater = None
        if self.config.use_elastic_excepthook:
            self.original_excepthook = sys.excepthook
            sys.excepthook = self._excepthook
        if config.enabled:
            self.start_threads()

        # Save this Client object as the global CLIENT_SINGLETON
        set_client(self)
예제 #25
0
    def __init__(self, config=None, **inline):
        # configure loggers first
        cls = self.__class__
        self.logger = logging.getLogger("%s.%s" %
                                        (cls.__module__, cls.__name__))
        self.error_logger = logging.getLogger("elasticapm.errors")
        self.state = ClientState()

        self.transaction_store = None
        self.processors = []
        self.filter_exception_types_dict = {}
        self._send_timer = None
        self._transports = {}
        self._service_info = None

        self.config = Config(config, inline_dict=inline)
        if self.config.errors:
            for msg in self.config.errors.values():
                self.error_logger.error(msg)
            self.config.disable_send = True

        self._transport_class = import_string(self.config.transport_class)

        for exc_to_filter in self.config.filter_exception_types or []:
            exc_to_filter_type = exc_to_filter.split(".")[-1]
            exc_to_filter_module = ".".join(exc_to_filter.split(".")[:-1])
            self.filter_exception_types_dict[
                exc_to_filter_type] = exc_to_filter_module

        self.processors = [import_string(p) for p in self.config.processors
                           ] if self.config.processors else []

        if platform.python_implementation() == "PyPy":
            # PyPy introduces a `_functools.partial.__call__` frame due to our use
            # of `partial` in AbstractInstrumentedModule
            skip_modules = ("elasticapm.", "_functools")
        else:
            skip_modules = ("elasticapm.", )

        def frames_collector_func():
            return self._get_stack_info_for_trace(
                stacks.iter_stack_frames(skip_top_modules=skip_modules),
                library_frame_context_lines=self.config.
                source_lines_span_library_frames,
                in_app_frame_context_lines=self.config.
                source_lines_span_app_frames,
                with_locals=self.config.collect_local_variables
                in ("all", "transactions"),
                locals_processor_func=lambda local_var: varmap(
                    lambda k, v: shorten(
                        v,
                        list_length=self.config.local_var_list_max_length,
                        string_length=self.config.local_var_max_length,
                    ),
                    local_var,
                ),
            )

        self.transaction_store = TransactionsStore(
            frames_collector_func=frames_collector_func,
            collect_frequency=self.config.flush_interval,
            sample_rate=self.config.transaction_sample_rate,
            max_spans=self.config.transaction_max_spans,
            span_frames_min_duration=self.config.span_frames_min_duration_ms,
            max_queue_size=self.config.max_queue_size,
            ignore_patterns=self.config.transactions_ignore_patterns,
        )
        self.include_paths_re = stacks.get_path_regex(
            self.config.include_paths) if self.config.include_paths else None
        self.exclude_paths_re = stacks.get_path_regex(
            self.config.exclude_paths) if self.config.exclude_paths else None
        compat.atexit_register(self.close)
예제 #26
0
def tracer():
    frames = [
        {
            "function": "something_expensive",
            "abs_path": "/var/parent-elasticapm/elasticapm/tests/contrib/django/testapp/views.py",
            "lineno": 52,
            "module": "tests.contrib.django.testapp.views",
            "filename": "tests/contrib/django/testapp/views.py",
        },
        {
            "function": "_resolve_lookup",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/base.py",
            "lineno": 789,
            "module": "django.template.base",
            "filename": "django/template/base.py",
        },
        {
            "function": "resolve",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/base.py",
            "lineno": 735,
            "module": "django.template.base",
            "filename": "django/template/base.py",
        },
        {
            "function": "resolve",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/base.py",
            "lineno": 585,
            "module": "django.template.base",
            "filename": "django/template/base.py",
        },
        {
            "lineno": 4,
            "filename": u"/var/parent-elasticapm/elasticapm/tests/contrib/django/testapp/templates/list_fish.html",
        },
        {
            "function": "render",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/defaulttags.py",
            "lineno": 4,
            "module": "django.template.defaulttags",
            "filename": "django/template/defaulttags.py",
        },
        {
            "function": "render_node",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/debug.py",
            "lineno": 78,
            "module": "django.template.debug",
            "filename": "django/template/debug.py",
        },
        {
            "function": "render",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/base.py",
            "lineno": 840,
            "module": "django.template.base",
            "filename": "django/template/base.py",
        },
        {
            "function": "instrumented_test_render",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/test/utils.py",
            "lineno": 85,
            "module": "django.test.utils",
            "filename": "django/test/utils.py",
        },
        {
            "function": "render",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/base.py",
            "lineno": 140,
            "module": "django.template.base",
            "filename": "django/template/base.py",
        },
        {
            "function": "rendered_content",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/response.py",
            "lineno": 82,
            "module": "django.template.response",
            "filename": "django/template/response.py",
        },
        {
            "function": "render",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/template/response.py",
            "lineno": 105,
            "module": "django.template.response",
            "filename": "django/template/response.py",
        },
        {
            "function": "get_response",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/core/handlers/base.py",
            "lineno": 137,
            "module": "django.core.handlers.base",
            "filename": "django/core/handlers/base.py",
        },
        {
            "function": "__call__",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/test/client.py",
            "lineno": 109,
            "module": "django.test.client",
            "filename": "django/test/client.py",
        },
        {
            "function": "request",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/test/client.py",
            "lineno": 426,
            "module": "django.test.client",
            "filename": "django/test/client.py",
        },
        {
            "function": "get",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/test/client.py",
            "lineno": 280,
            "module": "django.test.client",
            "filename": "django/test/client.py",
        },
        {
            "function": "get",
            "abs_path": "/home/ron/.virtualenvs/elasticapm/local/lib/python2.7/site-packages/django/test/client.py",
            "lineno": 473,
            "module": "django.test.client",
            "filename": "django/test/client.py",
        },
        {
            "function": "test_template_name_as_view",
            "abs_path": "/var/parent-elasticapm/elasticapm/tests/contrib/django/django_tests.py",
            "lineno": 710,
            "module": "tests.contrib.django.django_tests",
            "filename": "tests/contrib/django/django_tests.py",
        },
    ]

    events = defaultdict(list)

    def queue(event_type, event, flush=False):
        events[event_type].append(event)

    store = Tracer(lambda: frames, lambda frames: frames, queue, Config(), None)
    store.events = events
    return store
예제 #27
0
def test_get_transaction_clear():
    requests_store = Tracer(lambda: [], lambda: [], lambda *args: None, Config(), None)
    t = requests_store.begin_transaction("test")
    assert t == execution_context.get_transaction(clear=True)
    assert execution_context.get_transaction() is None