Skip to content

Commit d7ab602

Browse files
committed
fix: lazy loading core attr, custom provider patch
1 parent 1ad18c9 commit d7ab602

File tree

3 files changed

+54
-9
lines changed

3 files changed

+54
-9
lines changed

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ test:
2020
poetry run pytest -m "not perf" --cov=aws_lambda_powertools --cov-report=xml
2121
poetry run pytest --cache-clear tests/performance
2222

23+
unit-test:
24+
poetry run pytest tests/unit
25+
2326
coverage-html:
2427
poetry run pytest -m "not perf" --cov=aws_lambda_powertools --cov-report=html
2528

aws_lambda_powertools/tracing/tracer.py

+32-9
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
logger = logging.getLogger(__name__)
1818

1919
aws_xray_sdk = LazyLoader(constants.XRAY_SDK_MODULE, globals(), constants.XRAY_SDK_MODULE)
20-
aws_xray_sdk.core = LazyLoader(constants.XRAY_SDK_CORE_MODULE, globals(), constants.XRAY_SDK_CORE_MODULE) # type: ignore # noqa: E501
2120

2221

2322
class Tracer:
@@ -156,7 +155,7 @@ def __init__(
156155
self.__build_config(
157156
service=service, disabled=disabled, auto_patch=auto_patch, patch_modules=patch_modules, provider=provider
158157
)
159-
self.provider: BaseProvider = self._config["provider"]
158+
self.provider = self._config["provider"]
160159
self.disabled = self._config["disabled"]
161160
self.service = self._config["service"]
162161
self.auto_patch = self._config["auto_patch"]
@@ -167,10 +166,18 @@ def __init__(
167166
if self.auto_patch:
168167
self.patch(modules=patch_modules)
169168

170-
# Set the streaming threshold to 0 on the default recorder to force sending
171-
# subsegments individually, rather than batching them.
172-
# See https://github.com/awslabs/aws-lambda-powertools-python/issues/283
173-
aws_xray_sdk.core.xray_recorder.configure(streaming_threshold=0) # noqa: E800
169+
if "aws_xray_sdk" in self.provider.__module__:
170+
self._disable_xray_trace_batching()
171+
172+
def _disable_xray_trace_batching(self):
173+
"""Configure X-Ray SDK to send subsegment individually over batching
174+
Known issue: https://github.com/awslabs/aws-lambda-powertools-python/issues/283
175+
"""
176+
if self.disabled:
177+
logger.debug("Tracing has been disabled, aborting streaming override")
178+
return
179+
180+
aws_xray_sdk.core.xray_recorder.configure(streaming_threshold=0)
174181

175182
def put_annotation(self, key: str, value: Union[str, numbers.Number, bool]):
176183
"""Adds annotation to existing segment or subsegment
@@ -239,9 +246,9 @@ def patch(self, modules: Optional[Sequence[str]] = None):
239246
return
240247

241248
if modules is None:
242-
aws_xray_sdk.core.patch_all()
249+
self.provider.patch_all()
243250
else:
244-
aws_xray_sdk.core.patch(modules)
251+
self.provider.patch(modules)
245252

246253
def capture_lambda_handler(
247254
self,
@@ -743,7 +750,8 @@ def __build_config(
743750
is_disabled = disabled if disabled is not None else self._is_tracer_disabled()
744751
is_service = resolve_env_var_choice(choice=service, env=os.getenv(constants.SERVICE_NAME_ENV))
745752

746-
self._config["provider"] = provider or self._config["provider"] or aws_xray_sdk.core.xray_recorder
753+
# Logic: Choose overridden option first, previously cached config, or default if available
754+
self._config["provider"] = provider or self._config["provider"] or self._patch_xray_provider()
747755
self._config["auto_patch"] = auto_patch if auto_patch is not None else self._config["auto_patch"]
748756
self._config["service"] = is_service or self._config["service"]
749757
self._config["disabled"] = is_disabled or self._config["disabled"]
@@ -752,3 +760,18 @@ def __build_config(
752760
@classmethod
753761
def _reset_config(cls):
754762
cls._config = copy.copy(cls._default_config)
763+
764+
def _patch_xray_provider(self):
765+
# Due to Lazy Import, we need to activate `core` attrib via import
766+
# we also need to include `patch`, `patch_all` methods
767+
# to ensure patch calls are done via the provider
768+
from aws_xray_sdk.core import xray_recorder
769+
770+
provider = xray_recorder
771+
provider.patch = aws_xray_sdk.core.patch
772+
provider.patch_all = aws_xray_sdk.core.patch_all
773+
774+
return provider
775+
776+
def _is_xray_provider(self):
777+
return "aws_xray_sdk" in self.provider.__module__

tests/unit/test_tracing.py

+19
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ def in_subsegment(self, *args, **kwargs):
4444
def patch(self, *args, **kwargs):
4545
return self.patch_mock(*args, **kwargs)
4646

47+
def patch_all(self):
48+
...
49+
4750
return CustomProvider
4851

4952

@@ -590,3 +593,19 @@ def handler(event, context):
590593

591594
handler({}, mocker.MagicMock())
592595
assert in_subsegment_mock.put_annotation.call_args == mocker.call(key="ColdStart", value=False)
596+
597+
598+
def test_tracer_lambda_handler_add_service_annotation(mocker, dummy_response, provider_stub, in_subsegment_mock):
599+
# GIVEN
600+
provider = provider_stub(in_subsegment=in_subsegment_mock.in_subsegment)
601+
tracer = Tracer(provider=provider, service="booking")
602+
603+
# WHEN
604+
@tracer.capture_lambda_handler
605+
def handler(event, context):
606+
return dummy_response
607+
608+
handler({}, mocker.MagicMock())
609+
610+
# THEN
611+
assert in_subsegment_mock.put_annotation.call_args == mocker.call(key="Service", value="booking")

0 commit comments

Comments
 (0)