Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: event_source decorator with APIGatewayProxyEventV2 causes TypeError in debug mode #1152

Closed
sthuber90 opened this issue Apr 25, 2022 · 8 comments · Fixed by #1159
Closed
Labels
bug Something isn't working

Comments

@sthuber90
Copy link
Contributor

Expected Behaviour

Using the event source decorator with APIGatewayProxyEventV2 will run Lambda function and not fail with TypeError

Current Behaviour

When activating debug mode through either APIGatewayHttpResolver(debug=True) or POWERTOOLS_EVENT_HANDLER_DEBUG=true causes TypeError: Object of type APIGatewayProxyEventV2 is not JSON serializable and no further debug entries get logged.

Code snippet

from aws_lambda_powertools.utilities.data_classes import (
    APIGatewayProxyEventV2,
    event_source,
)
from aws_lambda_powertools.logging import correlation_paths
from aws_lambda_powertools import Logger
from aws_lambda_powertools.event_handler import APIGatewayHttpResolver
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger()
app = APIGatewayHttpResolver(debug=True)


@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext):
    return app.resolve(event, context)

@app.get("/my/path")
def get_hello_universe():
    return {"message": "hello universe"}

Possible Solution

Workaround: Enable debug mode and comment event source out

Steps to Reproduce

Create a Lambda function accepting APIGatewayProxyEventV2 requests. Decorate the handler method with logger inject and event source and add a simple route that will just return a small JSON response. Then enable debug mode by one of the supported ways and watch the lambda function fail

AWS Lambda Powertools for Python version

latest (Layer version 18)

AWS Lambda function runtime

3.9

Packaging format used

Lambda Layers

Debugging logs

[ERROR] TypeError: Object of type APIGatewayProxyEventV2 is not JSON serializable
Traceback (most recent call last):
  File "/opt/python/aws_lambda_powertools/logging/logger.py", line 354, in decorate
    return lambda_handler(event, context)
  File "/opt/python/aws_lambda_powertools/middleware_factory/factory.py", line 134, in wrapper
    response = middleware()
  File "/opt/python/aws_lambda_powertools/utilities/data_classes/event_source.py", line 39, in event_source
    return handler(data_class(event), context)
  File "/var/task/app.py", line 28, in lambda_handler
    return app.resolve(event, context)
  File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 495, in resolve
    print(self._json_dump(event), end="")
  File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 688, in _json_dump
    return self._serializer(obj)
  File "/var/lang/lib/python3.9/json/__init__.py", line 234, in dumps
    return cls(
  File "/var/lang/lib/python3.9/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/var/lang/lib/python3.9/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/opt/python/aws_lambda_powertools/shared/json_encoder.py", line 16, in default
    return super().default(obj)
  File "/var/lang/lib/python3.9/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
@sthuber90 sthuber90 added bug Something isn't working triage Pending triage from maintainers labels Apr 25, 2022
@heitorlessa
Copy link
Contributor

Hey @sthuber90 tha is for reporting it - we'll look into it as soon as we can.

Any particular reason you're using event_source with Event Handler?

We already do that for you upon a Lambda invocation, and make it available under app.current_event property.

https://awslabs.github.io/aws-lambda-powertools-python/latest/core/event_handler/api_gateway/#accessing-request-details

Thanks!!

@sthuber90
Copy link
Contributor Author

Thank you. No, no particular reason combining @event_source and APIGatewayHttpResolver. It's perfectly fine for me to remove the event source decorator. Are the resolver and event source incompatible? If so, I didn't see it in the docs

@heitorlessa
Copy link
Contributor

heitorlessa commented Apr 25, 2022 via email

michaelbrewer added a commit to gyft/aws-lambda-powertools-python that referenced this issue Apr 26, 2022
Changes:
- Allow for event being of type 'BaseProxyEvent'
- Add test case

closes aws-powertools#1152
@michaelbrewer
Copy link
Contributor

@heitorlessa @sthuber90 - i am sorry for missing this edge case, but it is pretty valid if your handler wants to use the data class. So i put up a PR which is pretty small.

Otherwise a current workaround would be:

@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext):
    return app.resolve(event.raw_event, context)

One thing i notices is that PyCharm does infer that event should be a dict.

Screen Shot 2022-04-26 at 10 30 50 AM

@heitorlessa heitorlessa removed the triage Pending triage from maintainers label Apr 28, 2022
@heitorlessa heitorlessa linked a pull request Apr 28, 2022 that will close this issue
7 tasks
@heitorlessa
Copy link
Contributor

thanks @michaelbrewer for the quick fix. I've pushed a change before merging so customers receive a warning that this is not necessary (double serialization), and link to this issue.

@heitorlessa heitorlessa added the pending-release Fix or implementation already in dev waiting to be released label Apr 28, 2022
@heitorlessa heitorlessa reopened this Apr 28, 2022
@sthuber90
Copy link
Contributor Author

sthuber90 commented Apr 28, 2022

Thank you. I actually think I found a use case:

@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_HTTP)
@event_source(data_class=APIGatewayProxyEventV2)
def lambda_handler(event: APIGatewayProxyEventV2, context: LambdaContext):
    logger.append_keys(path=event.path)
    return app.resolve(event, context)

Of course there are other ways to solve this, instead of using the event source handler 😏

@michaelbrewer
Copy link
Contributor

Yes within handler, you do have the option of also passing in event.raw_event

@github-actions
Copy link
Contributor

This is now released under 1.25.10 version!

@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Apr 29, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants