From 080d6073d5833e936e7ce2d800f5d13fa0a77043 Mon Sep 17 00:00:00 2001 From: Paulo Vital Date: Thu, 24 Sep 2026 23:36:53 +0200 Subject: [PATCH] fix: AWS Lambda collector. Fix initialization of spans and metrics collectors for the AWS Lambda Collector. Signed-off-by: Paulo Vital --- src/instana/agent/serverless.py | 2 +- src/instana/collector/aws_lambda.py | 4 +- tests/agent/test_serverless_agent.py | 12 ++++ tests/collector/test_aws_lambda_collector.py | 70 ++++++++++++++++++++ 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 tests/collector/test_aws_lambda_collector.py diff --git a/src/instana/agent/serverless.py b/src/instana/agent/serverless.py index e61261e9..8aad0068 100644 --- a/src/instana/agent/serverless.py +++ b/src/instana/agent/serverless.py @@ -153,7 +153,7 @@ def _prepare_payload(self, payload: dict[str, Any]) -> dict[str, Any]: Returns: Modified payload with filtered spans """ - spans = payload.get("spans", []) + spans = payload.get("spans") or [] filtered_spans = self.filter_spans(spans) if len(filtered_spans) > 0: diff --git a/src/instana/collector/aws_lambda.py b/src/instana/collector/aws_lambda.py index 1d680739..7b4c86f3 100644 --- a/src/instana/collector/aws_lambda.py +++ b/src/instana/collector/aws_lambda.py @@ -46,8 +46,8 @@ def should_send_snapshot_data(self): def prepare_payload(self): payload = DictionaryOfStan() - payload["spans"] = None - payload["metrics"] = None + payload["spans"] = [] + payload["metrics"]["plugins"] = [] if not self.span_queue.empty(): payload["spans"] = format_span(self.queued_spans()) diff --git a/tests/agent/test_serverless_agent.py b/tests/agent/test_serverless_agent.py index 3ea6d2af..16c422cf 100644 --- a/tests/agent/test_serverless_agent.py +++ b/tests/agent/test_serverless_agent.py @@ -205,6 +205,18 @@ def test_prepare_payload_with_no_spans(self) -> None: assert "metrics" in result assert "spans" not in result or len(result.get("spans", [])) == 0 + def test_prepare_payload_with_none_spans(self) -> None: + """Test payload preparation when spans are explicitly None.""" + agent = ConcreteServerlessAgent() + + payload = {"spans": None, "metrics": {"test": "data"}} + + result = agent._prepare_payload(payload) + + assert "metrics" in result + # Should handle None spans without raising a TypeError + assert result["spans"] is None + def test_build_headers(self) -> None: """Test that headers are built correctly.""" agent = ConcreteServerlessAgent() diff --git a/tests/collector/test_aws_lambda_collector.py b/tests/collector/test_aws_lambda_collector.py new file mode 100644 index 00000000..31201699 --- /dev/null +++ b/tests/collector/test_aws_lambda_collector.py @@ -0,0 +1,70 @@ +# (c) Copyright IBM Corp. 2026 + +""" +Unit tests for AWSLambdaCollector. +This test suite validates the payload preparation and metric reporting +for the AWS Lambda instrumentation collector. +""" + +from collections import defaultdict +from typing import Generator +from unittest.mock import MagicMock, patch + +import pytest + +from instana.collector.aws_lambda import AWSLambdaCollector + + +class TestAWSLambdaCollector: + """Test suite for AWSLambdaCollector base class.""" + + @pytest.fixture(autouse=True) + def _resource( + self, + caplog: pytest.LogCaptureFixture, + ) -> Generator[None, None, None]: + + self.agent = MagicMock() + self.collector = AWSLambdaCollector(self.agent) + yield + + def test_prepare_payload_empty_span_queue(self) -> None: + """Test that prepare_payload returns an empty list for spans when queue is empty.""" + payload = self.collector.prepare_payload() + + assert isinstance(payload, defaultdict) + + assert "spans" in payload + assert payload["spans"] == [] + + assert "metrics" in payload + assert "plugins" in payload["metrics"] + + def test_prepare_payload_with_spans(self) -> None: + """Test that prepare_payload formats queued spans and includes them in the payload.""" + mock_span = MagicMock() + self.collector.span_queue.put(mock_span) + + # Mock queued_spans and format_span + self.collector.queued_spans = MagicMock(return_value=[mock_span]) + + with patch("instana.collector.aws_lambda.format_span") as mock_format: + mock_format.return_value = [{"n": "test_span"}] + payload = self.collector.prepare_payload() + + assert payload["spans"] == [{"n": "test_span"}] + assert payload["metrics"]["plugins"] == [] + + def test_prepare_payload_with_snapshot_data(self) -> None: + """Test that prepare_payload includes snapshot data when it should be sent.""" + self.collector.snapshot_data = { + "plugins": [{"name": "com.instana.plugin.aws.lambda"}] + } + self.collector.snapshot_data_sent = False + + payload = self.collector.prepare_payload() + + assert payload["metrics"] == { + "plugins": [{"name": "com.instana.plugin.aws.lambda"}] + } + assert self.collector.snapshot_data_sent is True