forked from aws-powertools/powertools-lambda-python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtest_tracing.py
201 lines (141 loc) · 5.26 KB
/
test_tracing.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
import contextlib
import pytest
from aws_lambda_powertools import Tracer
@pytest.fixture
def dummy_response():
return {"test": "succeeds"}
@pytest.fixture(scope="function", autouse=True)
def reset_tracing_config():
Tracer._reset_config()
yield
@pytest.fixture
def service_name():
return "booking"
def test_capture_lambda_handler(dummy_response):
# GIVEN tracer lambda handler decorator is used
tracer = Tracer(disabled=True)
# WHEN a lambda handler is run
@tracer.capture_lambda_handler
def handler(event, context):
return dummy_response
# THEN tracer should not raise an Exception
handler({}, {})
def test_capture_method(dummy_response):
# GIVEN tracer method decorator is used
tracer = Tracer(disabled=True)
# WHEN a function is run
@tracer.capture_method
def greeting(name, message):
return dummy_response
# THEN tracer should not raise an Exception
greeting(name="Foo", message="Bar")
def test_tracer_lambda_emulator(monkeypatch, dummy_response):
# GIVEN tracer runs locally
monkeypatch.setenv("AWS_SAM_LOCAL", "true")
tracer = Tracer()
# WHEN a lambda function is run through SAM CLI
@tracer.capture_lambda_handler
def handler(event, context):
return dummy_response
# THEN tracer should run in disabled mode, and not raise an Exception
handler({}, {})
def test_tracer_chalice_cli_mode(monkeypatch, dummy_response):
# GIVEN tracer runs locally
monkeypatch.setenv("AWS_CHALICE_CLI_MODE", "true")
tracer = Tracer()
# WHEN a lambda function is run through the Chalice CLI.
@tracer.capture_lambda_handler
def handler(event, context):
return dummy_response
# THEN tracer should run in disabled mode, and not raise an Exception
handler({}, {})
def test_tracer_metadata_disabled(dummy_response):
# GIVEN tracer is disabled, and annotations/metadata are used
tracer = Tracer(disabled=True)
# WHEN a lambda handler is run
@tracer.capture_lambda_handler
def handler(event, context):
tracer.put_annotation("PaymentStatus", "SUCCESS")
tracer.put_metadata("PaymentMetadata", "Metadata")
return dummy_response
# THEN tracer should not raise any Exception
handler({}, {})
def test_tracer_service_env_var(monkeypatch, service_name):
# GIVEN tracer is run without parameters
# WHEN service is implicitly defined via env var
monkeypatch.setenv("POWERTOOLS_SERVICE_NAME", service_name)
tracer = Tracer(disabled=True)
# THEN tracer should have use that service name
assert tracer.service == service_name
def test_tracer_explicit_service(monkeypatch, service_name):
# GIVEN tracer is disabled
# WHEN service is explicitly defined
tracer_explicit = Tracer(disabled=True, service=service_name)
assert tracer_explicit.service == service_name
monkeypatch.setenv("POWERTOOLS_TRACE_DISABLED", "true")
tracer = Tracer()
# THEN tracer should have use that service name
assert tracer.service == service_name
def test_tracer_propagate_exception(mocker):
# GIVEN tracer decorator is used
class CustomException(Exception):
pass
tracer = Tracer(disabled=True)
# WHEN a lambda handler or method returns an Exception
@tracer.capture_lambda_handler
def handler(event, context):
raise CustomException("test")
@tracer.capture_method
def greeting():
raise CustomException("test")
# THEN tracer should reraise the same Exception
with pytest.raises(CustomException):
handler({}, {})
with pytest.raises(CustomException):
greeting()
def test_tracer_reuse_configuration(service_name):
# GIVEN tracer A is initialized
tracer_a = Tracer(disabled=True, service=service_name)
# WHEN tracer B is initialized afterwards
tracer_b = Tracer()
# THEN tracer B attributes should be equal to tracer A
assert tracer_a.__dict__.items() == tracer_b.__dict__.items()
def test_tracer_method_nested_sync(mocker):
# GIVEN tracer decorator is used
# WHEN multiple sync functions are nested
# THEN tracer should not raise a Runtime Error
tracer = Tracer(disabled=True)
@tracer.capture_method
def func_1():
return 1
@tracer.capture_method
def func_2():
return 2
@tracer.capture_method
def sums_values():
return func_1() + func_2()
sums_values()
def test_tracer_yield_with_capture():
# GIVEN tracer method decorator is used
tracer = Tracer(disabled=True)
# WHEN capture_method decorator is applied to a context manager
@tracer.capture_method
@contextlib.contextmanager
def yield_with_capture():
yield "testresult"
# Or WHEN capture_method decorator is applied to a generator function
@tracer.capture_method
def generator_func():
yield "testresult2"
@tracer.capture_lambda_handler
def handler(event, context):
result = []
with yield_with_capture() as yielded_value:
result.append(yielded_value)
gen = generator_func()
result.append(next(gen))
return result
# THEN no exception is thrown, and the functions properly return values
result = handler({}, {})
assert "testresult" in result
assert "testresult2" in result