feat: support logging of exceptions#277
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces exception logging capabilities to the logger, including a new exception function to log active stack traces and utility functions to safely serialize exceptions and handle circular references in exception arguments. Comprehensive tests have been added to verify these changes. The review feedback suggests improving type safety by changing the type of the refs parameter from set[_typing.Any] to set[int] in both _exception_from_args and _remove_circular, as it is used to track object IDs.
|
My main concern here is divergence from what JS does. I think JS puts the stack trace into the message field. It has no separate field or exception dict equivalent. Generally we need to keep the SDKs aligned Can we check if exceptions logged via this new approach show up in the error reporting console? |
Fixes #172
Summary
This updates
firebase_functions.loggersoERRORlogs can safely include exception values and other non-JSON-safe payloads without failing serialization, while aligning the emitted traceback shape with the JS SDK. Stack traces now surface at top-levelstack_trace, and the Python-only structured exception surface introduced earlier in the PR is removed.Problem/Root Cause
The original logger could fail when error metadata included exception-related values that were not directly JSON serializable, including the documented
sys.exc_info()[0]pattern and exception arguments containing opaque objects, badrepr()implementations, or cyclic data.The initial fix in this PR added a Python-specific structured exception payload under
errorand a newlogger.exception(...)helper. Reviewer feedback called out that this diverged from the JS SDK's logging shape, especially around traceback placement and the public API surface.Solution/Changes
The logger now applies the defensive serialization work generically, keeping circular-reference handling and safe repr coercion for arbitrary metadata values instead of treating exceptions as a special nested schema.
For
ERRORseverity, the logger inspects the provided arguments and active exception state, then emits any available traceback at top-levelstack_trace. Exception values passed viaerror=remain ordinary serialized metadata, so opaque or non-JSON-safe exception arguments no longer crash logging, but logs no longer emit nested-only traces or a Python-onlylogger.exception(...)helper.The test coverage was updated to match the final behavior, including exception instances,
sys.exc_info()[0], self-referential and cyclic payloads, non-JSON-safe values, and the top-level stack trace shape.Testing
tests/test_logger.pyto cover exception instances, exception types fromsys.exc_info()[0], cyclic/self-referential payloads, non-JSON-safe values, and top-levelstack_tracebehavior forERRORlogs.python3 -m pytest -q tests/test_logger.py