Closed
Description
I noticed that if I define a class like this:
from typing import Mapping
class Foo(Mapping):
def __repr__(self) -> str:
return "custom repr() to save space in the stack trace parameters list"
then Sentry does not call my custom repr()
and serializes the object like a regular dict. That's because how _serialize_node_impl
in serializer.py
branches:
if obj is None or isinstance(obj, (bool, number_types)):
...
elif isinstance(obj, datetime):
...
elif isinstance(obj, Mapping): # <- this is where all classes inherited from Mapping land
...
elif not isinstance(obj, serializable_str_types) and isinstance(obj, (Set, Sequence)):
...
obj = safe_repr(obj) # <- I want to flow here
I need this feature much because I deal with huge dict-likes (custom dataclasses with tens of key-values), they don't fully fit in the stack trace parameters list and thus clobber the rest of the values standing after them. My handcrafted __repr__
summarizes them instead of printing all the contents and significantly reduces the envelope size. My current workaround is:
class OverriddenReprMeta(abc.ABCMeta):
"""Metaclass for OverriddenReprMapping to make isinstance() return False on custom repr()-s."""
def __instancecheck__(self, instance):
"""Override for isinstance(instance, cls)."""
if type(instance).__repr__ not in (object.__repr__, dict.__repr__):
return False
return super().__instancecheck__(instance)
class OverriddenReprMapping(Mapping, metaclass=OverriddenReprMeta):
"""Mapping that fails isinstance() check if the object contains a custom repr()."""
sentry_sdk.serializer.serialize.__globals__["Mapping"] = OverriddenReprMapping
It's a broken ugly hack, of course, but it works really well for my project.
Would you please add custom __repr__
support for classes that inherit from Mapping?