From 0431af9e91be4cfb430e9ee640541caf4bc9a096 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Jul 2023 14:39:50 +0200 Subject: [PATCH 1/8] fix(parameters): make cache aware of single vs multiple calls Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/parameters/base.py | 2 +- aws_lambda_powertools/utilities/parameters/types.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index e4be9d33cdc..78bf865faf0 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -27,7 +27,7 @@ from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.shared.functions import resolve_max_age -from aws_lambda_powertools.utilities.parameters.types import TransformOptions +from aws_lambda_powertools.utilities.parameters.types import RecursiveOptions, TransformOptions from .exceptions import GetParameterError, TransformParameterError diff --git a/aws_lambda_powertools/utilities/parameters/types.py b/aws_lambda_powertools/utilities/parameters/types.py index 6a15873c496..2dbf1593d72 100644 --- a/aws_lambda_powertools/utilities/parameters/types.py +++ b/aws_lambda_powertools/utilities/parameters/types.py @@ -1,3 +1,4 @@ from typing_extensions import Literal TransformOptions = Literal["json", "binary", "auto", None] +RecursiveOptions = Literal[True, False] From dd5316a29679b44d7e5c5288d498c5a6da2a342c Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Jul 2023 15:16:51 +0200 Subject: [PATCH 2/8] chore: cleanup, add test for single and nested Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/parameters/base.py | 2 +- aws_lambda_powertools/utilities/parameters/types.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index 78bf865faf0..e4be9d33cdc 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -27,7 +27,7 @@ from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.shared.functions import resolve_max_age -from aws_lambda_powertools.utilities.parameters.types import RecursiveOptions, TransformOptions +from aws_lambda_powertools.utilities.parameters.types import TransformOptions from .exceptions import GetParameterError, TransformParameterError diff --git a/aws_lambda_powertools/utilities/parameters/types.py b/aws_lambda_powertools/utilities/parameters/types.py index 2dbf1593d72..6a15873c496 100644 --- a/aws_lambda_powertools/utilities/parameters/types.py +++ b/aws_lambda_powertools/utilities/parameters/types.py @@ -1,4 +1,3 @@ from typing_extensions import Literal TransformOptions = Literal["json", "binary", "auto", None] -RecursiveOptions = Literal[True, False] From b5e1f79bc6525ca468afeefea84ad4e74d820b7e Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Fri, 8 Sep 2023 09:40:03 +0200 Subject: [PATCH 3/8] docs(event_handler): use correct correlation_id in logger.set_correlation_id example --- examples/event_handler_rest/src/middleware_getting_started.py | 2 +- .../src/middleware_global_middlewares_module.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/event_handler_rest/src/middleware_getting_started.py b/examples/event_handler_rest/src/middleware_getting_started.py index 6968c85e882..9cd53d2e34f 100644 --- a/examples/event_handler_rest/src/middleware_getting_started.py +++ b/examples/event_handler_rest/src/middleware_getting_started.py @@ -16,7 +16,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id) # (2)! - logger.set_correlation_id(request_id) + logger.set_correlation_id(correlation_id) # Get response from next middleware OR /todos route result = next_middleware(app) # (3)! diff --git a/examples/event_handler_rest/src/middleware_global_middlewares_module.py b/examples/event_handler_rest/src/middleware_global_middlewares_module.py index 81b83c868ad..43fd1a1cc12 100644 --- a/examples/event_handler_rest/src/middleware_global_middlewares_module.py +++ b/examples/event_handler_rest/src/middleware_global_middlewares_module.py @@ -22,7 +22,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id) - logger.set_correlation_id(request_id) + logger.set_correlation_id(correlation_id) # Get response from next middleware OR /todos route result = next_middleware(app) From 9ddbc120838d5dea8619121558484881a9f61a03 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Fri, 8 Sep 2023 12:07:07 +0200 Subject: [PATCH 4/8] docs(event_handler): combine correlation id with logger for a more powerful example --- examples/event_handler_rest/src/middleware_getting_started.py | 4 ++-- .../src/middleware_global_middlewares_module.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/event_handler_rest/src/middleware_getting_started.py b/examples/event_handler_rest/src/middleware_getting_started.py index 9cd53d2e34f..c5d693ec571 100644 --- a/examples/event_handler_rest/src/middleware_getting_started.py +++ b/examples/event_handler_rest/src/middleware_getting_started.py @@ -12,7 +12,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd request_id = app.current_event.request_context.request_id # (1)! # Use API Gateway REST API request ID if caller didn't include a correlation ID - correlation_id = app.current_event.headers.get("x-correlation-id", request_id) + correlation_id = logger.get_correlation_id() or request_id # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id) # (2)! @@ -35,6 +35,6 @@ def get_todos(): return {"todos": todos.json()[:10]} -@logger.inject_lambda_context +@logger.inject_lambda_context(correlation_id_path='headers."x-correlation-id"') def lambda_handler(event, context): return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/middleware_global_middlewares_module.py b/examples/event_handler_rest/src/middleware_global_middlewares_module.py index 43fd1a1cc12..22009115f26 100644 --- a/examples/event_handler_rest/src/middleware_global_middlewares_module.py +++ b/examples/event_handler_rest/src/middleware_global_middlewares_module.py @@ -18,7 +18,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd request_id = app.current_event.request_context.request_id # Use API Gateway REST API request ID if caller didn't include a correlation ID - correlation_id = app.current_event.headers.get("x-correlation-id", request_id) + correlation_id = logger.get_correlation_id() or request_id # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id) From 8cb934bf4524c2ff0d461f4ef033b3fe02a623e5 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Jul 2023 14:39:50 +0200 Subject: [PATCH 5/8] fix(parameters): make cache aware of single vs multiple calls Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/parameters/base.py | 2 +- aws_lambda_powertools/utilities/parameters/types.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index e4be9d33cdc..78bf865faf0 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -27,7 +27,7 @@ from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.shared.functions import resolve_max_age -from aws_lambda_powertools.utilities.parameters.types import TransformOptions +from aws_lambda_powertools.utilities.parameters.types import RecursiveOptions, TransformOptions from .exceptions import GetParameterError, TransformParameterError diff --git a/aws_lambda_powertools/utilities/parameters/types.py b/aws_lambda_powertools/utilities/parameters/types.py index 6a15873c496..2dbf1593d72 100644 --- a/aws_lambda_powertools/utilities/parameters/types.py +++ b/aws_lambda_powertools/utilities/parameters/types.py @@ -1,3 +1,4 @@ from typing_extensions import Literal TransformOptions = Literal["json", "binary", "auto", None] +RecursiveOptions = Literal[True, False] From f67fedcccf8044b24caa3954a5edc2566f6ee5ee Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Tue, 25 Jul 2023 15:16:51 +0200 Subject: [PATCH 6/8] chore: cleanup, add test for single and nested Signed-off-by: heitorlessa --- aws_lambda_powertools/utilities/parameters/base.py | 2 +- aws_lambda_powertools/utilities/parameters/types.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/aws_lambda_powertools/utilities/parameters/base.py b/aws_lambda_powertools/utilities/parameters/base.py index 78bf865faf0..e4be9d33cdc 100644 --- a/aws_lambda_powertools/utilities/parameters/base.py +++ b/aws_lambda_powertools/utilities/parameters/base.py @@ -27,7 +27,7 @@ from aws_lambda_powertools.shared import constants, user_agent from aws_lambda_powertools.shared.functions import resolve_max_age -from aws_lambda_powertools.utilities.parameters.types import RecursiveOptions, TransformOptions +from aws_lambda_powertools.utilities.parameters.types import TransformOptions from .exceptions import GetParameterError, TransformParameterError diff --git a/aws_lambda_powertools/utilities/parameters/types.py b/aws_lambda_powertools/utilities/parameters/types.py index 2dbf1593d72..6a15873c496 100644 --- a/aws_lambda_powertools/utilities/parameters/types.py +++ b/aws_lambda_powertools/utilities/parameters/types.py @@ -1,4 +1,3 @@ from typing_extensions import Literal TransformOptions = Literal["json", "binary", "auto", None] -RecursiveOptions = Literal[True, False] From 98766465be2a2212a14d2a66d701b9aa071c2c12 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Fri, 8 Sep 2023 12:29:34 +0200 Subject: [PATCH 7/8] docs: remove Logger dependency on retrieval to address Simon's feedback --- docs/core/event_handler/api_gateway.md | 2 +- examples/event_handler_rest/src/middleware_getting_started.py | 2 +- .../src/middleware_global_middlewares_module.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index dd249ec6650..842fb34f711 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -406,7 +406,7 @@ Here's a sample middleware that extracts and injects correlation ID, using `APIG ``` 1. You can access current request like you normally would. - 2. [Shared context is available](#sharing-contextual-data) to any middleware, Router and App instances. + 2. [Shared context is available](#sharing-contextual-data) to any middleware, Router and App instances.

For example, another middleware can now use `app.context.get("correlation_id")` to retrieve it. 3. Get response from the next middleware (if any) or from `/todos` route. 4. You can manipulate headers, body, or status code before returning it. 5. Register one or more middlewares in order of execution. diff --git a/examples/event_handler_rest/src/middleware_getting_started.py b/examples/event_handler_rest/src/middleware_getting_started.py index c5d693ec571..ff079569153 100644 --- a/examples/event_handler_rest/src/middleware_getting_started.py +++ b/examples/event_handler_rest/src/middleware_getting_started.py @@ -12,7 +12,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd request_id = app.current_event.request_context.request_id # (1)! # Use API Gateway REST API request ID if caller didn't include a correlation ID - correlation_id = logger.get_correlation_id() or request_id + correlation_id = app.context.get("correlation_id") or request_id # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id) # (2)! diff --git a/examples/event_handler_rest/src/middleware_global_middlewares_module.py b/examples/event_handler_rest/src/middleware_global_middlewares_module.py index 22009115f26..a20606bff93 100644 --- a/examples/event_handler_rest/src/middleware_global_middlewares_module.py +++ b/examples/event_handler_rest/src/middleware_global_middlewares_module.py @@ -18,7 +18,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd request_id = app.current_event.request_context.request_id # Use API Gateway REST API request ID if caller didn't include a correlation ID - correlation_id = logger.get_correlation_id() or request_id + correlation_id = app.context.get("correlation_id") or request_id # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id) From 8a55354ff92fc74f038567dccf40a5c9530bca94 Mon Sep 17 00:00:00 2001 From: heitorlessa Date: Fri, 8 Sep 2023 12:53:49 +0200 Subject: [PATCH 8/8] docs: fix racing condition, more notes based on Simon's feedback Signed-off-by: heitorlessa --- docs/core/event_handler/api_gateway.md | 10 ++++++---- .../src/middleware_getting_started.py | 12 ++++++------ .../src/middleware_global_middlewares_module.py | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/core/event_handler/api_gateway.md b/docs/core/event_handler/api_gateway.md index 842fb34f711..fc57e9b1f6c 100644 --- a/docs/core/event_handler/api_gateway.md +++ b/docs/core/event_handler/api_gateway.md @@ -406,10 +406,12 @@ Here's a sample middleware that extracts and injects correlation ID, using `APIG ``` 1. You can access current request like you normally would. - 2. [Shared context is available](#sharing-contextual-data) to any middleware, Router and App instances.

For example, another middleware can now use `app.context.get("correlation_id")` to retrieve it. - 3. Get response from the next middleware (if any) or from `/todos` route. - 4. You can manipulate headers, body, or status code before returning it. - 5. Register one or more middlewares in order of execution. + 2. Logger extracts it first in the request path, so we can use it.

If this was available before, we'd use `app.context.get("correlation_id")`. + 3. [Shared context is available](#sharing-contextual-data) to any middleware, Router and App instances.

For example, another middleware can now use `app.context.get("correlation_id")` to retrieve it. + 4. Get response from the next middleware (if any) or from `/todos` route. + 5. You can manipulate headers, body, or status code before returning it. + 6. Register one or more middlewares in order of execution. + 7. Logger extracts correlation ID from header and makes it available under `correlation_id` key, and `get_correlation_id()` method. === "middleware_getting_started_output.json" diff --git a/examples/event_handler_rest/src/middleware_getting_started.py b/examples/event_handler_rest/src/middleware_getting_started.py index ff079569153..ce03d665141 100644 --- a/examples/event_handler_rest/src/middleware_getting_started.py +++ b/examples/event_handler_rest/src/middleware_getting_started.py @@ -12,21 +12,21 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd request_id = app.current_event.request_context.request_id # (1)! # Use API Gateway REST API request ID if caller didn't include a correlation ID - correlation_id = app.context.get("correlation_id") or request_id + correlation_id = logger.get_correlation_id() or request_id # (2)! # Inject correlation ID in shared context and Logger - app.append_context(correlation_id=correlation_id) # (2)! + app.append_context(correlation_id=correlation_id) # (3)! logger.set_correlation_id(correlation_id) # Get response from next middleware OR /todos route - result = next_middleware(app) # (3)! + result = next_middleware(app) # (4)! # Include Correlation ID in the response back to caller - result.headers["x-correlation-id"] = correlation_id # (4)! + result.headers["x-correlation-id"] = correlation_id # (5)! return result -@app.get("/todos", middlewares=[inject_correlation_id]) # (5)! +@app.get("/todos", middlewares=[inject_correlation_id]) # (6)! def get_todos(): todos: Response = requests.get("https://jsonplaceholder.typicode.com/todos") todos.raise_for_status() @@ -35,6 +35,6 @@ def get_todos(): return {"todos": todos.json()[:10]} -@logger.inject_lambda_context(correlation_id_path='headers."x-correlation-id"') +@logger.inject_lambda_context(correlation_id_path='headers."x-correlation-id"') # (7)! def lambda_handler(event, context): return app.resolve(event, context) diff --git a/examples/event_handler_rest/src/middleware_global_middlewares_module.py b/examples/event_handler_rest/src/middleware_global_middlewares_module.py index a20606bff93..2b06bc31c71 100644 --- a/examples/event_handler_rest/src/middleware_global_middlewares_module.py +++ b/examples/event_handler_rest/src/middleware_global_middlewares_module.py @@ -18,7 +18,7 @@ def inject_correlation_id(app: APIGatewayRestResolver, next_middleware: NextMidd request_id = app.current_event.request_context.request_id # Use API Gateway REST API request ID if caller didn't include a correlation ID - correlation_id = app.context.get("correlation_id") or request_id + correlation_id = logger.get_correlation_id() or request_id # elsewhere becomes app.context.get("correlation_id") # Inject correlation ID in shared context and Logger app.append_context(correlation_id=correlation_id)