Skip to content

Commit 1822ebe

Browse files
committed
docs(tracer): update single code blocks to title
1 parent f063550 commit 1822ebe

File tree

2 files changed

+106
-140
lines changed

2 files changed

+106
-140
lines changed

docs/core/tracer.md

Lines changed: 104 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -20,43 +20,36 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github.
2020

2121
Before your use this utility, your AWS Lambda function [must have permissions](https://docs.aws.amazon.com/lambda/latest/dg/services-xray.html#services-xray-permissions) to send traces to AWS X-Ray.
2222

23-
???+ example
24-
**AWS Serverless Application Model (SAM)**
25-
26-
=== "template.yml"
27-
28-
```yaml hl_lines="6 9"
29-
Resources:
30-
HelloWorldFunction:
31-
Type: AWS::Serverless::Function
32-
Properties:
33-
Runtime: python3.8
34-
Tracing: Active
35-
Environment:
36-
Variables:
37-
POWERTOOLS_SERVICE_NAME: example
38-
```
23+
```yaml hl_lines="6 9" title="AWS Serverless Application Model (SAM) example"
24+
Resources:
25+
HelloWorldFunction:
26+
Type: AWS::Serverless::Function
27+
Properties:
28+
Runtime: python3.8
29+
Tracing: Active
30+
Environment:
31+
Variables:
32+
POWERTOOLS_SERVICE_NAME: example
33+
```
3934

4035
### Lambda handler
4136

42-
You can quickly start by importing the `Tracer` class, initialize it outside the Lambda handler, and use `capture_lambda_handler` decorator.
43-
44-
=== "app.py"
37+
You can quickly start by initializing `Tracer` and use `capture_lambda_handler` decorator for your Lambda handler.
4538

46-
```python hl_lines="1 3 6"
47-
from aws_lambda_powertools import Tracer
39+
```python hl_lines="1 3 6" title="Tracing Lambda handler with capture_lambda_handler"
40+
from aws_lambda_powertools import Tracer
4841

49-
tracer = Tracer() # Sets service via env var
50-
# OR tracer = Tracer(service="example")
42+
tracer = Tracer() # Sets service via env var
43+
# OR tracer = Tracer(service="example")
5144

52-
@tracer.capture_lambda_handler
53-
def handler(event, context):
54-
charge_id = event.get('charge_id')
55-
payment = collect_payment(charge_id)
56-
...
57-
```
45+
@tracer.capture_lambda_handler
46+
def handler(event, context):
47+
charge_id = event.get('charge_id')
48+
payment = collect_payment(charge_id)
49+
...
50+
```
5851

59-
When using this `capture_lambda_handler` decorator, Tracer performs these additional tasks to ease operations:
52+
`capture_lambda_handler` performs these additional tasks to ease operations:
6053

6154
* Creates a `ColdStart` annotation to easily filter traces that have had an initialization overhead
6255
* Creates a `Service` annotation if `service` parameter or `POWERTOOLS_SERVICE_NAME` is set
@@ -66,51 +59,48 @@ When using this `capture_lambda_handler` decorator, Tracer performs these additi
6659

6760
**Annotations** are key-values associated with traces and indexed by AWS X-Ray. You can use them to filter traces and to create [Trace Groups](https://aws.amazon.com/about-aws/whats-new/2018/11/aws-xray-adds-the-ability-to-group-traces/) to slice and dice your transactions.
6861

69-
**Metadata** are key-values also associated with traces but not indexed by AWS X-Ray. You can use them to add additional context for an operation using any native object.
70-
71-
=== "Annotations"
72-
You can add annotations using `put_annotation` method.
62+
```python hl_lines="7" title="Adding annotations with put_annotation method"
63+
from aws_lambda_powertools import Tracer
64+
tracer = Tracer()
7365

74-
```python hl_lines="7"
75-
from aws_lambda_powertools import Tracer
76-
tracer = Tracer()
66+
@tracer.capture_lambda_handler
67+
def handler(event, context):
68+
...
69+
tracer.put_annotation(key="PaymentStatus", value="SUCCESS")
70+
```
7771

78-
@tracer.capture_lambda_handler
79-
def handler(event, context):
80-
...
81-
tracer.put_annotation(key="PaymentStatus", value="SUCCESS")
82-
```
83-
=== "Metadata"
84-
You can add metadata using `put_metadata` method.
72+
**Metadata** are key-values also associated with traces but not indexed by AWS X-Ray. You can use them to add additional context for an operation using any native object.
8573

86-
```python hl_lines="8"
87-
from aws_lambda_powertools import Tracer
88-
tracer = Tracer()
74+
```python hl_lines="8" title="Adding arbitrary metadata with put_metadata method"
75+
from aws_lambda_powertools import Tracer
76+
tracer = Tracer()
8977

90-
@tracer.capture_lambda_handler
91-
def handler(event, context):
92-
...
93-
ret = some_logic()
94-
tracer.put_metadata(key="payment_response", value=ret)
95-
```
78+
@tracer.capture_lambda_handler
79+
def handler(event, context):
80+
...
81+
ret = some_logic()
82+
tracer.put_metadata(key="payment_response", value=ret)
83+
```
9684

9785
### Synchronous functions
9886

9987
You can trace synchronous functions using the `capture_method` decorator.
10088

101-
???+ warning "Warning: When `capture_response` is enabled, the function response will be read and serialized as json"
89+
```python hl_lines="7 13" title="Tracing an arbitrary function with capture_method"
90+
@tracer.capture_method
91+
def collect_payment(charge_id):
92+
ret = requests.post(PAYMENT_ENDPOINT) # logic
93+
tracer.put_annotation("PAYMENT_STATUS", "SUCCESS") # custom annotation
94+
return ret
95+
```
10296

103-
The serialization is performed by the aws-xray-sdk which uses the `jsonpickle` module. This can cause
104-
unintended consequences if there are side effects to recursively reading the returned value, for example if the
105-
decorated function response contains a file-like object or a <a href="https://botocore.amazonaws.com/v1/documentation/api/latest/reference/response.html#botocore.response.StreamingBody">`StreamingBody`</a> for S3 objects.
97+
???+ note "Note: Function responses are auto-captured and stored as JSON, by default."
98+
99+
Use [capture_response](#disabling-response-auto-capture) parameter to override this behaviour.
100+
101+
The serialization is performed by aws-xray-sdk via `jsonpickle` module. This can cause
102+
side effects for file-like objects like boto S3 <a href="https://botocore.amazonaws.com/v1/documentation/api/latest/reference/response.html#botocore.response.StreamingBody">`StreamingBody`</a>, where its response will be read only once during serialization.
106103

107-
```python hl_lines="7 13"
108-
@tracer.capture_method
109-
def collect_payment(charge_id):
110-
ret = requests.post(PAYMENT_ENDPOINT) # logic
111-
tracer.put_annotation("PAYMENT_STATUS", "SUCCESS") # custom annotation
112-
return ret
113-
```
114104

115105
### Asynchronous and generator functions
116106

@@ -164,21 +154,6 @@ You can trace asynchronous functions and generator functions (including context
164154
...
165155
```
166156

167-
The decorator will detect whether your function is asynchronous, a generator, or a context manager and adapt its behaviour accordingly.
168-
169-
=== "app.py"
170-
171-
```python
172-
@tracer.capture_lambda_handler
173-
def handler(evt, ctx):
174-
asyncio.run(collect_payment())
175-
176-
with collect_payment_ctxman as result:
177-
do_something_with(result)
178-
179-
another_result = list(collect_payment_gen())
180-
```
181-
182157
## Advanced
183158

184159
### Patching modules
@@ -187,17 +162,15 @@ Tracer automatically patches all [supported libraries by X-Ray](https://docs.aws
187162

188163
If you're looking to shave a few microseconds, or milliseconds depending on your function memory configuration, you can patch specific modules using `patch_modules` param:
189164

190-
=== "app.py"
191-
192-
```python hl_lines="7"
193-
import boto3
194-
import requests
165+
```python hl_lines="7" title="Example of explicitly patching boto3 and requests only"
166+
import boto3
167+
import requests
195168

196-
from aws_lambda_powertools import Tracer
169+
from aws_lambda_powertools import Tracer
197170

198-
modules_to_be_patched = ["boto3", "requests"]
199-
tracer = Tracer(patch_modules=modules_to_be_patched)
200-
```
171+
modules_to_be_patched = ["boto3", "requests"]
172+
tracer = Tracer(patch_modules=modules_to_be_patched)
173+
```
201174

202175
### Disabling response auto-capture
203176

@@ -240,15 +213,13 @@ Use **`capture_error=False`** parameter in both `capture_lambda_handler` and `ca
240213
???+ info
241214
Useful when returning sensitive information in exceptions/stack traces you don't control
242215

243-
=== "sensitive_data_exception.py"
244-
245-
```python hl_lines="3 5"
246-
from aws_lambda_powertools import Tracer
216+
```python hl_lines="3 5" title="Disabling exception auto-capture for tracing metadata"
217+
from aws_lambda_powertools import Tracer
247218

248-
@tracer.capture_lambda_handler(capture_error=False)
249-
def handler(event, context):
250-
raise ValueError("some sensitive info in the stack trace...")
251-
```
219+
@tracer.capture_lambda_handler(capture_error=False)
220+
def handler(event, context):
221+
raise ValueError("some sensitive info in the stack trace...")
222+
```
252223

253224
### Tracing aiohttp requests
254225

@@ -257,43 +228,39 @@ Use **`capture_error=False`** parameter in both `capture_lambda_handler` and `ca
257228

258229
You can use `aiohttp_trace_config` function to create a valid [aiohttp trace_config object](https://docs.aiohttp.org/en/stable/tracing_reference.html). This is necessary since X-Ray utilizes aiohttp trace hooks to capture requests end-to-end.
259230

260-
=== "aiohttp_example.py"
231+
```python hl_lines="5 10" title="Tracing aiohttp requests"
232+
import asyncio
233+
import aiohttp
261234

262-
```python hl_lines="5 10"
263-
import asyncio
264-
import aiohttp
265-
266-
from aws_lambda_powertools import Tracer
267-
from aws_lambda_powertools.tracing import aiohttp_trace_config
235+
from aws_lambda_powertools import Tracer
236+
from aws_lambda_powertools.tracing import aiohttp_trace_config
268237

269-
tracer = Tracer()
238+
tracer = Tracer()
270239

271-
async def aiohttp_task():
272-
async with aiohttp.ClientSession(trace_configs=[aiohttp_trace_config()]) as session:
273-
async with session.get("https://httpbin.org/json") as resp:
274-
resp = await resp.json()
275-
return resp
276-
```
240+
async def aiohttp_task():
241+
async with aiohttp.ClientSession(trace_configs=[aiohttp_trace_config()]) as session:
242+
async with session.get("https://httpbin.org/json") as resp:
243+
resp = await resp.json()
244+
return resp
245+
```
277246

278247
### Escape hatch mechanism
279248

280249
You can use `tracer.provider` attribute to access all methods provided by AWS X-Ray `xray_recorder` object.
281250

282251
This is useful when you need a feature available in X-Ray that is not available in the Tracer utility, for example [thread-safe](https://github.com/aws/aws-xray-sdk-python/#user-content-trace-threadpoolexecutor), or [context managers](https://github.com/aws/aws-xray-sdk-python/#user-content-start-a-custom-segmentsubsegment).
283252

284-
=== "escape_hatch_context_manager_example.py"
285-
286-
```python hl_lines="7"
287-
from aws_lambda_powertools import Tracer
253+
```python hl_lines="7" title="Tracing a code block with in_subsegment escape hatch"
254+
from aws_lambda_powertools import Tracer
288255

289-
tracer = Tracer()
256+
tracer = Tracer()
290257

291-
@tracer.capture_lambda_handler
292-
def handler(event, context):
293-
with tracer.provider.in_subsegment('## custom subsegment') as subsegment:
294-
ret = some_work()
295-
subsegment.put_metadata('response', ret)
296-
```
258+
@tracer.capture_lambda_handler
259+
def handler(event, context):
260+
with tracer.provider.in_subsegment('## custom subsegment') as subsegment:
261+
ret = some_work()
262+
subsegment.put_metadata('response', ret)
263+
```
297264

298265
### Concurrent asynchronous functions
299266

@@ -302,28 +269,26 @@ This is useful when you need a feature available in X-Ray that is not available
302269

303270
A safe workaround mechanism is to use `in_subsegment_async` available via Tracer escape hatch (`tracer.provider`).
304271

305-
=== "concurrent_async_workaround.py"
272+
```python hl_lines="6 7 12 15 17" title="Workaround to safely trace async concurrent functions"
273+
import asyncio
306274

307-
```python hl_lines="6 7 12 15 17"
308-
import asyncio
309-
310-
from aws_lambda_powertools import Tracer
311-
tracer = Tracer()
275+
from aws_lambda_powertools import Tracer
276+
tracer = Tracer()
312277

313-
async def another_async_task():
314-
async with tracer.provider.in_subsegment_async("## another_async_task") as subsegment:
315-
subsegment.put_annotation(key="key", value="value")
316-
subsegment.put_metadata(key="key", value="value", namespace="namespace")
317-
...
278+
async def another_async_task():
279+
async with tracer.provider.in_subsegment_async("## another_async_task") as subsegment:
280+
subsegment.put_annotation(key="key", value="value")
281+
subsegment.put_metadata(key="key", value="value", namespace="namespace")
282+
...
318283

319-
async def another_async_task_2():
320-
...
284+
async def another_async_task_2():
285+
...
321286

322-
@tracer.capture_method
323-
async def collect_payment(charge_id):
324-
asyncio.gather(another_async_task(), another_async_task_2())
325-
...
326-
```
287+
@tracer.capture_method
288+
async def collect_payment(charge_id):
289+
asyncio.gather(another_async_task(), another_async_task_2())
290+
...
291+
```
327292

328293
### Reusing Tracer across your code
329294

docs/stylesheets/extra.css

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
border-bottom: 0.1px dashed black;
4040
}
4141

42-
p > code {
42+
p > code,
43+
li > code {
4344
font-weight: bold
4445
}

0 commit comments

Comments
 (0)