aws / aws-lambda-python-runtime-interface-client

Apache License 2.0
261 stars 74 forks source link

Better logging of unhandled Python 3.11 ExceptionGroups #161

Open jmehnle opened 1 month ago

jmehnle commented 1 month ago

Python 3.11 introduced exception groups (the {Base,}ExceptionGroup classes) to better handle situations where async (and other) code may raise multiple exceptions that need to be propagated and handled/logged together.

Unfortunately the Lambda Python RIC's logging of unhandled exceptions performs rather poorly when encountering such exception groups. I have a lambda function that is implemented with async Python code (using the trio framework, but that's tangential, and the same problem could occur using the stdlib asyncio framework), and I've been running into situations where the lambda function fails for a variety of reasons (such as being unable to connect to one of its dependency services), and all I get in the response is:

{
    "timestamp": "2024-07-27T00:17:54Z",
    "log_level": "ERROR",
    "errorMessage": "Exceptions from Trio nursery (1 sub-exception)",
    "errorType": "ExceptionGroup",
    "requestId": "redacted",
    "stackTrace": [
        "... long stack trace redacted ..."
    ]
}

The fact that only the top-level ExceptionGroup object is included in the output has been incredibly frustrating because it obscures the true cause of the failure.

As asyncio matures, this situation will become increasingly common (though likely never exactly become a mainstream problem). I believe you should find some way of including information about the exceptions nested inside the exception group. In this PR I'm proposing a simple change that concatenates all nested exception messages for inclusion in the errorMessage field, but if you prefer a more sophisticated solution, feel free to use my simple change as a starting point.

Ideally the structure generated by the make_error function would be overhauled to account for the fact that as of Python 3.11, exceptions can now be trees of exceptions.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.