From a34cf5d6d3f089d7e293ace66dadc2cded864709 Mon Sep 17 00:00:00 2001 From: Riccardo Magliocchetti Date: Fri, 19 Dec 2025 10:02:52 +0100 Subject: [PATCH] elasticapm: introduce ELASTIC_APM_SKIP_SERVER_INFO Introduce this option in order to avoid fetch the apm server info to get its version, off by default. Calling that endpoint with the aws lambda extension incurs in a measurable latency on AWS Lambda. Enabling this issue requires the receiving APM server version to be greater than 8.7.0. Option is still in technical preview. --- docs/reference/configuration.md | 17 +++++++++++++++++ elasticapm/conf/__init__.py | 1 + elasticapm/transport/http.py | 6 +++++- tests/transports/test_urllib3.py | 17 +++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/docs/reference/configuration.md b/docs/reference/configuration.md index 5934f3b6e..1841631c7 100644 --- a/docs/reference/configuration.md +++ b/docs/reference/configuration.md @@ -969,6 +969,23 @@ If set to `True`, the agent will intercept the default `sys.excepthook`, which a Whether each transaction should have the process arguments attached. Disabled by default to save disk space. +### `skip_server_info` [config-skip-server-info] + +| Environment | Django/Flask | Default | +| --- | --- | --- | +| `ELASTIC_APM_SKIP_SERVER_INFO` | `SKIP_SERVER_INFO` | `False` | + +Whether we should skip the server info check to save some latency on constrained environments like AWS Lambda. Disabled by default. + +::::{warning} +This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features. +:::: + +::::{warning} +This requires sending data to an APM Server newer than 8.7.0 in order to work properly. +:::: + + ## Django-specific configuration [config-django-specific] diff --git a/elasticapm/conf/__init__.py b/elasticapm/conf/__init__.py index 6d19eb96c..f00a2cda9 100644 --- a/elasticapm/conf/__init__.py +++ b/elasticapm/conf/__init__.py @@ -743,6 +743,7 @@ class Config(_ConfigBase): default=TRACE_CONTINUATION_STRATEGY.CONTINUE, ) include_process_args = _BoolConfigValue("INCLUDE_PROCESS_ARGS", default=False) + skip_server_info = _BoolConfigValue("SKIP_SERVER_INFO", default=False) @property def is_recording(self): diff --git a/elasticapm/transport/http.py b/elasticapm/transport/http.py index ed132068c..cd960e40f 100644 --- a/elasticapm/transport/http.py +++ b/elasticapm/transport/http.py @@ -203,7 +203,11 @@ def _get_cache_control_max_age(self, response_headers): def _process_queue(self) -> None: if not self.client.server_version: - self.fetch_server_info() + # this is useful on aws lambda environments where this call incurs in unwanted latency + if self.client.config.skip_server_info: + logger.debug("Skipping to fetch server info") + else: + self.fetch_server_info() super()._process_queue() def fetch_server_info(self) -> None: diff --git a/tests/transports/test_urllib3.py b/tests/transports/test_urllib3.py index 32a5b7384..78bc26200 100644 --- a/tests/transports/test_urllib3.py +++ b/tests/transports/test_urllib3.py @@ -520,6 +520,23 @@ def test_fetch_server_info_flat_string(waiting_httpserver, caplog, elasticapm_cl assert_any_record_contains(caplog.records, "No version key found in server response") +def test_skip_server_info(waiting_httpserver, elasticapm_client): + elasticapm_client.config.update(version="1", skip_server_info=True) + waiting_httpserver.serve_content(code=202, content="", headers={"Location": "http://example.com/foo"}) + transport = Transport( + waiting_httpserver.url, client=elasticapm_client, headers=elasticapm_client._transport._headers + ) + transport.start_thread() + try: + url = transport.send("x".encode("latin-1")) + assert url == "http://example.com/foo" + finally: + transport.close() + + assert elasticapm_client.server_version is None + assert elasticapm_client.check_server_version(gte=(8, 7, 1)) + + def test_close(waiting_httpserver, elasticapm_client): elasticapm_client.server_version = (8, 0, 0) # avoid making server_info request waiting_httpserver.serve_content(code=202, content="", headers={"Location": "http://example.com/foo"})