Skip to content

Commit

Permalink
docs(event-handler): snippets split, improved, and lint (#1279)
Browse files Browse the repository at this point in the history
  • Loading branch information
heitorlessa committed Jul 13, 2022
1 parent 3927738 commit 2a51de0
Show file tree
Hide file tree
Showing 43 changed files with 1,164 additions and 1,018 deletions.
1,166 changes: 148 additions & 1,018 deletions docs/core/event_handler/api_gateway.md

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions docs/core/logger.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ Logger provides an opinionated logger with output structured as JSON.

## Getting started

???+ tip
All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}.

Logger requires two settings:

| Setting | Description | Environment variable | Constructor parameter |
Expand Down
3 changes: 3 additions & 0 deletions docs/core/metrics.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ If you're new to Amazon CloudWatch, there are two terminologies you must be awar

## Getting started

???+ tip
All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}.

Metric has two global settings that will be used across all metrics emitted:

| Setting | Description | Environment variable | Constructor parameter |
Expand Down
3 changes: 3 additions & 0 deletions docs/core/tracer.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Tracer is an opinionated thin wrapper for [AWS X-Ray Python SDK](https://github.

## Getting started

???+ tip
All examples shared in this documentation are available within the [project repository](https://github.com/awslabs/aws-lambda-powertools-python/tree/develop/examples){target="_blank"}.

### Permissions

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.
Expand Down
56 changes: 56 additions & 0 deletions examples/event_handler_rest/sam/template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Hello world event handler API Gateway

Globals:
Api:
TracingEnabled: true
Cors: # see CORS section
AllowOrigin: "'https://example.com'"
AllowHeaders: "'Content-Type,Authorization,X-Amz-Date'"
MaxAge: "'300'"
BinaryMediaTypes: # see Binary responses section
- "*~1*" # converts to */* for any binary type
Function:
Timeout: 5
Runtime: python3.8
Tracing: Active
Environment:
Variables:
LOG_LEVEL: INFO
POWERTOOLS_LOGGER_SAMPLE_RATE: 0.1
POWERTOOLS_LOGGER_LOG_EVENT: true
POWERTOOLS_SERVICE_NAME: example

Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Handler: app.lambda_handler
CodeUri: api_handler/
Description: API handler function
Events:
AnyApiEvent:
Type: Api
Properties:
# NOTE: this is a catch-all rule to simplify the documentation.
# explicit routes and methods are recommended for prod instead (see below)
Path: /{proxy+} # Send requests on any path to the lambda function
Method: ANY # Send requests using any http method to the lambda function


# GetAllTodos:
# Type: Api
# Properties:
# Path: /todos
# Method: GET
# GetTodoById:
# Type: Api
# Properties:
# Path: /todos/{todo_id}
# Method: GET
# CreateTodo:
# Type: Api
# Properties:
# Path: /todos
# Method: POST
40 changes: 40 additions & 0 deletions examples/event_handler_rest/src/accessing_request_details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from typing import Optional

import requests
from requests import Response

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver()


@app.get("/todos")
@tracer.capture_method
def get_todos():
todo_id: str = app.current_event.get_query_string_value(name="id", default_value="")
# alternatively
_: Optional[str] = app.current_event.query_string_parameters.get("id")

# Payload
_: Optional[str] = app.current_event.body # raw str | None

endpoint = "https://jsonplaceholder.typicode.com/todos"
if todo_id:
endpoint = f"{endpoint}/{todo_id}"

todos: Response = requests.get(endpoint)
todos.raise_for_status()

return {"todos": todos.json()}


# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import requests
from requests import Response

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver()


@app.get("/todos")
@tracer.capture_method
def get_todos():
endpoint = "https://jsonplaceholder.typicode.com/todos"

api_key: str = app.current_event.get_header_value(name="X-Api-Key", case_sensitive=True, default_value="")
todos: Response = requests.get(endpoint, headers={"X-Api-Key": api_key})
todos.raise_for_status()

return {"todos": todos.json()}


# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
28 changes: 28 additions & 0 deletions examples/event_handler_rest/src/assert_http_response.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from dataclasses import dataclass

import assert_http_response_module
import pytest


@pytest.fixture
def lambda_context():
@dataclass
class LambdaContext:
function_name: str = "test"
memory_limit_in_mb: int = 128
invoked_function_arn: str = "arn:aws:lambda:eu-west-1:123456789012:function:test"
aws_request_id: str = "da658bd3-2d6f-4e7b-8ec2-937234644fdc"

return LambdaContext()


def test_lambda_handler(lambda_context):
minimal_event = {
"path": "/todos",
"httpMethod": "GET",
"requestContext": {"requestId": "227b78aa-779d-47d4-a48e-ce62120393b8"}, # correlation ID
}

ret = assert_http_response_module.lambda_handler(minimal_event, lambda_context)
assert ret["statusCode"] == 200
assert ret["body"] != ""
27 changes: 27 additions & 0 deletions examples/event_handler_rest/src/assert_http_response_module.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import requests
from requests import Response

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver()


@app.get("/todos")
@tracer.capture_method
def get_todos():
todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos.raise_for_status()

return {"todos": todos.json()[:10]}


# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
8 changes: 8 additions & 0 deletions examples/event_handler_rest/src/binary_responses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"headers": {
"Accept": "image/svg+xml"
},
"resource": "/logo",
"path": "/logo",
"httpMethod": "GET"
}
27 changes: 27 additions & 0 deletions examples/event_handler_rest/src/binary_responses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import os
from pathlib import Path

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler.api_gateway import APIGatewayRestResolver, Response
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()


app = APIGatewayRestResolver()
logo_file: bytes = Path(os.getenv("LAMBDA_TASK_ROOT") + "/logo.svg").read_bytes()


@app.get("/logo")
@tracer.capture_method
def get_logo():
return Response(status_code=200, content_type="image/svg+xml", body=logo_file)


# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
14 changes: 14 additions & 0 deletions examples/event_handler_rest/src/binary_responses_logo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions examples/event_handler_rest/src/binary_responses_output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"body": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iMjU2cHgiIGhlaWdodD0iMjU2cHgiIHZpZXdCb3g9IjAgMCAyNTYgMjU2IiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHByZXNlcnZlQXNwZWN0UmF0aW89InhNaWRZTWlkIj4KICAgIDx0aXRsZT5BV1MgTGFtYmRhPC90aXRsZT4KICAgIDxkZWZzPgogICAgICAgIDxsaW5lYXJHcmFkaWVudCB4MT0iMCUiIHkxPSIxMDAlIiB4Mj0iMTAwJSIgeTI9IjAlIiBpZD0ibGluZWFyR3JhZGllbnQtMSI+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiNDODUxMUIiIG9mZnNldD0iMCUiPjwvc3RvcD4KICAgICAgICAgICAgPHN0b3Agc3RvcC1jb2xvcj0iI0ZGOTkwMCIgb2Zmc2V0PSIxMDAlIj48L3N0b3A+CiAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDwvZGVmcz4KICAgIDxnPgogICAgICAgIDxyZWN0IGZpbGw9InVybCgjbGluZWFyR3JhZGllbnQtMSkiIHg9IjAiIHk9IjAiIHdpZHRoPSIyNTYiIGhlaWdodD0iMjU2Ij48L3JlY3Q+CiAgICAgICAgPHBhdGggZD0iTTg5LjYyNDExMjYsMjExLjIgTDQ5Ljg5MDMyNzcsMjExLjIgTDkzLjgzNTQ4MzIsMTE5LjM0NzIgTDExMy43NDcyOCwxNjAuMzM5MiBMODkuNjI0MTEyNiwyMTEuMiBaIE05Ni43MDI5MzU3LDExMC41Njk2IEM5Ni4xNjQwODU4LDEwOS40NjU2IDk1LjA0MTQ4MTMsMTA4Ljc2NDggOTMuODE2MjM4NCwxMDguNzY0OCBMOTMuODA2NjE2MywxMDguNzY0OCBDOTIuNTcxNzUxNCwxMDguNzY4IDkxLjQ0OTE0NjYsMTA5LjQ3NTIgOTAuOTE5OTE4NywxMTAuNTg1NiBMNDEuOTEzNDIwOCwyMTMuMDIwOCBDNDEuNDM4NzE5NywyMTQuMDEyOCA0MS41MDYwNzU4LDIxNS4xNzc2IDQyLjA5NjI0NTEsMjE2LjEwODggQzQyLjY3OTk5OTQsMjE3LjAzNjggNDMuNzA2MzgwNSwyMTcuNiA0NC44MDY1MzMxLDIxNy42IEw5MS42NTQ0MjMsMjE3LjYgQzkyLjg5NTcwMjcsMjE3LjYgOTQuMDIxNTE0OSwyMTYuODg2NCA5NC41NTM5NTAxLDIxNS43Njk2IEwxMjAuMjAzODU5LDE2MS42ODk2IEMxMjAuNjE3NjE5LDE2MC44MTI4IDEyMC42MTQ0MTIsMTU5Ljc5ODQgMTIwLjE4NzgyMiwxNTguOTI4IEw5Ni43MDI5MzU3LDExMC41Njk2IFogTTIwNy45ODUxMTcsMjExLjIgTDE2OC41MDc5MjgsMjExLjIgTDEwNS4xNzM3ODksNzguNjI0IEMxMDQuNjQ0NTYxLDc3LjUxMDQgMTAzLjUxNTU0MSw3Ni44IDEwMi4yNzc0NjksNzYuOCBMNzYuNDQ3OTQzLDc2LjggTDc2LjQ3NjgwOTksNDQuOCBMMTI3LjEwMzA2Niw0NC44IEwxOTAuMTQ1MzI4LDE3Ny4zNzI4IEMxOTAuNjc0NTU2LDE3OC40ODY0IDE5MS44MDM1NzUsMTc5LjIgMTkzLjA0MTY0NywxNzkuMiBMMjA3Ljk4NTExNywxNzkuMiBMMjA3Ljk4NTExNywyMTEuMiBaIE0yMTEuMTkyNTU4LDE3Mi44IEwxOTUuMDcxOTU4LDE3Mi44IEwxMzIuMDI5Njk2LDQwLjIyNzIgQzEzMS41MDA0NjgsMzkuMTEzNiAxMzAuMzcxNDQ5LDM4LjQgMTI5LjEzMDE2OSwzOC40IEw3My4yNzI1NzYsMzguNCBDNzEuNTA1Mjc1OCwzOC40IDcwLjA2ODM0MjEsMzkuODMwNCA3MC4wNjUxMzQ0LDQxLjU5NjggTDcwLjAyOTg1MjgsNzkuOTk2OCBDNzAuMDI5ODUyOCw4MC44NDggNzAuMzYzNDI2Niw4MS42NjA4IDcwLjk2OTYzMyw4Mi4yNjI0IEM3MS41Njk0MjQ2LDgyLjg2NCA3Mi4zODQxMTQ2LDgzLjIgNzMuMjM3Mjk0MSw4My4yIEwxMDAuMjUzNTczLDgzLjIgTDE2My41OTA5MiwyMTUuNzc2IEMxNjQuMTIzMzU1LDIxNi44ODk2IDE2NS4yNDU5NiwyMTcuNiAxNjYuNDg0MDMyLDIxNy42IEwyMTEuMTkyNTU4LDIxNy42IEMyMTIuOTY2Mjc0LDIxNy42IDIxNC40LDIxNi4xNjY0IDIxNC40LDIxNC40IEwyMTQuNCwxNzYgQzIxNC40LDE3NC4yMzM2IDIxMi45NjYyNzQsMTcyLjggMjExLjE5MjU1OCwxNzIuOCBMMjExLjE5MjU1OCwxNzIuOCBaIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICA8L2c+Cjwvc3ZnPg==",
"headers": {
"Content-Type": "image/svg+xml"
},
"isBase64Encoded": true,
"statusCode": 200
}
8 changes: 8 additions & 0 deletions examples/event_handler_rest/src/compressing_responses.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"headers": {
"Accept-Encoding": "gzip"
},
"resource": "/todos",
"path": "/todos",
"httpMethod": "GET"
}
28 changes: 28 additions & 0 deletions examples/event_handler_rest/src/compressing_responses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import requests
from requests import Response

from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver()


@app.get("/todos", compress=True)
@tracer.capture_method
def get_todos():
todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos")
todos.raise_for_status()

# for brevity, we'll limit to the first 10 only
return {"todos": todos.json()[:10]}


# You can continue to use other utilities just as before
@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"statusCode": 200,
"headers": {
"Content-Type": "application/json",
"Content-Encoding": "gzip"
},
"body": "H4sIAAAAAAACE42STU4DMQyFrxJl3QXln96AMyAW7sSDLCVxiJ0Kqerd8TCCUOgii1EmP/783pOPXjmw+N3L0TfB+hz8brvxtC5KGtHvfMCIkzZx0HT5MPmNnziViIr2dIYoeNr8Q1x3xHsjcVadIbkZJoq2RXU8zzQROLseQ9505NzeCNQdMJNBE+UmY4zbzjAJhWtlZ57sB84BWtul+rteH2HPlVgWARwjqXkxpklK5gmEHAQqJBMtFsGVygcKmNVRjG0wxvuzGF2L0dpVUOKMC3bfJNjJgWMrCuZk7cUp02AiD72D6WKHHwUDKbiJs6AZ0VZXKOUx4uNvzdxT+E4mLcMA+6G8nzrLQkaxkNEVrFKW2VGbJCoCY7q2V3+tiv5kGThyxfTecDWbgGz/NfYXhL6ePgF9PnFdPgMAAA==",
"isBase64Encoded": true
}
5 changes: 5 additions & 0 deletions examples/event_handler_rest/src/custom_api_mapping.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"resource": "/subscriptions/{subscription}",
"path": "/payment/subscriptions/123",
"httpMethod": "GET"
}
20 changes: 20 additions & 0 deletions examples/event_handler_rest/src/custom_api_mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from aws_lambda_powertools import Logger, Tracer
from aws_lambda_powertools.event_handler import APIGatewayRestResolver
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools.utilities.typing import LambdaContext

tracer = Tracer()
logger = Logger()
app = APIGatewayRestResolver(strip_prefixes=["/payment"])


@app.get("/subscriptions/<subscription>")
@tracer.capture_method
def get_subscription(subscription):
return {"subscription_id": subscription}


@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@tracer.capture_lambda_handler
def lambda_handler(event: dict, context: LambdaContext) -> dict:
return app.resolve(event, context)
Loading

0 comments on commit 2a51de0

Please sign in to comment.