You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/quickstart.md
+61-26Lines changed: 61 additions & 26 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -362,10 +362,16 @@ From here, we could handle [404 routes](./core/event_handler/api_gateway.md#hand
362
362
!!! tip
363
363
If you'd like to learn how python decorators work under the hood, you can follow [Real Python](https://realpython.com/primer-on-python-decorators/)'s article.
364
364
## Structured Logging
365
-
In the next step, you decided to propose production quality logging capabilities to your Lambda code.
366
-
We want our log event to be in a JSON format. Also, You follow [structured logging approach](https://docs.aws.amazon.com/lambda/latest/operatorguide/parse-logs.html). In a result, we expect easy to search, consistent logs containing enough context and data to analyse the status of our system. We can take advantage of CloudWatch Logs and Cloudwatch Insight for this purpose.
367
365
368
-
The first option could be to use a python logger in combination with the `pythonjsonlogger` library for simple structured logging.
366
+
Over time, you realize that searching logs as text results in poor observability, it's hard to create metrics from, enumerate common exceptions, etc.
367
+
368
+
Then, you decided to propose production quality logging capabilities to your Lambda code. You found out that by having logs as `JSON` you can [structure them](https://docs.aws.amazon.com/lambda/latest/operatorguide/parse-logs.html), so that you can use any Log Analytics tool out there to quickly analyze them.
369
+
370
+
This helps not only in searching, but produces consistent logs containing enough context and data to ask arbitrary questions on the status of your system. We can take advantage of CloudWatch Logs and Cloudwatch Insight for this purpose.
371
+
372
+
### Logs as JSON with pythonjsonlogger
373
+
374
+
The first option could be to use the standard Python Logger, and use a specialized library like `pythonjsonlogger` to create a JSON Formatter.
369
375
370
376
=== "app.py"
371
377
@@ -378,7 +384,7 @@ The first option could be to use a python logger in combination with the `python
378
384
379
385
from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver
[INFO] 2021-11-22T15:32:02.145Z ba3bea3d-fe3a-45db-a2ce-72e813d55b91 Request from unknown received
426
-
```
427
427
428
-
So far, so good! To make things easier, we want to add extra context to the logs.
429
-
We can extract it from a Lambda context or an event passed to Lambda handler at the time of invocation. We add those specific attributes wherever a logger is used.
428
+
=== "JSON output"
429
+
430
+
```json
431
+
{
432
+
"asctime": "2021-11-22 15:32:02,145",
433
+
"levelname": "INFO",
434
+
"name": "hello",
435
+
"message": "Request from unknown received"
436
+
}
437
+
```
438
+
439
+
=== "Normal output"
440
+
441
+
```python
442
+
[INFO] 2021-11-22T15:32:02.145Z ba3bea3d-fe3a-45db-a2ce-72e813d55b91 Request from unknown received
443
+
```
444
+
445
+
So far, so good! We can take a step further now by adding additional context to the logs.
446
+
447
+
We could start by creating a dictionary with Lambda context information or something from the incoming event, which should always be logged. Additional attributes could be added on every `logger.info` using `extra` keyword like in any standard Python logger.
448
+
449
+
450
+
### Simplifying with Logger
451
+
452
+
???+ question "Surely this could be easier, right?"
453
+
Yes! Powertools Logger to the rescue :-)
454
+
455
+
As we already have Lambda Powertools as a dependency, we can simply import [Logger](./core/logger.md){target="_blank"}.
430
456
431
-
Can we ensure that the required attributes are added automatically on our behalf without having to move them around? Yes! Powertools Logger to the rescue :-)
432
457
=== "app.py"
433
458
434
-
```python hl_lines="3 7 14 20 24"
459
+
```python hl_lines="3 5 7 14 20 24"
435
460
import json
436
461
437
462
from aws_lambda_powertools import Logger
438
463
from aws_lambda_powertools.event_handler.api_gateway import ApiGatewayResolver
439
464
from aws_lambda_powertools.logging import correlation_paths
440
465
441
-
logger = Logger(service="APP")
466
+
logger = Logger(service="order")
442
467
443
468
app = ApiGatewayResolver()
444
469
@@ -460,12 +485,18 @@ Can we ensure that the required attributes are added automatically on our behalf
460
485
return app.resolve(event, context)
461
486
```
462
487
463
-
We add powertools logger (line 8) and all the configuration is done.
464
-
We also use `logger.inject_lambda_context` decorator to inject Lambda context into every log. We instruct logger to log correlation id taken from API Gateway and event automatically. Because powertools library adds a correlation identifier to each log, we can easily correlate all the logs generated for a specific request.
488
+
Let's break this down:
465
489
466
-
In result, we should see logs with following attributes.
467
-
=== "Example Application Structured Log"
468
-
```json
490
+
***L8**: We add Lambda Powertools Logger; the boilerplate is now done for you. By default, we set `INFO` as the logging level if `LOG_LEVEL` env var isn't set
491
+
***L24**: We use `logger.inject_lambda_context` decorator to inject key information from Lambda context into every log.
492
+
***L24**: We also instruct Logger to use the incoming API Gateway Request ID as a [correlation id](./core/logger.md##set_correlation_id-method) automatically.
493
+
***L24**: Since we're in dev, we also use `log_event=True` to automatically log each incoming request for debugging. This can be also set via [environment variables](./index.md#environment-variables){target="_blank"}.
494
+
495
+
We can now search our logs by the request ID to find a specific operation. Additionally, we can also search our logs for function name, Lambda request ID, Lambda function ARN, find out whether an operation was a cold start, etc.
496
+
497
+
This is how the logs would look like now:
498
+
499
+
```json title="Our logs are now structured consistently"
469
500
{
470
501
"level":"INFO",
471
502
"location":"hello:17",
@@ -481,7 +512,11 @@ In result, we should see logs with following attributes.
By having structured logs like this, we can easily search and analyse them in [CloudWatch Logs Insight](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html).
515
+
516
+
From here, we could [set specific keys](./core/logger.md#append_keys-method){target="_blank"} to add additional contextual information about a given operation, [log exceptions](./core/logger.md#logging-exceptions){target="_blank"} to easily enumerate them later, [sample debug logs](./core/logger.md#sampling-debug-logs){target="_blank"}, etc.
517
+
518
+
By having structured logs like this, we can easily search and analyse them in [CloudWatch Logs Insight](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AnalyzingLogData.html){target="_blank"}.
0 commit comments