From 934a31725c53d4d205e43249d8c3a9e08ec106db Mon Sep 17 00:00:00 2001 From: Benjamin Wohlwend Date: Fri, 1 May 2020 12:56:02 +0200 Subject: [PATCH] introduce enabled/recording settings (#790) * introduce enabled/recording settings see https://github.com/elastic/apm/issues/92#issuecomment-519752096 Co-authored-by: Colton Myers --- docs/configuration.asciidoc | 31 +++++++++++++++++ elasticapm/base.py | 23 +++++++------ elasticapm/conf/__init__.py | 24 +++++++++++-- elasticapm/contrib/aiohttp/__init__.py | 2 +- elasticapm/contrib/django/apps.py | 2 +- elasticapm/contrib/flask/__init__.py | 3 +- elasticapm/contrib/opentracing/tracer.py | 2 +- elasticapm/contrib/tornado/__init__.py | 6 +++- elasticapm/metrics/base_metrics.py | 38 ++++++++++++--------- elasticapm/transport/base.py | 9 ++--- elasticapm/utils/threading.py | 17 ++++++++-- tests/client/client_tests.py | 43 ++++++++++++++++++++++++ tests/config/tests.py | 9 +++++ tests/fixtures.py | 6 ++-- tests/metrics/base_tests.py | 34 +++++++++---------- tests/metrics/cpu_linux_tests.py | 14 ++++---- tests/metrics/cpu_psutil_tests.py | 10 +++--- 17 files changed, 199 insertions(+), 74 deletions(-) diff --git a/docs/configuration.asciidoc b/docs/configuration.asciidoc index 1cad37151..b47832d81 100644 --- a/docs/configuration.asciidoc +++ b/docs/configuration.asciidoc @@ -112,6 +112,37 @@ Your service name must only contain characters from the ASCII alphabet, numbers, The URL for your APM Server. The URL must be fully qualified, including protocol (`http` or `https`) and port. +[float] +[[config-enabled]] +=== `enabled` + +[options="header"] +|============ +| Environment | Django/Flask | Default +| `ELASTIC_APM_ENABLED` | `ENABLED` | `true` +|============ + +Enable or disable the agent. +When set to false, the agent will not collect any data, nor start any background threads. + + +[float] +[[config-recording]] +=== `recording` + +<> + +[options="header"] +|============ +| Environment | Django/Flask | Default +| `ELASTIC_APM_RECORDING` | `RECORDING` | `false` +|============ + +Enable or disable recording of events. +If set to false, then the Python agent does not send any events to the Elastic APM server, +and instrumentation overhead is minimized, +but the agent will continue to poll the server for configuration changes. + [float] [[config-transport-class]] diff --git a/elasticapm/base.py b/elasticapm/base.py index c12cf0be8..64dbdbfd2 100644 --- a/elasticapm/base.py +++ b/elasticapm/base.py @@ -187,9 +187,7 @@ def __init__(self, config=None, **inline): ) 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 - ) + self._metrics = MetricsRegistry(self) for path in self.config.metrics_sets: self._metrics.register(path) if self.config.breakdown_metrics: @@ -200,15 +198,14 @@ def __init__(self, config=None, **inline): self._thread_managers["config"] = self.config else: self._config_updater = None - if self.config.use_elastic_excepthook: self.original_excepthook = sys.excepthook self.excepthook_overwritten_by_user = ( self.original_excepthook is not sys.__excepthook__ ) sys.excepthook = self._excepthook - - self.start_threads() + if config.enabled: + self.start_threads() def start_threads(self): with self._thread_starter_lock: @@ -217,7 +214,7 @@ def start_threads(self): self.logger.debug("Detected PID change from %r to %r, starting threads", self._pid, current_pid) for manager_type, manager in self._thread_managers.items(): self.logger.debug("Starting %s thread", manager_type) - manager.start_thread() + manager.start_thread(pid=current_pid) self._pid = current_pid def get_handler(self, name): @@ -227,6 +224,8 @@ def capture(self, event_type, date=None, context=None, custom=None, stack=None, """ Captures and processes an event and pipes it off to Client.send. """ + if not self.config.is_recording: + return if event_type == "Exception": # never gather log stack for exceptions stack = False @@ -281,7 +280,8 @@ def begin_transaction(self, transaction_type, trace_parent=None, start=None): :param start: override the start timestamp, mostly useful for testing :return: the started transaction object """ - return self.tracer.begin_transaction(transaction_type, trace_parent=trace_parent, start=start) + if self.config.is_recording: + return self.tracer.begin_transaction(transaction_type, trace_parent=trace_parent, start=start) def end_transaction(self, name=None, result="", duration=None): """ @@ -296,9 +296,10 @@ def end_transaction(self, name=None, result="", duration=None): return transaction def close(self): - with self._thread_starter_lock: - for _manager_type, manager in self._thread_managers.items(): - manager.stop_thread() + if self.config.enabled: + with self._thread_starter_lock: + for _, manager in self._thread_managers.items(): + manager.stop_thread() def get_service_info(self): if self._service_info: diff --git a/elasticapm/conf/__init__.py b/elasticapm/conf/__init__.py index c544a0291..ecf2d86cc 100644 --- a/elasticapm/conf/__init__.py +++ b/elasticapm/conf/__init__.py @@ -337,6 +337,8 @@ class Config(_ConfigBase): framework_version = _ConfigValue("FRAMEWORK_VERSION", default=None) global_labels = _DictConfigValue("GLOBAL_LABELS", default=None) disable_send = _BoolConfigValue("DISABLE_SEND", default=False) + enabled = _BoolConfigValue("ENABLED", default=True) + recording = _BoolConfigValue("RECORDING", default=True) instrument = _BoolConfigValue("INSTRUMENT", default=True) enable_distributed_tracing = _BoolConfigValue("ENABLE_DISTRIBUTED_TRACING", default=True) capture_headers = _BoolConfigValue("CAPTURE_HEADERS", default=True) @@ -345,13 +347,29 @@ class Config(_ConfigBase): use_elastic_traceparent_header = _BoolConfigValue("USE_ELASTIC_TRACEPARENT_HEADER", default=True) use_elastic_excepthook = _BoolConfigValue("USE_ELASTIC_EXCEPTHOOK", default=False) + @property + def is_recording(self): + if not self.enabled: + return False + else: + return self.recording + class VersionedConfig(ThreadManager): """ A thin layer around Config that provides versioning """ - __slots__ = ("_config", "_version", "_first_config", "_first_version", "_lock", "transport", "_update_thread") + __slots__ = ( + "_config", + "_version", + "_first_config", + "_first_version", + "_lock", + "transport", + "_update_thread", + "pid", + ) def __init__(self, config_object, version, transport=None): """ @@ -364,6 +382,7 @@ def __init__(self, config_object, version, transport=None): self.transport = transport self._lock = threading.Lock() self._update_thread = None + super(VersionedConfig, self).__init__() def update(self, version, **config): """ @@ -437,11 +456,12 @@ def update_config(self): return next_run - def start_thread(self): + def start_thread(self, pid=None): self._update_thread = IntervalTimer( self.update_config, 1, "eapm conf updater", daemon=True, evaluate_function_interval=True ) self._update_thread.start() + super(VersionedConfig, self).start_thread(pid=pid) def stop_thread(self): if self._update_thread: diff --git a/elasticapm/contrib/aiohttp/__init__.py b/elasticapm/contrib/aiohttp/__init__.py index 6b571f707..75799caca 100644 --- a/elasticapm/contrib/aiohttp/__init__.py +++ b/elasticapm/contrib/aiohttp/__init__.py @@ -52,5 +52,5 @@ def install_tracing(self, app, client): from elasticapm.contrib.aiohttp.middleware import tracing_middleware app.middlewares.insert(0, tracing_middleware(app)) - if client.config.instrument: + if client.config.instrument and client.config.enabled: elasticapm.instrument() diff --git a/elasticapm/contrib/django/apps.py b/elasticapm/contrib/django/apps.py index a75587f99..7e0bb234e 100644 --- a/elasticapm/contrib/django/apps.py +++ b/elasticapm/contrib/django/apps.py @@ -65,7 +65,7 @@ def ready(self): if self.client.config.autoinsert_django_middleware: self.insert_middleware(django_settings) register_handlers(self.client) - if self.client.config.instrument: + if self.client.config.instrument and self.client.config.enabled: instrument(self.client) else: self.client.logger.debug("Skipping instrumentation. INSTRUMENT is set to False.") diff --git a/elasticapm/contrib/flask/__init__.py b/elasticapm/contrib/flask/__init__.py index 57836ee11..085f05c3a 100644 --- a/elasticapm/contrib/flask/__init__.py +++ b/elasticapm/contrib/flask/__init__.py @@ -30,6 +30,7 @@ from __future__ import absolute_import + import logging import flask @@ -145,7 +146,7 @@ def init_app(self, app, **defaults): pass # Instrument to get spans - if self.client.config.instrument: + if self.client.config.instrument and self.client.config.enabled: elasticapm.instrumentation.control.instrument() signals.request_started.connect(self.request_started, sender=app) diff --git a/elasticapm/contrib/opentracing/tracer.py b/elasticapm/contrib/opentracing/tracer.py index d7b61dedc..cd65e66df 100644 --- a/elasticapm/contrib/opentracing/tracer.py +++ b/elasticapm/contrib/opentracing/tracer.py @@ -53,7 +53,7 @@ def __init__(self, client_instance=None, config=None, scope_manager=None): "Usage of other scope managers will lead to unpredictable results." ) self._scope_manager = scope_manager or ThreadLocalScopeManager() - if self._agent.config.instrument: + if self._agent.config.instrument and self._agent.config.enabled: instrument() def start_active_span( diff --git a/elasticapm/contrib/tornado/__init__.py b/elasticapm/contrib/tornado/__init__.py index b71a5c006..b91b0a622 100644 --- a/elasticapm/contrib/tornado/__init__.py +++ b/elasticapm/contrib/tornado/__init__.py @@ -63,5 +63,9 @@ def __init__(self, app, client=None, **config): app.elasticapm_client = client # Don't instrument if debug=True in tornado, unless client.config.debug is True - if (not self.app.settings.get("debug") or client.config.debug) and client.config.instrument: + if ( + (not self.app.settings.get("debug") or client.config.debug) + and client.config.instrument + and client.config.enabled + ): elasticapm.instrument() diff --git a/elasticapm/metrics/base_metrics.py b/elasticapm/metrics/base_metrics.py index 2793fb538..5b8d6d21a 100644 --- a/elasticapm/metrics/base_metrics.py +++ b/elasticapm/metrics/base_metrics.py @@ -44,20 +44,18 @@ class MetricsRegistry(ThreadManager): - def __init__(self, collect_interval, queue_func, tags=None, ignore_patterns=None): + def __init__(self, client, tags=None): """ Creates a new metric registry - :param collect_interval: the interval to collect metrics from registered metric sets - :param queue_func: the function to call with the collected metrics + :param client: client instance :param tags: """ - self._collect_interval = collect_interval - self._queue_func = queue_func + self.client = client self._metricsets = {} self._tags = tags or {} self._collect_timer = None - self._ignore_patterns = ignore_patterns or () + super(MetricsRegistry, self).__init__() def register(self, class_path): """ @@ -84,16 +82,18 @@ def collect(self): Collect metrics from all registered metric sets and queues them for sending :return: """ - logger.debug("Collecting metrics") + if self.client.config.is_recording: + logger.debug("Collecting metrics") - for name, metricset in compat.iteritems(self._metricsets): - for data in metricset.collect(): - self._queue_func(constants.METRICSET, data) + for _, metricset in compat.iteritems(self._metricsets): + for data in metricset.collect(): + self.client.queue(constants.METRICSET, data) - def start_thread(self): - if self._collect_interval: + def start_thread(self, pid=None): + super(MetricsRegistry, self).start_thread(pid=pid) + if self.client.config.metrics_interval: self._collect_timer = IntervalTimer( - self.collect, self._collect_interval, name="eapm metrics collect timer", daemon=True + self.collect, self.collect_interval, name="eapm metrics collect timer", daemon=True ) logger.debug("Starting metrics collect timer") self._collect_timer.start() @@ -104,6 +104,14 @@ def stop_thread(self): self._collect_timer.cancel() self._collect_timer = None + @property + def collect_interval(self): + return self.client.config.metrics_interval / 1000.0 + + @property + def ignore_patterns(self): + return self.client.config.disable_metrics or [] + class MetricsSet(object): def __init__(self, registry): @@ -159,9 +167,7 @@ def _metric(self, container, metric_class, name, reset_on_collect, labels): key = (name, labels) with self._lock: if key not in container: - if self._registry._ignore_patterns and any( - pattern.match(name) for pattern in self._registry._ignore_patterns - ): + if any(pattern.match(name) for pattern in self._registry.ignore_patterns): metric = noop_metric elif len(self._gauges) + len(self._counters) + len(self._timers) >= DISTINCT_LABEL_LIMIT: if not self._label_limit_logged: diff --git a/elasticapm/transport/base.py b/elasticapm/transport/base.py index 7330272d8..ce4da1c02 100644 --- a/elasticapm/transport/base.py +++ b/elasticapm/transport/base.py @@ -94,6 +94,7 @@ def __init__( self._flushed = threading.Event() self._closed = False self._processors = processors if processors is not None else [] + super(Transport, self).__init__() @property def _max_flush_time(self): @@ -228,13 +229,13 @@ def _flush(self, buffer): except Exception as e: self.handle_transport_fail(e) - def start_thread(self): - current_pid = os.getpid() - if (not self._thread or current_pid != self._thread.pid) and not self._closed: + def start_thread(self, pid=None): + super(Transport, self).start_thread(pid=pid) + if (not self._thread or self.pid != self._thread.pid) and not self._closed: try: self._thread = threading.Thread(target=self._process_queue, name="eapm event processor thread") self._thread.daemon = True - self._thread.pid = current_pid + self._thread.pid = self.pid self._thread.start() except RuntimeError: pass diff --git a/elasticapm/utils/threading.py b/elasticapm/utils/threading.py index 79749e228..fd5139591 100644 --- a/elasticapm/utils/threading.py +++ b/elasticapm/utils/threading.py @@ -30,6 +30,7 @@ from __future__ import absolute_import +import os import threading from timeit import default_timer @@ -47,7 +48,7 @@ def __init__( """ :param function: the function to run - :param interval: the interval in-between invocations of the function + :param interval: the interval in-between invocations of the function, in milliseconds :param name: name of the thread :param args: arguments to call the function with :param kwargs: keyword arguments to call the function with @@ -88,8 +89,18 @@ def cancel(self): class ThreadManager(object): - def start_thread(self): - raise NotImplementedError() + def __init__(self): + self.pid = None + + def start_thread(self, pid=None): + if not pid: + pid = os.getpid() + self.pid = pid def stop_thread(self): raise NotImplementedError() + + def is_started(self, current_pid=None): + if not current_pid: + current_pid = os.getpid() + return self.pid == current_pid diff --git a/tests/client/client_tests.py b/tests/client/client_tests.py index d4896dd2c..e8fdc08a7 100644 --- a/tests/client/client_tests.py +++ b/tests/client/client_tests.py @@ -799,3 +799,46 @@ def test_python_version_deprecation(mock_python_version_tuple, version, raises, assert "agent only supports" in w.message.args[0] else: assert len(recwarn) == 0 + + +def test_recording(elasticapm_client): + assert elasticapm_client.capture_message("x") is not None + try: + 1 / 0 + except ZeroDivisionError: + assert elasticapm_client.capture_exception() is not None + assert elasticapm_client.begin_transaction("test") is not None + with elasticapm.capture_span("x") as x_span: + assert x_span is not None + assert elasticapm_client.end_transaction("ok", "ok") is not None + + elasticapm_client.config.update("1", recording=False) + assert not elasticapm_client.config.is_recording + assert elasticapm_client.capture_message("x") is None + try: + 1 / 0 + except ZeroDivisionError: + assert elasticapm_client.capture_exception() is None + assert elasticapm_client.begin_transaction("test") is None + with elasticapm.capture_span("x") as x_span: + assert x_span is None + assert elasticapm_client.end_transaction("ok", "ok") is None + + +@pytest.mark.parametrize( + "elasticapm_client", + [ + {"enabled": True, "metrics_interval": "30s", "central_config": "true"}, + {"enabled": False, "metrics_interval": "30s", "central_config": "true"}, + ], + indirect=True, +) +def test_client_enabled(elasticapm_client): + if elasticapm_client.config.enabled: + assert elasticapm_client.config.is_recording + for manager in elasticapm_client._thread_managers.values(): + assert manager.is_started() + else: + assert not elasticapm_client.config.is_recording + for manager in elasticapm_client._thread_managers.values(): + assert not manager.is_started() diff --git a/tests/config/tests.py b/tests/config/tests.py index 13d4e5db2..9c92c394a 100644 --- a/tests/config/tests.py +++ b/tests/config/tests.py @@ -292,3 +292,12 @@ class MyConfig(_ConfigBase): def test_capture_body_mapping(val, expected): c = Config(inline_dict={"capture_body": val}) assert c.capture_body == expected + + +@pytest.mark.parametrize( + "enabled,recording,is_recording", + [(True, True, True), (True, False, False), (False, True, False), (False, False, False)], +) +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 diff --git a/tests/fixtures.py b/tests/fixtures.py index d2179cdfe..1a4cf0e97 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -49,6 +49,7 @@ from elasticapm.traces import execution_context from elasticapm.transport.http_base import HTTPTransportBase from elasticapm.utils import compat +from elasticapm.utils.threading import ThreadManager try: from urllib.request import pathname2url @@ -234,8 +235,9 @@ def queue(self, event_type, data, flush=False): self.events[event_type].append(data) self._flushed.set() - def start_thread(self): - pass + def start_thread(self, pid=None): + # don't call the parent method, but the one from ThreadManager + ThreadManager.start_thread(self, pid=pid) def stop_thread(self): pass diff --git a/tests/metrics/base_tests.py b/tests/metrics/base_tests.py index 8d4876308..dcf25486b 100644 --- a/tests/metrics/base_tests.py +++ b/tests/metrics/base_tests.py @@ -48,16 +48,12 @@ def before_collect(self): self.gauge("c").val = 0 -def test_metrics_registry(): - mock_queue = mock.Mock() - registry = MetricsRegistry(0.001, queue_func=mock_queue) +@pytest.mark.parametrize("elasticapm_client", [{"metrics_interval": "30s"}], indirect=True) +def test_metrics_registry(elasticapm_client): + registry = MetricsRegistry(elasticapm_client) registry.register("tests.metrics.base_tests.DummyMetricSet") - try: - registry.start_thread() - time.sleep(0.1) - assert mock_queue.call_count > 0 - finally: - registry.stop_thread() + registry.collect() + assert len(elasticapm_client.events[constants.METRICSET]) @pytest.mark.parametrize( @@ -74,8 +70,8 @@ def test_disable_metrics(elasticapm_client): assert "c" not in metrics["samples"] -def test_metrics_counter(): - metricset = MetricsSet(MetricsRegistry(0, lambda x: None)) +def test_metrics_counter(elasticapm_client): + metricset = MetricsSet(MetricsRegistry(elasticapm_client)) metricset.counter("x").inc() data = next(metricset.collect()) assert data["samples"]["x"]["value"] == 1 @@ -90,8 +86,8 @@ def test_metrics_counter(): assert data["samples"]["x"]["value"] == 0 -def test_metrics_labels(): - metricset = MetricsSet(MetricsRegistry(0, lambda x: None)) +def test_metrics_labels(elasticapm_client): + metricset = MetricsSet(MetricsRegistry(elasticapm_client)) metricset.counter("x", mylabel="a").inc() metricset.counter("y", mylabel="a").inc() metricset.counter("x", mylabel="b").inc().inc() @@ -113,8 +109,8 @@ def test_metrics_labels(): assert asserts == 3 -def test_metrics_multithreaded(): - metricset = MetricsSet(MetricsRegistry(0, lambda x: None)) +def test_metrics_multithreaded(elasticapm_client): + metricset = MetricsSet(MetricsRegistry(elasticapm_client)) pool = Pool(5) def target(): @@ -130,8 +126,8 @@ def target(): @mock.patch("elasticapm.metrics.base_metrics.DISTINCT_LABEL_LIMIT", 3) -def test_metric_limit(caplog): - m = MetricsSet(MetricsRegistry(0, lambda x: None)) +def test_metric_limit(caplog, elasticapm_client): + m = MetricsSet(MetricsRegistry(elasticapm_client)) with caplog.at_level(logging.WARNING, logger="elasticapm.metrics"): for i in range(2): counter = m.counter("counter", some_label=i) @@ -151,8 +147,8 @@ def test_metric_limit(caplog): assert "The limit of 3 metricsets has been reached" in record.message -def test_metrics_not_collected_if_zero_and_reset(): - m = MetricsSet(MetricsRegistry(0, lambda x: None)) +def test_metrics_not_collected_if_zero_and_reset(elasticapm_client): + m = MetricsSet(MetricsRegistry(elasticapm_client)) counter = m.counter("counter", reset_on_collect=False) resetting_counter = m.counter("resetting_counter", reset_on_collect=True) gauge = m.gauge("gauge", reset_on_collect=False) diff --git a/tests/metrics/cpu_linux_tests.py b/tests/metrics/cpu_linux_tests.py index 46822a066..1b1ae2fa2 100644 --- a/tests/metrics/cpu_linux_tests.py +++ b/tests/metrics/cpu_linux_tests.py @@ -46,7 +46,7 @@ TEMPLATE_PROC_STAT_DEBIAN = """cpu {user} 2037 278561 {idle} 15536 0 178811 0 0 0 cpu0 189150 166 34982 1081369 2172 0 73586 0 0 0 cpu1 190286 201 35110 637359 1790 0 41941 0 0 0 -intr 60591079 11 12496 0 0 0 0 0 0 1 27128 0 0 474144 0 0 0 0 0 0 0 0 0 0 +intr 60591079 11 12496 0 0 0 0 0 0 1 27128 0 0 474144 0 0 0 0 0 0 0 0 0 0 ctxt 215687788 btime 1544981001 processes 416902 @@ -88,7 +88,7 @@ @pytest.mark.parametrize("proc_stat_template", [TEMPLATE_PROC_STAT_DEBIAN, TEMPLATE_PROC_STAT_RHEL]) -def test_cpu_mem_from_proc(proc_stat_template, tmpdir): +def test_cpu_mem_from_proc(elasticapm_client, proc_stat_template, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") @@ -101,7 +101,7 @@ def test_cpu_mem_from_proc(proc_stat_template, tmpdir): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( - MetricsRegistry(0, lambda x: None), + MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, @@ -125,7 +125,7 @@ def test_cpu_mem_from_proc(proc_stat_template, tmpdir): assert data["samples"]["system.process.memory.size"]["value"] == 3686981632 -def test_mem_free_from_memfree_when_memavailable_not_mentioned(tmpdir): +def test_mem_free_from_memfree_when_memavailable_not_mentioned(elasticapm_client, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") @@ -138,7 +138,7 @@ def test_mem_free_from_memfree_when_memavailable_not_mentioned(tmpdir): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( - MetricsRegistry(0, lambda x: None), + MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, @@ -157,7 +157,7 @@ def test_mem_free_from_memfree_when_memavailable_not_mentioned(tmpdir): assert data["samples"]["system.memory.actual.free"]["value"] == mem_free_expected -def test_cpu_usage_when_cpu_total_is_zero(tmpdir): +def test_cpu_usage_when_cpu_total_is_zero(elasticapm_client, tmpdir): proc_stat_self = os.path.join(tmpdir.strpath, "self-stat") proc_stat = os.path.join(tmpdir.strpath, "stat") proc_meminfo = os.path.join(tmpdir.strpath, "meminfo") @@ -170,7 +170,7 @@ def test_cpu_usage_when_cpu_total_is_zero(tmpdir): with open(path, mode="w") as f: f.write(content) metricset = CPUMetricSet( - MetricsRegistry(0, lambda x: None), + MetricsRegistry(elasticapm_client), sys_stats_file=proc_stat, process_stats_file=proc_stat_self, memory_stats_file=proc_meminfo, diff --git a/tests/metrics/cpu_psutil_tests.py b/tests/metrics/cpu_psutil_tests.py index 097ca5863..55ccae8a9 100644 --- a/tests/metrics/cpu_psutil_tests.py +++ b/tests/metrics/cpu_psutil_tests.py @@ -39,8 +39,8 @@ pytestmark = pytest.mark.psutil -def test_cpu_mem_from_psutil(): - metricset = cpu_psutil.CPUMetricSet(MetricsRegistry(0, lambda x: None)) +def test_cpu_mem_from_psutil(elasticapm_client): + metricset = cpu_psutil.CPUMetricSet(MetricsRegistry(elasticapm_client)) # do something that generates some CPU load for i in compat.irange(10 ** 6): j = i * i @@ -62,9 +62,9 @@ def test_cpu_mem_from_psutil(): @pytest.mark.skip("test is flaky on CI") -def test_compare_psutil_linux_metricsets(): - psutil_metricset = cpu_psutil.CPUMetricSet(MetricsRegistry(0, lambda x: None)) - linux_metricset = cpu_linux.CPUMetricSet(MetricsRegistry(0, lambda x: None)) +def test_compare_psutil_linux_metricsets(elasticapm_client): + psutil_metricset = cpu_psutil.CPUMetricSet(MetricsRegistry(elasticapm_client)) + linux_metricset = cpu_linux.CPUMetricSet(MetricsRegistry(elasticapm_client)) # do something that generates some CPU load for i in compat.irange(10 ** 6): j = i * i