Skip to content

Commit a5c5ad8

Browse files
authored
Check LambdaRuntimeClient before logging tracebacks in _ensure_flush_after_aws_lambda (#388)
1 parent b7afdd5 commit a5c5ad8

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

logfire/_internal/config.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99
import time
1010
import warnings
11+
from contextlib import suppress
1112
from dataclasses import dataclass, field
1213
from functools import cached_property
1314
from pathlib import Path
@@ -862,15 +863,26 @@ def wrapper(*args: Any, **kwargs: Any) -> Any:
862863
client = getattr(mod, 'LambdaRuntimeClient', None)
863864
except Exception: # pragma: no cover
864865
continue
865-
if not client: # pragma: no branch
866+
if not client:
866867
continue
867868
try: # pragma: no cover
868869
client.post_invocation_error = wrap_client_post_invocation_method(client.post_invocation_error)
869870
client.post_invocation_result = wrap_client_post_invocation_method(client.post_invocation_result)
870-
except Exception: # pragma: no cover
871+
except Exception as e: # pragma: no cover
872+
with suppress(Exception):
873+
# client is likely some random object from a dynamic module unrelated to AWS lambda.
874+
# If it doesn't look like the LambdaRuntimeClient class, ignore this error.
875+
# We don't check this beforehand so that if the lambda runtime library changes
876+
# LambdaRuntimeClient to some object other than a class,
877+
# or something else patches it with some kind of wrapper,
878+
# our patching still has some chance of working.
879+
# But we also don't want to log spurious noisy tracebacks.
880+
if not (isinstance(client, type) and client.__name__ == 'LambdaRuntimeClient'):
881+
continue
882+
871883
import traceback
872884

873-
traceback.print_exc()
885+
traceback.print_exception(e)
874886

875887

876888
def _get_default_span_processor(exporter: SpanExporter) -> SpanProcessor:
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# See test_dynamic_module_ignored_in_ensure_flush_after_aws_lambda
2+
3+
4+
def __getattr__(name: str) -> str:
5+
return name

tests/test_auto_trace.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,14 +138,23 @@ def test_check_already_imported() -> None:
138138
# because we don't want anything to get auto-traced here.
139139
imported_modules = set(sys.modules.items())
140140

141+
meta_path = sys.meta_path.copy()
142+
141143
with pytest.raises(AutoTraceModuleAlreadyImportedException, match=r"The module 'tests.*' matches modules to trace"):
142144
install_auto_tracing(['tests'])
143145

146+
with pytest.raises(ValueError):
147+
install_auto_tracing(['tests'], check_imported_modules='other') # type: ignore
148+
149+
# No tracing installed.
150+
assert sys.meta_path == meta_path
151+
144152
with pytest.warns(AutoTraceModuleAlreadyImportedWarning, match=r"The module 'tests.*' matches modules to trace"):
145153
install_auto_tracing(['tests'], check_imported_modules='warn')
146154

147-
with pytest.raises(ValueError):
148-
install_auto_tracing(['tests'], check_imported_modules='other') # type: ignore
155+
# The tracing was installed, undo it.
156+
assert sys.meta_path[1:] == meta_path
157+
sys.meta_path = meta_path
149158

150159
assert set(sys.modules.items()) == imported_modules
151160

tests/test_configure.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,6 +1452,18 @@ def get_metric_readers() -> Iterable[SpanProcessor]:
14521452
return get_meter_provider().provider._sdk_config.metric_readers # type: ignore
14531453

14541454

1455+
def test_dynamic_module_ignored_in_ensure_flush_after_aws_lambda(
1456+
config_kwargs: dict[str, Any], capsys: pytest.CaptureFixture[str]
1457+
):
1458+
from tests.import_used_for_tests.module_with_getattr import module_with_getattr_value
1459+
1460+
assert module_with_getattr_value == 'module_with_getattr_value'
1461+
1462+
logfire.configure(**config_kwargs)
1463+
1464+
assert capsys.readouterr().err == ''
1465+
1466+
14551467
def test_collect_system_metrics_false():
14561468
with inline_snapshot.extra.raises(
14571469
snapshot(

0 commit comments

Comments
 (0)