getsentry / getsentry/sentry-python
Exceptions are formatted incorrectly (or even fail) when `message` or `detail` attribute presents
- 主要言語
- Python
- スター
- 2.2k
- フォーク
- 669
- 平均マージ
- 1日 1時間
- マージ済み PR(30日)
- 213
説明
### How do you use Sentry?
Self-hosted/on-premise
### Version
2.43.0
### Steps to Reproduce
Some of our exception define properties `message` and `detail`. The formatting of error message for those exceptions is almost always incorrect (doesn't contain important information, not formatted properly) or sometimes even fails. There is a couple of such exceptions in simplified form:
```python
class GRpcError(Exception):
def __init__(self, code: int, message: bytes) -> None:
super().__init__(code, message)
self.code = code
# Original protobuf message to allow its inspection in error handlers.
# Here we use bytes, but it can be `google.protobuf.message.Message`
# instance as well.
self.message = message
def __str__(self) -> str:
return f"code={self.code}"
class ApiError(Exception):
def __init__(self, code: str, detail: dict[str, Any]) -> None:
super().__init__(code, detail)
self.code = code
self.detail = detail
def __str__(self) -> str:
formatted = f"[{self.code}]"
for key, value in self.detail.items():
formatted += f"\n {key}={value}"
return formatted
```
### Expected Result
Here is how they are formatted by Python itself:
```python
grpc_exc = GRpcError(13, b"unreadable protobuf message")
print("".join(traceback.format_exception_only(grpc_exc)).strip())
# GRpcError: code=13
grpc_exc.add_note("additional context note")
print("".join(traceback.format_exception_only(grpc_exc)).strip())
# GRpcError: code=13
# additional context note
api_exc = ApiError("RATE_LIMIT_EXCEEDED", detail={"retry_after": 30})
print("".join(traceback.format_exception_only(api_exc)).strip())
# ApiError: [RATE_LIMIT_EXCEEDED]
# retry_after=30
api_exc.add_note("additional context note")
print("".join(traceback.format_exception_only(api_exc)).strip())
# ApiError: [RATE_LIMIT_EXCEEDED]
# retry_after=30
# additional context note
```
### Actual Result
And the formatting by sentry (`get_error_message` is used internally by `event_from_exception`, here I call it directly):
```python
grpc_exc = GRpcError(13, b"unreadable protobuf message")
print(sentry_sdk.utils.get_error_message(grpc_exc))
# No `code` field, only unreadable field in the result:
# b'unreadable protobuf message'
grpc_exc.add_note("additional context note")
print(sentry_sdk.utils.get_error_message(grpc_exc))
# Fails with the error:
# TypeError: can't concat str to bytes
api_exc = ApiError("RATE_LIMIT_EXCEEDED", detail={"retry_after": 30})
print(sentry_sdk.utils.get_error_message(api_exc))
# No `code` field, `detail` is not formatted:
# {'retry_after': 30}
api_exc.add_note("additional context note")
print(sentry_sdk.utils.get_error_message(api_exc))
# Fails with the error:
# TypeError: unsupported operand type(s) for +=: 'dict' and 'str'
```
コントリビューションガイド
評価
この issue はまだ評価されていません。