From dbfd5d926b6dce1273ce6ee1b9d43102b82dc35d Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Mon, 3 Feb 2025 16:59:00 -0800 Subject: [PATCH 1/3] Simplify if underlying exception has no message In `SlackWebException.from_exception`, the message of the created `SlackWebException` is based on the type name and message of the underlying exception. However, some underlying exceptions, such as timeout errors, may have no message. In that case, drop the trailing colon and space and set the message of `SlackWebException` to only the name of the type of the underlying exception. --- safir/src/safir/slack/blockkit.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/safir/src/safir/slack/blockkit.py b/safir/src/safir/slack/blockkit.py index b9099e18..750508c5 100644 --- a/safir/src/safir/slack/blockkit.py +++ b/safir/src/safir/slack/blockkit.py @@ -358,7 +358,8 @@ def from_exception(cls, exc: HTTPError, user: str | None = None) -> Self: body=exc.response.text, ) else: - message = f"{type(exc).__name__}: {exc!s}" + exc_name = type(exc).__name__ + message = f"{exc_name}: {exc!s}" if str(exc) else exc_name # All httpx.HTTPError exceptions have a slot for the request, # initialized to None and then sometimes added by child From 0ea374abbc1080ed232f876ad186798f57f4a0f1 Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Mon, 3 Feb 2025 17:03:19 -0800 Subject: [PATCH 2/3] Improve change log for 9.2.0 Flesh out the change log entry for Sentry integration helpers. --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46cf7487..13198d6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,8 +14,7 @@ Changes for the upcoming release can be found in [changelog.d](https://github.co ### New features -- Sentry instrumentation helpers - +- Add a new `safir.sentry` module that provides helper functions and custom exception types for improved Sentry integration. - Allow the encryption key to be passed to `safir.redis.EncryptedPydanticRedisStorage` as a `pydantic.SecretStr` instead of `str`. This allows easier integration with secrets that come from Pydantic-parsed settings. From cf56c7051dd6894604b9f6ac8fe4e897cb78703a Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Mon, 3 Feb 2025 17:06:50 -0800 Subject: [PATCH 3/3] Also simplify SentryWebException Similar to `SlackWebException`, simplify the message of `SentryWebException` if the underlying exception has no message. --- safir/src/safir/sentry/_exceptions.py | 9 +++++---- safir/src/safir/slack/blockkit.py | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/safir/src/safir/sentry/_exceptions.py b/safir/src/safir/sentry/_exceptions.py index d136e760..b8b2a4c6 100644 --- a/safir/src/safir/sentry/_exceptions.py +++ b/safir/src/safir/sentry/_exceptions.py @@ -88,15 +88,16 @@ def from_exception(cls, exc: HTTPError, user: str | None = None) -> Self: body=exc.response.text, ) else: - message = f"{type(exc).__name__}: {exc!s}" + exc_name = type(exc).__name__ + message = f"{exc_name}: {exc!s}" if str(exc) else exc_name # All httpx.HTTPError exceptions have a slot for the request, # initialized to None and then sometimes added by child # constructors or during exception processing. The request # property is a property method that raises RuntimeError if - # request has not been set, so we can't just check for None. - # Hence this approach of attempting to use the request and falling - # back on reporting less data if that raised any exception. + # request has not been set, so we can't just check for None. Hence + # this approach of attempting to use the request and falling back + # on reporting less data if that raised any exception. try: return cls( message, diff --git a/safir/src/safir/slack/blockkit.py b/safir/src/safir/slack/blockkit.py index 750508c5..bb404e11 100644 --- a/safir/src/safir/slack/blockkit.py +++ b/safir/src/safir/slack/blockkit.py @@ -365,9 +365,9 @@ def from_exception(cls, exc: HTTPError, user: str | None = None) -> Self: # initialized to None and then sometimes added by child # constructors or during exception processing. The request # property is a property method that raises RuntimeError if - # request has not been set, so we can't just check for None. - # Hence this approach of attempting to use the request and falling - # back on reporting less data if that raised any exception. + # request has not been set, so we can't just check for None. Hence + # this approach of attempting to use the request and falling back + # on reporting less data if that raised any exception. try: return cls( message,