Skip to content

Commit 13eb005

Browse files
authored
Adopt logging best practices (#23)
* fix: set NullHandler for package logger * improv: remove root logger logic, lib * fix: update exception type * improv: propagate log level if set, null otherwise * fix: explicit wins over env var * chore: fix test naming * fix: exception logging * improv: shorten log location * feat: add Logger class wrapper * improv: add deprecation warning * BREAKING CHANGE: logger_setup, inject_lambda_ctx * improv: update tests * improv: cover duplicated keys edge case * improv: cover debug package logging * improv: more coverage, linting * improv: complete coverage, fix dead code * docs: update readme to reflect changes * fix: address jacob's code review feedback * chore: linting * fix: metric spillover at 100, not 101 * fix: trace auto-disable, doc edge cases * chore: linting * chore: 0.8.0 version bump Co-authored-by: heitorlessa <[email protected]>
1 parent 68b108d commit 13eb005

20 files changed

+641
-335
lines changed

Diff for: README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Lambda Powertools
22

3-
![PackageStatus](https://img.shields.io/static/v1?label=status&message=beta&color=blueviolet?style=flat-square) ![PythonSupport](https://img.shields.io/static/v1?label=python&message=3.6%20|%203.7|%203.8&color=blue?style=flat-square&logo=python)
3+
![Python Build](https://github.com/awslabs/aws-lambda-powertools/workflows/Powertools%20Python/badge.svg?branch=master)
44

55
A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray, structured logging and creating custom metrics asynchronously easier.
66

Diff for: python/HISTORY.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# HISTORY
22

3+
## April 24th
4+
5+
* Introduces `Logger` for stuctured logging as a replacement for `logger_setup`
6+
* Introduces `Logger.inject_lambda_context` decorator as a replacement for `logger_inject_lambda_context`
7+
* Raise `DeprecationWarning` exception for both `logger_setup`, `logger_inject_lambda_context`
8+
39
## April 20th, 2020
410

511
**0.7.0**

Diff for: python/README.md

+58-12
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray,
1313
> It currently uses AWS X-Ray
1414
1515
* Decorators that capture cold start as annotation, and response and exceptions as metadata
16-
* Run functions locally without code change to disable tracing
16+
* Run functions locally with SAM CLI without code change to disable tracing
1717
* Explicitly disable tracing via env var `POWERTOOLS_TRACE_DISABLED="true"`
1818

1919
**Logging**
@@ -24,6 +24,7 @@ A suite of utilities for AWS Lambda Functions that makes tracing with AWS X-Ray,
2424
* Logs canonical custom metric line to logs that can be consumed asynchronously
2525
* Log sampling enables DEBUG log level for a percentage of requests (disabled by default)
2626
- Enable via `POWERTOOLS_LOGGER_SAMPLE_RATE=0.1`, ranges from 0 to 1, where 0.1 is 10% and 1 is 100%
27+
* Append additional keys to structured log at any point in time so they're available across log statements
2728

2829
**Metrics**
2930

@@ -113,6 +114,8 @@ tracer = Tracer(auto_patch=False) # new instance using existing configuration wi
113114

114115
### Logging
115116

117+
> **NOTE** `logger_setup` and `logger_inject_lambda_context` are deprecated and will be completely removed once it's GA.
118+
116119
**Example SAM template using supported environment variables**
117120

118121
```yaml
@@ -128,13 +131,12 @@ Globals:
128131
**Pseudo Python Lambda code**
129132
130133
```python
131-
from aws_lambda_powertools.logging import logger_setup, logger_inject_lambda_context
134+
from aws_lambda_powertools.logging import Logger
132135

133-
logger = logger_setup()
134-
# logger_setup(service="payment") # also accept explicit service name
135-
# logger_setup(level="INFO") # also accept explicit log level
136+
logger = Logger()
137+
# Logger(service="payment", level="INFO") # also accepts explicit service name, log level
136138

137-
@logger_inject_lambda_context
139+
@logger.inject_lambda_context
138140
def handler(event, context)
139141
logger.info("Collecting payment")
140142
...
@@ -159,6 +161,7 @@ def handler(event, context)
159161
"lambda_function_arn":"arn:aws:lambda:eu-west-1:12345678910:function:test",
160162
"lambda_request_id":"52fdfc07-2182-154f-163f-5f0f9a621d72",
161163
"cold_start": "true",
164+
"sampling_rate": 0.1,
162165
"message": "Collecting payment"
163166
}
164167

@@ -172,13 +175,48 @@ def handler(event, context)
172175
"lambda_function_arn":"arn:aws:lambda:eu-west-1:12345678910:function:test",
173176
"lambda_request_id":"52fdfc07-2182-154f-163f-5f0f9a621d72",
174177
"cold_start": "true",
178+
"sampling_rate": 0.1,
175179
"message":{
176180
"operation":"collect_payment",
177181
"charge_id": "ch_AZFlk2345C0"
178182
}
179183
}
180184
```
181185

186+
**Append additional keys to structured log**
187+
188+
```python
189+
from aws_lambda_powertools.logging import Logger
190+
191+
logger = Logger()
192+
193+
@logger.inject_lambda_context
194+
def handler(event, context)
195+
if "order_id" in event:
196+
logger.structure_logs(append=True, order_id=event["order_id"])
197+
logger.info("Collecting payment")
198+
...
199+
```
200+
201+
**Exerpt output in CloudWatch Logs**
202+
203+
```json
204+
{
205+
"timestamp":"2019-08-22 18:17:33,774",
206+
"level":"INFO",
207+
"location":"collect.handler:1",
208+
"service":"payment",
209+
"lambda_function_name":"test",
210+
"lambda_function_memory_size":"128",
211+
"lambda_function_arn":"arn:aws:lambda:eu-west-1:12345678910:function:test",
212+
"lambda_request_id":"52fdfc07-2182-154f-163f-5f0f9a621d72",
213+
"cold_start": "true",
214+
"sampling_rate": 0.1,
215+
"order_id": "order_id_value",
216+
"message": "Collecting payment"
217+
}
218+
```
219+
182220
### Custom Metrics async
183221

184222
> **NOTE** `log_metric` will be removed once it's GA.
@@ -229,6 +267,7 @@ with single_metric(name="ColdStart", unit=MetricUnit.Count, value=1) as metric:
229267
metric.add_dimension(name="function_context", value="$LATEST")
230268
```
231269

270+
> **NOTE**: If you want to instantiate Metrics() in multiple places in your code, make sure to use `POWERTOOLS_METRICS_NAMESPACE` env var as we don't keep a copy of that across instances.
232271
233272
### Utilities
234273

@@ -320,12 +359,19 @@ def lambda_handler(event, context):
320359
return True
321360
```
322361

323-
## Beta
324362

325-
> **[Progress towards GA](https://github.com/awslabs/aws-lambda-powertools/projects/1)**
363+
### Debug mode
364+
365+
By default, all debug log statements from AWS Lambda Powertools package are suppressed. If you'd like to enable them, use `set_package_logger` utility:
366+
367+
```python
368+
import aws_lambda_powertools
369+
aws_lambda_powertools.logging.logger.set_package_logger()
370+
...
371+
```
372+
373+
## Beta
326374

327-
This library may change its API/methods or environment variables as it receives feedback from customers. Currently looking for ideas in the following areas before making it stable:
375+
This library may change its API/methods or environment variables as it receives feedback from customers
328376

329-
* **Should Tracer patch all possible imported libraries by default or only AWS SDKs?**
330-
- Patching all libraries may have a small performance penalty (~50ms) at cold start
331-
- Alternatively, we could patch only AWS SDK if available and to provide a param to patch multiple `Tracer(modules=("boto3", "requests"))`
377+
**[Progress towards GA](https://github.com/awslabs/aws-lambda-powertools/projects/1)**

Diff for: python/aws_lambda_powertools/__init__.py

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# -*- coding: utf-8 -*-
22

33
"""Top-level package for Lambda Python Powertools."""
4+
import logging
45

56
__author__ = """Amazon Web Services"""
7+
8+
logger = logging.getLogger("aws_lambda_powertools")
9+
logger.addHandler(logging.NullHandler())
10+
logger.propagate = False

Diff for: python/aws_lambda_powertools/logging/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Logging utility
22
"""
33
from ..helper.models import MetricUnit
4-
from .logger import log_metric, logger_inject_lambda_context, logger_setup
4+
from .logger import Logger, log_metric, logger_inject_lambda_context, logger_setup
55

6-
__all__ = ["logger_setup", "logger_inject_lambda_context", "log_metric", "MetricUnit"]
6+
__all__ = ["logger_setup", "logger_inject_lambda_context", "log_metric", "MetricUnit", "Logger"]

Diff for: python/aws_lambda_powertools/logging/aws_lambda_logging.py

-98
This file was deleted.

Diff for: python/aws_lambda_powertools/logging/exceptions.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class InvalidLoggerSamplingRateError(Exception):
2+
pass

0 commit comments

Comments
 (0)