Releases: aws-powertools/powertools-lambda-python
v2.6.0
Summary
In this release, we added new specialised routers for all supported event handlers. This way you'll get type hints from your IDE as you access the current_event
property.
We also improved the exception logging in the idempotency utility with additional context taken from the raised downstream exception.
⭐ Finally, we thank our two new contributors @aidansteele and @pawosty for helping us iron out some important bugs! ⭐
Changes
🌟New features and non-breaking changes
- (feat): introduce specialized routers for typing (#1824) by @rubenfonseca
📜 Documentation updates
- docs(logger): fix incorrect field names in example structured logs (#1830) by @aidansteele
- feat(event_handler): introduce specialized routers for typing (#1824) by @rubenfonseca
- docs(logger): Add warning of uncaught exceptions (#1826) by @leandrodamascena
🐛 Bug and hot fixes
- fix(idempotency): Log nested exception message (#1813) by @mploski
- fix(api_gateway): fixed custom metrics issue when using debug mode (#1827) by @pawosty
🔧 Maintenance
- chore(deps-dev): bump coverage from 7.0.4 to 7.0.5 (#1829) by @dependabot
- chore(deps-dev): bump mkdocs-material from 9.0.2 to 9.0.3 (#1823) by @dependabot
- chore(deps-dev): bump coverage from 7.0.3 to 7.0.4 (#1822) by @dependabot
- chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 2.0.3 to 2.0.4 (#1821) by @dependabot
- chore(deps-dev): bump ijson from 3.1.4 to 3.2.0.post0 (#1815) by @dependabot
- chore(deps): bump peaceiris/actions-gh-pages from 3.9.0 to 3.9.1 (#1814) by @dependabot
- chore(deps): bump pydantic from 1.10.2 to 1.10.4 (#1817) by @dependabot
- chore(deps-dev): bump mypy-boto3-ssm from 1.26.11.post1 to 1.26.43 (#1819) by @dependabot
- chore(deps-dev): bump mypy-boto3-logs from 1.26.27 to 1.26.43 (#1820) by @dependabot
- chore(deps-dev): bump filelock from 3.8.2 to 3.9.0 (#1816) by @dependabot
- chore(deps-dev): bump mypy-boto3-cloudformation from 1.26.11.post1 to 1.26.35.post1 (#1818) by @dependabot
- chore(deps-dev): bump mkdocs-material from 8.5.11 to 9.0.2 (#1808) by @dependabot
- chore(deps-dev): bump coverage from 6.5.0 to 7.0.3 (#1806) by @dependabot
- chore(deps-dev): bump flake8-builtins from 2.0.1 to 2.1.0 (#1799) by @dependabot
- chore(deps): bump gitpython from 3.1.29 to 3.1.30 (#1812) by @dependabot
- chore(deps-dev): bump mypy-boto3-secretsmanager from 1.26.12 to 1.26.40 (#1811) by @dependabot
- chore(deps-dev): bump isort from 5.11.3 to 5.11.4 (#1809) by @dependabot
- chore(deps-dev): bump aws-cdk-lib from 2.55.1 to 2.59.0 (#1810) by @dependabot
- chore(deps-dev): bump importlib-metadata from 5.1.0 to 6.0.0 (#1804) by @dependabot
- chore(deps): bump release-drafter/release-drafter from 5.21.1 to 5.22.0 (#1802) by @dependabot
- chore(deps-dev): bump black from 22.10.0 to 22.12.0 (#1770) by @dependabot
- chore(deps-dev): bump flake8-black from 0.3.5 to 0.3.6 (#1792) by @dependabot
- chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 2.0.1 to 2.0.3 (#1801) by @dependabot
- chore(deps-dev): bump types-requests from 2.28.11.5 to 2.28.11.7 (#1795) by @dependabot
This release was made possible by the following contributors:
@aidansteele, @dependabot, @dependabot[bot], @leandrodamascena, @mploski, @pawosty, @rubenfonseca and Release bot
v2.5.0
Summary
This release improves logging incoming events that might be wrapped in common containers such as Event Source Data Classes, Pydantic/Parser BaseModels, and Dataclasses.
Also we addressed an issue when a header is set explicit to None.
Big thanks to @jasmarc for the bug report!
Example:
import json
from aws_lambda_powertools.event_handler import (
APIGatewayRestResolver,
Response,
)
app = APIGatewayRestResolver()
@app.get("/none")
def hello():
headers = {"This-Header-Will-Be-Omitted": None}
response = {"hello": "world"}
return Response(body=json.dumps(response), headers=headers, status_code=200)
def lambda_handler(event, context):
return app.resolve(event, context)
Changes
🌟New features and non-breaking changes
- feat(logger): unwrap event from common models if asked to log (#1778) by @heitorlessa
📜 Documentation updates
- docs(validation): fix broken link; enrich built-in jmespath links (#1777) by @heitorlessa
- docs(idempotency): fix, improve, and increase visibility for batch integration (#1776) by @heitorlessa
🐛 Bug and hot fixes
- fix(event_handlers): omit explicit None HTTP header values (#1793) by @leandrodamascena
🔧 Maintenance
- chore(deps-dev): bump isort from 5.11.2 to 5.11.3 (#1788) by @dependabot
- chore(deps-dev): bump aws-cdk-lib from 2.54.0 to 2.55.1 (#1787) by @dependabot
- chore(deps-dev): bump mypy-boto3-cloudwatch from 1.26.17 to 1.26.30 (#1785) by @dependabot
- chore(deps-dev): bump isort from 5.10.1 to 5.11.2 (#1782) by @dependabot
- chore(deps-dev): bump pytest-asyncio from 0.20.2 to 0.20.3 (#1767) by @dependabot
- chore(deps): bump certifi from 2022.9.24 to 2022.12.7 (#1768) by @dependabot
- chore(deps-dev): bump mypy-boto3-dynamodb from 1.26.13.post16 to 1.26.24 (#1765) by @dependabot
- chore(deps-dev): bump mypy-boto3-logs from 1.26.17 to 1.26.27 (#1775) by @dependabot
- chore(deps-dev): bump aws-cdk-lib from 2.53.0 to 2.54.0 (#1764) by @dependabot
- chore(deps-dev): bump flake8-bugbear from 22.10.27 to 22.12.6 (#1760) by @dependabot
- chore(deps-dev): bump filelock from 3.8.0 to 3.8.2 (#1759) by @dependabot
- chore(deps-dev): bump pytest-xdist from 3.0.2 to 3.1.0 (#1758) by @dependabot
- chore(deps-dev): bump mkdocs-material from 8.5.10 to 8.5.11 (#1756) by @dependabot
- chore(deps-dev): bump importlib-metadata from 4.13.0 to 5.1.0 (#1750) by @dependabot
- chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 1.4.0 to 2.0.1 (#1752) by @dependabot
- chore(deps-dev): bump flake8-black from 0.3.3 to 0.3.5 (#1738) by @dependabot
- chore(deps-dev): bump mypy-boto3-cloudwatch from 1.26.0.post1 to 1.26.17 (#1753) by @dependabot
- chore(deps): bump zgosalvez/github-actions-ensure-sha-pinned-actions from 1.3.0 to 1.4.0 (#1749) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, @leandrodamascena and Release bot
v2.4.0
Summary
This release introduces a brand new streaming utility to handle datasets larger than the available memory.
This addresses scenarios where you want to process Amazon S3 objects as seekable data streams, with minimal memory consumption.
Built-in data transformations
We've added support for popular data transformations to decompress and deserialize data (gzip, CSV and ZIP). This way you can transform the data while streaming, and only use the minimum amount of memory necessary.
Bring your own data transformation
You can also create your own data transformations and add them to the pipeline. For example, here's how to use the ijson
library to parse JSON as a data stream:
We plan to support more data transformations in the future too!
🌟 Would you like to see a specific data transformation supported in Powertools? Drop us a line in the python channel of our Discord.
Changes
🌟New features and non-breaking changes
- feat(streaming): add new s3 streaming utility (#1719) by @rubenfonseca
📜 Documentation updates
- docs(idempotency): fix register_lambda_context order (#1747) by @heitorlessa
- feat(streaming): add new s3 streaming utility (#1719) by @rubenfonseca
🔧 Maintenance
- feat(streaming): add new s3 streaming utility (#1719) by @rubenfonseca
- chore(deps-dev): bump mypy-boto3-cloudformation from 1.26.0.post1 to 1.26.11.post1 (#1746) by @dependabot
- chore(deps-dev): bump mypy-boto3-lambda from 1.26.0.post1 to 1.26.12 (#1742) by @dependabot
- chore(deps-dev): bump aws-cdk-lib from 2.50.0 to 2.51.1 (#1741) by @dependabot
- chore(deps-dev): bump mypy-boto3-dynamodb from 1.26.0.post1 to 1.26.13.post16 (#1743) by @dependabot
- chore(deps-dev): bump mypy-boto3-secretsmanager from 1.26.0.post1 to 1.26.12 (#1744) by @dependabot
- chore(deps-dev): bump mypy-boto3-ssm from 1.26.4 to 1.26.11.post1 (#1740) by @dependabot
- chore(deps-dev): bump types-requests from 2.28.11.4 to 2.28.11.5 (#1729) by @dependabot
- chore(deps): bump aws-xray-sdk from 2.10.0 to 2.11.0 (#1730) by @dependabot
- chore(deps-dev): bump mkdocs-material from 8.5.9 to 8.5.10 (#1731) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, @rubenfonseca and Release bot
v2.3.1
Summary
This patch release address an issue in Event Handler REST API to support dynamic routes with an equal sign (=
).
Big thanks to @baraksalomon for the bug report!
Previously, a dynamic route containing =
would result in a not found response (HTTP 404).
Example
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayRestResolver()
# NOTE: `/token/bXl0b2tlbg==` should be matched and not return 404 now
@app.get("/token/<token>")
def get_token(token: str):
return {"received": f"{token}"}
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
Changes
🐛 Bug and hot fixes
- fix(apigateway): support dynamic routes with equal sign (RFC3986) (#1737) by @heitorlessa
🔧 Maintenance
- chore(deps-dev): bump mypy-boto3-xray from 1.26.9 to 1.26.11.post1 (#1734) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa and Release bot
v2.3.0
Summary
This release features: (1) Extract CloudWatch Logs sent to Kinesis streams, (2) Handling multiple exceptions in Event Handler REST, and (3) Log uncaught exceptions in Logger.
Big thanks to new contributors: @ascopes (logger static typing), @bnsouza (expand testing docs in Event Handler), @kt-hr (bugfix multiple routes in Event Handler), @mangoes-git (bugfix for fetching SecretBinary)
Extracting CloudWatch Logs shipped to Kinesis Data Streams
This address a common use case of centralizing CloudWatch Logs from multiple regions or accounts using Kinesis Data Streams.
You can now easily extract CloudWatch Logs (decompress, decode, etc.) using either Event Source Data Classes or Parser. It also seamless integrates with Batch so you can benefit from partial failure handling among other benefits, when processing large batch of logs from Kinesis.
Event Source Data Classes
from aws_lambda_powertools.utilities.batch import (BatchProcessor, EventType,
batch_processor)
from aws_lambda_powertools.utilities.data_classes.kinesis_stream_event import (
KinesisStreamRecord, extract_cloudwatch_logs_from_record)
processor = BatchProcessor(event_type=EventType.KinesisDataStreams)
def record_handler(record: KinesisStreamRecord):
log = extract_cloudwatch_logs_from_record(record)
return log.message_type == "DATA_MESSAGE"
@batch_processor(record_handler=record_handler, processor=processor)
def lambda_handler(event, context):
return processor.response()
Parser
from aws_lambda_powertools.utilities.batch import (BatchProcessor, EventType,
batch_processor)
from aws_lambda_powertools.utilities.parser.models import (
KinesisDataStreamModel, KinesisDataStreamRecord)
from aws_lambda_powertools.utilities.parser.models.kinesis import \
extract_cloudwatch_logs_from_record
processor = BatchProcessor(event_type=EventType.KinesisDataStreams, model=KinesisDataStreamModel)
def record_handler(record: KinesisDataStreamRecord):
log = extract_cloudwatch_logs_from_record(record)
return log.messageType == "DATA_MESSAGE"
@batch_processor(record_handler=record_handler, processor=processor)
def lambda_handler(event, context):
return processor.response()
Handling multiple exceptions in Event Handler
You can now catch multiple exceptions when registering an exception handler.
This is useful when you have related exceptions you want to handle the same way.
import requests
from aws_lambda_powertools.event_handler import (
APIGatewayRestResolver,
Response,
content_types,
)
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayRestResolver()
@app.exception_handler([ValueError, requests.HTTPError])
def handle_invalid_limit_qs(ex: ValueError | requests.HTTPError): # receives exception raised
metadata = {"path": app.current_event.path, "query_strings": app.current_event.query_string_parameters}
logger.error(f"Malformed request: {ex}", extra=metadata)
return Response(
status_code=400,
content_type=content_types.TEXT_PLAIN,
body="Invalid request parameters.",
)
@app.get("/todos")
def get_todos():
max_results: int = int(app.current_event.get_query_string_value(name="limit", default_value=0))
todos: requests.Response = requests.get(f"https://jsonplaceholder.typicode.com/todos?limit={max_results}")
todos.raise_for_status()
return {"todos": todos.json()}
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
Logging uncaught exceptions
You can now automatically log uncaught exceptions using Logger via log_uncaught_exceptions=True
.
Logger will use Python's exception hook to log such exception with your pre-configured Logger instance for maximum context.
import requests
from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.typing import LambdaContext
ENDPOINT = "http://httpbin.org/status/500"
logger = Logger(log_uncaught_exceptions=True)
def handler(event: dict, context: LambdaContext) -> str:
ret = requests.get(ENDPOINT)
# HTTP 4xx/5xx status will lead to requests.HTTPError
# Logger will log this exception before this program exits non-successfully
ret.raise_for_status()
return "hello world"
This would generate the following output in CloudWatch Logs
{
"level": "ERROR",
"location": "log_uncaught_exception_hook:756",
"message": "500 Server Error: INTERNAL SERVER ERROR for url: http://httpbin.org/status/500",
"timestamp": "2022-11-16 13:51:29,198+0100",
"service": "payment",
"exception": "Traceback (most recent call last):\n File \"<input>\", line 52, in <module>\n handler({}, {})\n File \"<input>\", line 17, in handler\n ret.raise_for_status()\n File \"<input>/lib/python3.9/site-packages/requests/models.py\", line 1021, in raise_for_status\n raise HTTPError(http_error_msg, response=self)\nrequests.exceptions.HTTPError: 500 Server Error: INTERNAL SERVER ERROR for url: http://httpbin.org/status/500",
"exception_name": "HTTPError"
}
Changes
🌟New features and non-breaking changes
- feat(parser): export Pydantic.errors through escape hatch (#1728) by @heitorlessa
- feat(logger): log uncaught exceptions via system's exception hook (#1727) by @heitorlessa
- feat(parser): extract CloudWatch Logs in Kinesis streams (#1726) by @heitorlessa
- feat(event_sources): extract CloudWatch Logs in Kinesis streams (#1710) by @heitorlessa
- feat(apigateway): multiple exceptions in exception_handler (#1707) by @sprkem
📜 Documentation updates
- docs(idempotency): add missing Lambda Context; note on thread-safe (#1732) by @heitorlessa
- feat(logger): log uncaught exceptions via system's exception hook (#1727) by @heitorlessa
- feat(event_sources): extract CloudWatch Logs in Kinesis streams (#1710) by @heitorlessa
- feat(apigateway): multiple exceptions in exception_handler (#1707) by @sprkem
- docs(apigateway): add all resolvers in testing your code section for accuracy (#1688) by @bnsouza
- docs(homepage): update default value for
POWERTOOLS_DEV
(#1695) by @dreamorosi
🐛 Bug and hot fixes
- fix(parameters): get_secret correctly return SecretBinary value (#1717) by @mangoes-git
- fix(apigateway): support nested router decorators (#1709) by @kt-hr
🔧 Maintenance
- chore(deps-dev): bump flake8-builtins from 2.0.0 to 2.0.1 (#1715) by @dependabot
- chore(deps-dev): bump pytest-asyncio from 0.20.1 to 0.20.2 (#1723) by @dependabot
- chore(deps-dev): bump mypy-boto3-appconfig from 1.25.0 to 1.26.0.post1 (#1722) by @dependabot
- chore(deps-dev): bump mypy-boto3-ssm from 1.26.0.post1 to 1.26.4 (#1721) by @dependabot
- chore(deps-dev): bump mypy-boto3-xray from 1.26.0.post1 to 1.26.9 (#1720) by @dependabot
- chore(deps-dev): bump mypy-boto3-lambda from 1.25.0 to 1.26.0.post1 (#1705) by @dependabot
- chore(deps-dev): bump mypy-boto3-s3 from 1.25.0 to 1.26.0.post1 (#1716) by @dependabot
- chore(deps-dev): bump mypy-boto3-appconfigdata from 1.25.0 to 1.26.0.post1 (#1704) by @dependabot
- chore(deps-dev): bump mypy-boto3-xray from 1.25.0 to 1.26.0.post1 (#1703) by @dependabot
- chore(deps-dev): bump mypy-boto3-cloudwatch from 1.25.0 to 1.26.0.post1 (#1714) by @dependabot
- chore(logger): overload inject_lambda_context with generics (#1583) by @ascopes
- chore(deps-dev): bump types-requests from 2.28.11.3 to 2.28.11.4 (#1701) by @dependabot
- chore(deps-dev): bump mypy-boto3-logs from 1.25.0 to 1.26.3 (#1702) by @dependabot
- chore(deps-dev): bump pytest-xdist from 2.5.0 to 3.0.2 (#1655) by @dependabot
- chore(deps-dev): bump mkdocs-material from 8.5.7 to 8.5.9 (#1697) by @dependabot
- chore(deps-dev): bump flake8-comprehensions from 3.10.0 to 3.10.1 (#1699) by @dependabot
- chore(deps-dev): bump types-requests from 2.28.11.2 to 2.28.11.3 (#1698) by @dependabot
- chore(deps-dev): bump pytest-benchmark from 3.4.1 to 4.0.0 (#1659) by @dependabot
- chore(deps-dev): bump mypy-boto3-secretsmanager from 1.25.0 to 1.26.0.post1 (#1691) by @dependabot
- chore(deps): bump dependabot/fetch-metadata from 1.3.4 to 1.3.5 (#1689) by @dependabot
- chore(deps-dev): bump flake8-bugbear from 22.10.25 to 22.10.27 (#1665) by @dependabot
- chore(deps-dev): bump mypy-boto3-ssm from 1.25.0 to 1.26.0.post1 (#1690) by @dependabot
This release was made possible by the following contributors:
@ascopes, @bnsouza, @dependabot, @dependabot[bot], @dreamorosi, @heitorlessa, @kt-hr, @mangoes-git, @sprkem and Release bot
v2.2.0
Summary
This release features: (1) a new get_parameters_by_name
function to fetch multiple Parameter Store parameters from distinct paths, and (2) a new EphemeralMetrics
class for multi-tenancy and ISV use cases that require multiple metrics namespace.
Fetching distinct parameters by name
You can now fetch distinct parameters by their full name with get_parameters_by_name
.
Previously, you could only fetch multiple parameters by path via get_parameters
. We also heard from customers they'd like more flexibility when fetching parameters.
This new high level function has the following in mind:
- Per parameter config: cache parameters differently while fetching them in batch
- Decrypt all, none, or a few: transparent batch operations for when decryption is required without being worried on aggressive throttling
- Fail-fast vs graceful error handling: choose whether to fail at the error, or aggregate errors so you can handle them gracefully
Quick flow on how get_parameters_by_name
decides which System Manager Parameter Store to use based on per parameter config (or global):
┌────────────────────────┐
┌───▶ Decrypt entire batch │─────┐
│ └────────────────────────┘ │ ┌────────────────────┐
│ ├─────▶ GetParameters API │
┌──────────────────┐ │ ┌────────────────────────┐ │ └────────────────────┘
│ Split batch │───┼──▶│ No decryption required │─────┘
└──────────────────┘ │ └────────────────────────┘
│ ┌────────────────────┐
│ ┌────────────────────────┐ │ GetParameter API │
└──▶│Decrypt some but not all│──────────▶├────────────────────┤
└────────────────────────┘ │ GetParameters API │
└────────────────────┘
EphemeralMetrics
You can use EphemeralMetrics
class when looking to isolate multiple instances of metrics with distinct namespaces and/or dimensions.
from aws_lambda_powertools.metrics import EphemeralMetrics, MetricUnit
from aws_lambda_powertools.utilities.typing import LambdaContext
metrics = EphemeralMetrics()
@metrics.log_metrics
def lambda_handler(event: dict, context: LambdaContext):
metrics.add_metric(name="SuccessfulBooking", unit=MetricUnit.Count, value=1)
By default, Metrics
share metrics data across instances. This prevents common data deduplication due to CloudWatch EMF constraints on metric dimensions. However, this limits use cases where you want to create metrics for different applications within the same Lambda function, namely multi-tenancy - whether you use distinct metrics dimensions per metric or multiple metric namespaces.
There are subtle differences between the two:
Feature | Metrics | EphemeralMetrics |
---|---|---|
Share data across instances (metrics, dimensions, metadata, etc.) | Yes | - |
Default dimensions that persists across Lambda invocations (metric flush) | Yes | - |
Changes
🌟New features and non-breaking changes
- feat(parameters): add get_parameters_by_name for SSM params in distinct paths (#1678) by @heitorlessa
- feat(metrics): add EphemeralMetrics as a non-singleton option (#1676) by @heitorlessa
📜 Documentation updates
- feat(parameters): add get_parameters_by_name for SSM params in distinct paths (#1678) by @heitorlessa
- feat(metrics): add EphemeralMetrics as a non-singleton option (#1676) by @heitorlessa
🔧 Maintenance
- chore(deps-dev): bump aws-cdk-lib from 2.49.0 to 2.50.0 (#1683) by @dependabot
- feat(parameters): add get_parameters_by_name for SSM params in distinct paths (#1678) by @heitorlessa
- chore(deps-dev): bump mypy-boto3-dynamodb from 1.25.0 to 1.26.0.post1 (#1682) by @dependabot
- chore(deps-dev): bump mypy-boto3-cloudformation from 1.25.0 to 1.26.0.post1 (#1679) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, Release bot
v2.1.0
Summary
This release features: (1) Logger UX enhancements, (2) New docs community section (We Made This), and (3) New issue form to accept customer references in our docs.
Big thanks to new contributors 👏: @nayaverdier (logger mypy fix), @pierskarsenbarg (Pulumi docs), and @dmwesterhoff (idempotency_function
bug finding)
Logger
Simplifying log statements for additional metadata
You can now pass any arbitrary and ephemeral metadata as keyword-arguments when logging: logging.info("Incoming payment", customer_id="...")
Previously, you had to use the extras
parameter. This ergonomics improvement makes it easier to surface keys at the root of your structured log on a per log statement basis.
This has been a long overdue and we're so so excited to have this finally out!
Use RFC3339 date format with a single flag
You can now set use_rfc3339=True
to instruct Logger to change the timestamp
key to a value compliant with both RFC3339 and ISO8601: 2022-10-27T16:27:43.738+02:00
Big thanks to @kishaningithub @JJSphar for the discussion and UX here!
New community docs section
You can now submit blog posts, workshops, videos, and sample projects featuring Lambda Powertools.
Please check out the early submitted content from our awesome community!
PS: We accept content in any language!
Become a customer reference
You can now give us permission to list your organization name in the Lambda Powertools documentation..
This helps us tremendously and new customers looking to learn who's using it. This permission is explicit for our documentation.
Changes
🌟New features and non-breaking changes
- feat(logger): add use_rfc3339 and auto-complete formatter opts in Logger (#1662) by @heitorlessa
- feat(logger): accept arbitrary keyword=value for ephemeral metadata (#1658) by @heitorlessa
- feat(layers): add layer balancer script (#1643) by @rubenfonseca
📜 Documentation updates
- feat(logger): add use_rfc3339 and auto-complete formatter opts in Logger (#1662) by @heitorlessa
- feat(logger): accept arbitrary keyword=value for ephemeral metadata (#1658) by @heitorlessa
- docs(homepage): add Pulumi code example (#1652) by @pierskarsenbarg
- docs(community): fix social handlers for Ran (#1654) by @ran-isenberg
- docs(we-made-this): new community content section (#1650) by @leandrodamascena
🐛 Bug and hot fixes
- fix(logger): fix unknown attributes being ignored by mypy (#1670) by @nayaverdier
- fix(idempotency): idempotent_function should support standalone falsy values (#1669) by @heitorlessa
- fix(deps): update build system to poetry-core (#1651) by @rubenfonseca
🔧 Maintenance
- chore(deps-dev): bump aws-cdk-lib from 2.48.0 to 2.49.0 (#1671) by @dependabot
- chore(deps-dev): bump aws-cdk-lib from 2.47.0 to 2.48.0 (#1664) by @dependabot
- fix(deps): update build system to poetry-core (#1651) by @rubenfonseca
- chore(deps-dev): bump flake8-variables-names from 0.0.4 to 0.0.5 (#1628) by @dependabot
- chore(deps): bump docker/setup-qemu-action from 2.0.0 to 2.1.0 (#1627) by @dependabot
- chore(deps-dev): bump pytest-asyncio from 0.16.0 to 0.20.1 (#1635) by @dependabot
- chore(deps): bump peaceiris/actions-gh-pages from 3.8.0 to 3.9.0 (#1649) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @heitorlessa, @leandrodamascena, @nayaverdier, @pierskarsenbarg, @ran-isenberg, @rubenfonseca and Release bot
v2.0.0
Summary
We are extremely happy to announce the smallest release version ever - v2.0.0 🎉🎉!
The number one customer request was reducing package size. Some customers use a different tracing provider. Others used Parser (Pydantic) for data modelling and deep data validation instead of JSON Schema Validation. A few brought large machine learning models and every bit of space they can save matters.
The number two request was ARM64 support. Customers want to benefit from performance and cost savings for their workloads. However, they don’t want to invest additional time testing and compiling dependencies they use daily for ARM64.
We’ve spent the past 2 months optimizing as much as we could. We kept breaking changes to a minimum to make your transition to v2 as smooth as possible.
For backwards incompatible changes, we’ve spent considerable effort making sure they are visible, why we implemented them, and and what to do if they affect you.
Our sincerest appreciation for the community help and patience while we’ve worked on this release - Thank you ❤️!
Table of contents
- What's New in V2
- Changes
- 🌟New features and non-breaking changes
- 📜 Documentation updates
- 🐛 Bug and hot fixes
- 🔧 Maintenance
- This release was made possible by the following contributors:
What's New in V2
Python compatibility
We dropped support for Python 3.6. We highly recommend moving to the latest Python available in AWS Lambda (3.9).
Package size reduction by 97.6%
We now rely on AWS SDK available in the Lambda runtime, and all other dependencies are marked as optional.
There are subtle but important differences in the installation experience - PyPi (all optional) and Lambda Layer (all included).
PyPi
The compressed package size is now approximately 240K (previously 10M).
We updated each documentation to emphasize when an additional dependency is required (Tracer, Validation and Parser). If you prefer to install all of them, use pip install aws-lambda-powertools[all]
.
Note. If you need to use newer AWS services or features not available in the Lambda runtime provided SDK, you'll need to bundle boto3
as a dependency.
Lambda Layer
The compressed package size is now approximately 2M (previously 17M).
Lambda Layer includes all dependencies. They're also optimized for package size and speed (Pydantic now compiled with Cython for ~30-50% speed gain).
ARM Support
We now offer full support to ARM via Lambda Layer and SAR installation. All C-extension dependencies are compiled, optimized and tested against Lambda environment.
PyPi and Lambda Layer available upon release notes event
You can now safely subscribe to GitHub Release event to know when PyPi and Lambda Layer ARNs have the latest version.
Previously, PyPi, Lambda Layers, and docs were updated after a release notes went live to GitHub (~15m completion). Due to Lambda Layer compilation (x86/ARM64), this process takes on average 30m longer.
As such, we make releases prior to sharing release notes, guaranteeing for customers watching for GitHub Releases that Layer ARNs available in the documentation match PyPi releases (no more delays).
Event Handler REST new features
Multi-value header and cookies support
When returning custom responses, you now can add a list of values for a header, including cookies.
Event Handler will seamless adapt to the expected format based on resolver used, whether that is REST API, HTTP API, ALB, or Function URL.
from http import HTTPStatus
from uuid import uuid4
import requests
from aws_lambda_powertools.event_handler import (
APIGatewayRestResolver,
Response,
content_types,
)
from aws_lambda_powertools.shared.cookies import Cookie
from aws_lambda_powertools.utilities.typing import LambdaContext
app = APIGatewayRestResolver()
@app.get("/todos")
def get_todos():
todos: requests.Response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos.raise_for_status()
dummy_transactions = [f"{uuid4()}", f"{uuid4()}", f"{uuid4()}"]
multi_value_header = {"X-Transaction-Id": dummy_transactions}
return Response(
status_code=HTTPStatus.OK.value, # 200
content_type=content_types.APPLICATION_JSON,
body=todos.json()[:10],
headers=multi_value_header, # NEW
cookies=[Cookie(name="session_id", value="12345")], # NEW
)
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
NOTE. For ALB, you have to explicitly enable multi-value headers in the target configuration.
Trailing slash route support
APIGatewayRestResolver
now seamless support route resolution with trailing slashes: /todos/
.
Previously, requests with a trailing slash would return HTTP 404 due to route mismatch.
Note. This was not necessary for HTTP API and ALB.
Fully qualified names for Tracer subsegments
tracer.capture_method
or tracer.capture_lambda_handler
decorators now use the decorated function or method fully qualified name as the subsegment name.
This enables accurate traces for ABC or Protocol classes, where their method name will be the same but for distinct classes.
Backwards incompatible change in v2
Here’s a quick view of deprecated features removed and backwards incompatible changes.
Area | Change | Code change required | IAM Permissions change required |
---|---|---|---|
Batch | Removed legacy SQS batch processor in favour of BatchProcessor . |
Yes | - |
Environment variables | Removed legacy POWERTOOLS_EVENT_HANDLER_DEBUG in favour of [POWERTOOLS_DEV ](https://awslabs.github.io/aws-lambda-powertools-python... |
v1.31.1
Summary
This patch release is focused on Parser with SNS FIFO.
When using SNS FIFO topics, SNS removes three fields, namely: SigningCertUrl
, Signature
, and SignatureVersion
. As such, we're marking these fields as Optional
to prevent ValidationError
. Thanks to @plondino for flagging this.
NOTE: In the future, we'll be looking at creating separate FIFO Models.
Hacktoberfest
Big thanks to @digitalisx and @senmm who helped addresses typos in the documentation. Thank you for helping make the documentation better for everyone 💞!
Changes
NOTE: This release will be available in PyPi in roughly 5m, and Lambda Layers across all AWS commercial regions in ~15m.
📜 Documentation updates
- docs(governance): allow community to suggest feature content (#1593) by @heitorlessa
- docs(idempotency): "persisntence" typo (#1596) by @senmm
- docs(idempotency) - Update invalid link target. (#1588) by @eldritchideen
- docs(governance): new form to allow customers self-nominate as public reference (#1589) by @heitorlessa
- docs(logger): fix typo. (#1587) by @digitalisx
🐛 Bug and hot fixes
- fix(parser): loose validation on SNS fields to support FIFO (#1606) by @heitorlessa
🔧 Maintenance
- docs(governance): allow community to suggest feature content (#1593) by @heitorlessa
- chore(deps-dev): bump mypy-boto3-ssm from 1.24.81 to 1.24.90 (#1594) by @dependabot
- chore(deps-dev): bump flake8-builtins from 1.5.3 to 2.0.0 (#1582) by @dependabot
This release was made possible by the following contributors:
@dependabot, @dependabot[bot], @digitalisx, @eldritchideen, @heitorlessa, @rubenfonseca, @senmm and Release bot
v1.31.0
Summary
This release fixes a bug in Metrics where subsequent instances didn't share a dimensions set - Huge thanks to @cfchou for flagging it and for being super proactive in creating a test ahead of time.
This also adds support for Amazon Kinesis Firehose in Parser - big thanks to @ran-isenberg!
Changes
🌟New features and non-breaking changes
- feat(parser): add KinesisFirehoseModel (#1556) by @ran-isenberg
🐛 Bug and hot fixes
- fix(metrics): ensure dimension_set is reused across instances (pointer) (#1581) by @heitorlessa
🔧 Maintenance
- chore(deps-dev): bump types-requests from 2.28.11.1 to 2.28.11.2 (#1576) by @dependabot
- chore(deps-dev): bump typing-extensions from 4.3.0 to 4.4.0 (#1575) by @dependabot
This release was made possible by the following contributors:
@am29d, @dependabot, @dependabot[bot], @heitorlessa, @ran-isenberg and Release bot