Skip to content

Commit 5fda86d

Browse files
authored
fix(metrics): lambda_handler typing, and **kwargs preservation all middlewares (#3460)
1 parent d76607c commit 5fda86d

File tree

9 files changed

+33
-18
lines changed

9 files changed

+33
-18
lines changed

aws_lambda_powertools/metrics/metrics.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
# NOTE: keeps for compatibility
22
from __future__ import annotations
33

4-
from typing import Any, Callable, Dict, Optional
4+
from typing import Any, Dict
55

66
from aws_lambda_powertools.metrics.base import MetricResolution, MetricUnit
77
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.cloudwatch import AmazonCloudWatchEMFProvider
88
from aws_lambda_powertools.metrics.provider.cloudwatch_emf.types import CloudWatchEMFOutput
9+
from aws_lambda_powertools.shared.types import AnyCallableT
910

1011

1112
class Metrics:
@@ -129,16 +130,18 @@ def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:
129130

130131
def log_metrics(
131132
self,
132-
lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
133+
lambda_handler: AnyCallableT | None = None,
133134
capture_cold_start_metric: bool = False,
134135
raise_on_empty_metrics: bool = False,
135136
default_dimensions: Dict[str, str] | None = None,
137+
**kwargs,
136138
):
137139
return self.provider.log_metrics(
138140
lambda_handler=lambda_handler,
139141
capture_cold_start_metric=capture_cold_start_metric,
140142
raise_on_empty_metrics=raise_on_empty_metrics,
141143
default_dimensions=default_dimensions,
144+
**kwargs,
142145
)
143146

144147
def set_default_dimensions(self, **dimensions) -> None:

aws_lambda_powertools/metrics/provider/base.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
import functools
44
import logging
55
from abc import ABC, abstractmethod
6-
from typing import Any, Callable, Dict, Optional
6+
from typing import Any
77

88
from aws_lambda_powertools.metrics.provider import cold_start
9+
from aws_lambda_powertools.shared.types import AnyCallableT
910
from aws_lambda_powertools.utilities.typing import LambdaContext
1011

1112
logger = logging.getLogger(__name__)
@@ -140,7 +141,7 @@ def add_cold_start_metric(self, context: LambdaContext) -> Any:
140141

141142
def log_metrics(
142143
self,
143-
lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
144+
lambda_handler: AnyCallableT | None = None,
144145
capture_cold_start_metric: bool = False,
145146
raise_on_empty_metrics: bool = False,
146147
**kwargs,

aws_lambda_powertools/metrics/provider/cloudwatch_emf/cloudwatch.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import os
88
import warnings
99
from collections import defaultdict
10-
from typing import Any, Callable, Dict, List, Optional
10+
from typing import Any, Dict, List
1111

1212
from aws_lambda_powertools.metrics.base import single_metric
1313
from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError
@@ -22,6 +22,7 @@
2222
from aws_lambda_powertools.metrics.types import MetricNameUnitResolution
2323
from aws_lambda_powertools.shared import constants
2424
from aws_lambda_powertools.shared.functions import resolve_env_var_choice
25+
from aws_lambda_powertools.shared.types import AnyCallableT
2526
from aws_lambda_powertools.utilities.typing import LambdaContext
2627

2728
logger = logging.getLogger(__name__)
@@ -334,7 +335,7 @@ def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:
334335

335336
def log_metrics(
336337
self,
337-
lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
338+
lambda_handler: AnyCallableT | None = None,
338339
capture_cold_start_metric: bool = False,
339340
raise_on_empty_metrics: bool = False,
340341
**kwargs,

aws_lambda_powertools/metrics/provider/datadog/datadog.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@
77
import re
88
import time
99
import warnings
10-
from typing import Any, Callable, Dict, List, Optional
10+
from typing import Any, Dict, List
1111

1212
from aws_lambda_powertools.metrics.exceptions import MetricValueError, SchemaValidationError
1313
from aws_lambda_powertools.metrics.provider import BaseProvider
1414
from aws_lambda_powertools.metrics.provider.datadog.warnings import DatadogDataValidationWarning
1515
from aws_lambda_powertools.shared import constants
1616
from aws_lambda_powertools.shared.functions import resolve_env_var_choice
17+
from aws_lambda_powertools.shared.types import AnyCallableT
1718
from aws_lambda_powertools.utilities.typing import LambdaContext
1819

1920
METRIC_NAME_REGEX = re.compile(r"^[a-zA-Z0-9_.]+$")
@@ -226,7 +227,7 @@ def add_cold_start_metric(self, context: LambdaContext) -> None:
226227

227228
def log_metrics(
228229
self,
229-
lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
230+
lambda_handler: AnyCallableT | None = None,
230231
capture_cold_start_metric: bool = False,
231232
raise_on_empty_metrics: bool = False,
232233
**kwargs,

aws_lambda_powertools/metrics/provider/datadog/metrics.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# NOTE: keeps for compatibility
22
from __future__ import annotations
33

4-
from typing import Any, Callable, Dict, List, Optional
4+
from typing import Any, Dict, List
55

66
from aws_lambda_powertools.metrics.provider.datadog.datadog import DatadogProvider
7+
from aws_lambda_powertools.shared.types import AnyCallableT
78

89

910
class DatadogMetrics:
@@ -90,7 +91,7 @@ def flush_metrics(self, raise_on_empty_metrics: bool = False) -> None:
9091

9192
def log_metrics(
9293
self,
93-
lambda_handler: Callable[[Dict, Any], Any] | Optional[Callable[[Dict, Any, Optional[Dict]], Any]] = None,
94+
lambda_handler: AnyCallableT | None = None,
9495
capture_cold_start_metric: bool = False,
9596
raise_on_empty_metrics: bool = False,
9697
default_tags: Dict[str, Any] | None = None,

aws_lambda_powertools/middleware_factory/factory.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ def final_decorator(func: Optional[Callable] = None, **kwargs: Any):
124124
)
125125

126126
@functools.wraps(func)
127-
def wrapper(event, context):
127+
def wrapper(event, context, **handler_kwargs):
128128
try:
129-
middleware = functools.partial(decorator, func, event, context, **kwargs)
129+
middleware = functools.partial(decorator, func, event, context, **kwargs, **handler_kwargs)
130130
if trace_execution:
131131
tracer = Tracer(auto_patch=False)
132132
with tracer.provider.in_subsegment(name=f"## {decorator.__qualname__}"):

aws_lambda_powertools/utilities/idempotency/idempotency.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def idempotent(
6666
"""
6767

6868
if os.getenv(constants.IDEMPOTENCY_DISABLED_ENV):
69-
return handler(event, context)
69+
return handler(event, context, **kwargs)
7070

7171
config = config or IdempotencyConfig()
7272
config.register_lambda_context(context)
@@ -91,6 +91,7 @@ def idempotent_function(
9191
persistence_store: BasePersistenceLayer,
9292
config: Optional[IdempotencyConfig] = None,
9393
output_serializer: Optional[Union[BaseIdempotencySerializer, Type[BaseIdempotencyModelSerializer]]] = None,
94+
**kwargs: Any,
9495
) -> Any:
9596
"""
9697
Decorator to handle idempotency of any function
@@ -136,6 +137,7 @@ def process_order(customer_id: str, order: dict, **kwargs):
136137
persistence_store=persistence_store,
137138
config=config,
138139
output_serializer=output_serializer,
140+
**kwargs,
139141
),
140142
)
141143

aws_lambda_powertools/utilities/parser/parser.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@
1515

1616
@lambda_handler_decorator
1717
def event_parser(
18-
handler: Callable[[Any, LambdaContext], EventParserReturnType],
18+
handler: Callable[..., EventParserReturnType],
1919
event: Dict[str, Any],
2020
context: LambdaContext,
2121
model: Optional[Type[Model]] = None,
2222
envelope: Optional[Type[Envelope]] = None,
23+
**kwargs: Any,
2324
) -> EventParserReturnType:
2425
"""Lambda handler decorator to parse & validate events using Pydantic models
2526
@@ -93,9 +94,13 @@ def handler(event: Order, context: LambdaContext):
9394
"or as the type hint of `event` in the handler that it wraps",
9495
)
9596

96-
parsed_event = parse(event=event, model=model, envelope=envelope) if envelope else parse(event=event, model=model)
97+
if envelope:
98+
parsed_event = parse(event=event, model=model, envelope=envelope)
99+
else:
100+
parsed_event = parse(event=event, model=model)
101+
97102
logger.debug(f"Calling handler {handler.__name__}")
98-
return handler(parsed_event, context)
103+
return handler(parsed_event, context, **kwargs)
99104

100105

101106
@overload
@@ -104,7 +109,7 @@ def parse(event: Dict[str, Any], model: Type[Model]) -> Model:
104109

105110

106111
@overload
107-
def parse(event: Dict[str, Any], model: Type[Model], envelope: Type[Envelope]):
112+
def parse(event: Dict[str, Any], model: Type[Model], envelope: Type[Envelope]) -> Model:
108113
... # pragma: no cover
109114

110115

aws_lambda_powertools/utilities/validation/validator.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ def validator(
2020
outbound_formats: Optional[Dict] = None,
2121
envelope: str = "",
2222
jmespath_options: Optional[Dict] = None,
23+
**kwargs: Any,
2324
) -> Any:
2425
"""Lambda handler decorator to validate incoming/outbound data using a JSON Schema
2526
@@ -128,7 +129,7 @@ def handler(event, context):
128129
logger.debug("Validating inbound event")
129130
validate_data_against_schema(data=event, schema=inbound_schema, formats=inbound_formats)
130131

131-
response = handler(event, context)
132+
response = handler(event, context, **kwargs)
132133

133134
if outbound_schema:
134135
logger.debug("Validating outbound event")

0 commit comments

Comments
 (0)