From 0bb34ed3e0bfde303fd052149bd42c038d57d4f0 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 8 Sep 2023 15:03:26 +0200 Subject: [PATCH] Add the Sentry event ID in error response headers --- crates/axum-utils/src/fancy_error.rs | 5 ++- crates/axum-utils/src/lib.rs | 1 + crates/axum-utils/src/sentry.rs | 38 +++++++++++++++++++ crates/handlers/src/compat/login.rs | 10 +++-- .../handlers/src/compat/login_sso_redirect.rs | 10 ++++- crates/handlers/src/compat/logout.rs | 10 +++-- crates/handlers/src/compat/refresh.rs | 10 +++-- crates/handlers/src/graphql/mod.rs | 12 ++++-- .../src/oauth2/authorization/complete.rs | 10 +++-- .../handlers/src/oauth2/authorization/mod.rs | 10 +++-- crates/handlers/src/oauth2/consent.rs | 9 ++++- crates/handlers/src/oauth2/introspection.rs | 9 +++-- crates/handlers/src/oauth2/registration.rs | 9 +++-- crates/handlers/src/oauth2/revoke.rs | 9 +++-- crates/handlers/src/oauth2/token.rs | 11 ++++-- crates/handlers/src/oauth2/userinfo.rs | 9 +++-- .../handlers/src/upstream_oauth2/authorize.rs | 12 ++++-- .../handlers/src/upstream_oauth2/callback.rs | 12 ++++-- crates/handlers/src/upstream_oauth2/link.rs | 9 +++-- 19 files changed, 149 insertions(+), 56 deletions(-) create mode 100644 crates/axum-utils/src/sentry.rs diff --git a/crates/axum-utils/src/fancy_error.rs b/crates/axum-utils/src/fancy_error.rs index 88cefdbb..27c238d6 100644 --- a/crates/axum-utils/src/fancy_error.rs +++ b/crates/axum-utils/src/fancy_error.rs @@ -19,6 +19,8 @@ use axum::{ }; use mas_templates::ErrorContext; +use crate::sentry::SentryEventID; + pub struct FancyError { context: ErrorContext, } @@ -59,9 +61,10 @@ impl From for FancyError { impl IntoResponse for FancyError { fn into_response(self) -> Response { let error = format!("{:?}", self.context); - sentry::capture_message(&error, sentry::Level::Error); + let event_id = sentry::capture_message(&error, sentry::Level::Error); ( StatusCode::INTERNAL_SERVER_ERROR, + SentryEventID::from(event_id), Extension(self.context), error, ) diff --git a/crates/axum-utils/src/lib.rs b/crates/axum-utils/src/lib.rs index 799f66a4..9174ee12 100644 --- a/crates/axum-utils/src/lib.rs +++ b/crates/axum-utils/src/lib.rs @@ -28,6 +28,7 @@ pub mod csrf; pub mod fancy_error; pub mod http_client_factory; pub mod jwt; +pub mod sentry; pub mod session; pub mod user_authorization; diff --git a/crates/axum-utils/src/sentry.rs b/crates/axum-utils/src/sentry.rs new file mode 100644 index 00000000..95bf6ed9 --- /dev/null +++ b/crates/axum-utils/src/sentry.rs @@ -0,0 +1,38 @@ +// Copyright 2023 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::convert::Infallible; + +use axum::response::{IntoResponseParts, ResponseParts}; +use sentry::types::Uuid; + +/// A wrapper to include a Sentry event ID in the response headers. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct SentryEventID(Uuid); + +impl From for SentryEventID { + fn from(uuid: Uuid) -> Self { + Self(uuid) + } +} + +impl IntoResponseParts for SentryEventID { + type Error = Infallible; + fn into_response_parts(self, mut res: ResponseParts) -> Result { + res.headers_mut() + .insert("X-Sentry-Event-ID", self.0.to_string().parse().unwrap()); + + Ok(res) + } +} diff --git a/crates/handlers/src/compat/login.rs b/crates/handlers/src/compat/login.rs index bdf380af..3cc4531c 100644 --- a/crates/handlers/src/compat/login.rs +++ b/crates/handlers/src/compat/login.rs @@ -15,6 +15,7 @@ use axum::{extract::State, response::IntoResponse, Json}; use chrono::Duration; use hyper::StatusCode; +use mas_axum_utils::sentry::SentryEventID; use mas_data_model::{CompatSession, CompatSsoLoginState, Device, TokenType, User}; use mas_storage::{ compat::{ @@ -169,8 +170,8 @@ impl_from_error_for_route!(mas_storage::RepositoryError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(_) | Self::SessionNotFound => MatrixError { errcode: "M_UNKNOWN", error: "Internal server error", @@ -198,8 +199,9 @@ impl IntoResponse for RouteError { error: "Invalid login token", status: StatusCode::FORBIDDEN, }, - } - .into_response() + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/compat/login_sso_redirect.rs b/crates/handlers/src/compat/login_sso_redirect.rs index cd0a19b9..a87fa8e5 100644 --- a/crates/handlers/src/compat/login_sso_redirect.rs +++ b/crates/handlers/src/compat/login_sso_redirect.rs @@ -18,6 +18,7 @@ use axum::{ response::IntoResponse, }; use hyper::StatusCode; +use mas_axum_utils::sentry::SentryEventID; use mas_router::{CompatLoginSsoAction, CompatLoginSsoComplete, UrlBuilder}; use mas_storage::{compat::CompatSsoLoginRepository, BoxClock, BoxRepository, BoxRng}; use rand::distributions::{Alphanumeric, DistString}; @@ -51,8 +52,13 @@ impl_from_error_for_route!(mas_storage::RepositoryError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - (StatusCode::INTERNAL_SERVER_ERROR, format!("{self}")).into_response() + let event_id = sentry::capture_error(&self); + ( + StatusCode::INTERNAL_SERVER_ERROR, + SentryEventID::from(event_id), + format!("{self}"), + ) + .into_response() } } diff --git a/crates/handlers/src/compat/logout.rs b/crates/handlers/src/compat/logout.rs index 4f91f363..6b08a52d 100644 --- a/crates/handlers/src/compat/logout.rs +++ b/crates/handlers/src/compat/logout.rs @@ -15,6 +15,7 @@ use axum::{response::IntoResponse, Json, TypedHeader}; use headers::{authorization::Bearer, Authorization}; use hyper::StatusCode; +use mas_axum_utils::sentry::SentryEventID; use mas_data_model::TokenType; use mas_storage::{ compat::{CompatAccessTokenRepository, CompatSessionRepository}, @@ -45,8 +46,8 @@ impl_from_error_for_route!(mas_storage::RepositoryError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(_) => MatrixError { errcode: "M_UNKNOWN", error: "Internal error", @@ -62,8 +63,9 @@ impl IntoResponse for RouteError { error: "Invalid access token", status: StatusCode::UNAUTHORIZED, }, - } - .into_response() + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/compat/refresh.rs b/crates/handlers/src/compat/refresh.rs index 3bf06c83..1f5ed754 100644 --- a/crates/handlers/src/compat/refresh.rs +++ b/crates/handlers/src/compat/refresh.rs @@ -15,6 +15,7 @@ use axum::{extract::State, response::IntoResponse, Json}; use chrono::Duration; use hyper::StatusCode; +use mas_axum_utils::sentry::SentryEventID; use mas_data_model::{TokenFormatError, TokenType}; use mas_storage::{ compat::{CompatAccessTokenRepository, CompatRefreshTokenRepository, CompatSessionRepository}, @@ -52,8 +53,8 @@ pub enum RouteError { impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(_) | Self::UnknownSession => MatrixError { errcode: "M_UNKNOWN", error: "Internal error", @@ -64,8 +65,9 @@ impl IntoResponse for RouteError { error: "Invalid refresh token", status: StatusCode::UNAUTHORIZED, }, - } - .into_response() + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/graphql/mod.rs b/crates/handlers/src/graphql/mod.rs index 79069856..2bbd6a2a 100644 --- a/crates/handlers/src/graphql/mod.rs +++ b/crates/handlers/src/graphql/mod.rs @@ -28,7 +28,9 @@ use axum::{ use futures_util::TryStreamExt; use headers::{authorization::Bearer, Authorization, ContentType, HeaderValue}; use hyper::header::CACHE_CONTROL; -use mas_axum_utils::{cookies::CookieJar, FancyError, SessionInfo, SessionInfoExt}; +use mas_axum_utils::{ + cookies::CookieJar, sentry::SentryEventID, FancyError, SessionInfo, SessionInfoExt, +}; use mas_data_model::User; use mas_graphql::{Requester, Schema}; use mas_matrix::HomeserverConnection; @@ -144,9 +146,9 @@ impl_from_error_for_route!(mas_storage::RepositoryError); impl IntoResponse for RouteError { fn into_response(self) -> Response { - sentry::capture_error(&self); + let event_id = sentry::capture_error(&self); - match self { + let response = match self { e @ (Self::Internal(_) | Self::LoadFailed) => { let error = async_graphql::Error::new_with_source(e); ( @@ -182,7 +184,9 @@ impl IntoResponse for RouteError { ) .into_response() } - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/oauth2/authorization/complete.rs b/crates/handlers/src/oauth2/authorization/complete.rs index c804c304..a2dca527 100644 --- a/crates/handlers/src/oauth2/authorization/complete.rs +++ b/crates/handlers/src/oauth2/authorization/complete.rs @@ -17,7 +17,7 @@ use axum::{ response::{Html, IntoResponse, Response}, }; use hyper::StatusCode; -use mas_axum_utils::{cookies::CookieJar, csrf::CsrfExt, SessionInfoExt}; +use mas_axum_utils::{cookies::CookieJar, csrf::CsrfExt, sentry::SentryEventID, SessionInfoExt}; use mas_data_model::{AuthorizationGrant, BrowserSession, Client, Device}; use mas_keystore::Keystore; use mas_policy::{EvaluationResult, Policy}; @@ -53,9 +53,9 @@ pub enum RouteError { impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); + let event = sentry::capture_error(&self); // TODO: better error pages - match self { + let response = match self { RouteError::NotFound => { (StatusCode::NOT_FOUND, "authorization grant was not found").into_response() } @@ -67,7 +67,9 @@ impl IntoResponse for RouteError { RouteError::Internal(_) | Self::NoSuchClient => { (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response() } - } + }; + + (SentryEventID::from(event), response).into_response() } } diff --git a/crates/handlers/src/oauth2/authorization/mod.rs b/crates/handlers/src/oauth2/authorization/mod.rs index 1cef1ac4..0df067dd 100644 --- a/crates/handlers/src/oauth2/authorization/mod.rs +++ b/crates/handlers/src/oauth2/authorization/mod.rs @@ -17,7 +17,7 @@ use axum::{ response::{Html, IntoResponse, Response}, }; use hyper::StatusCode; -use mas_axum_utils::{cookies::CookieJar, csrf::CsrfExt, SessionInfoExt}; +use mas_axum_utils::{cookies::CookieJar, csrf::CsrfExt, sentry::SentryEventID, SessionInfoExt}; use mas_data_model::{AuthorizationCode, Pkce}; use mas_keystore::Keystore; use mas_policy::Policy; @@ -64,9 +64,9 @@ pub enum RouteError { impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); + let event_id = sentry::capture_error(&self); // TODO: better error pages - match self { + let response = match self { RouteError::Internal(e) => { (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response() } @@ -84,7 +84,9 @@ impl IntoResponse for RouteError { format!("Invalid redirect URI ({e})"), ) .into_response(), - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/oauth2/consent.rs b/crates/handlers/src/oauth2/consent.rs index c448923a..5c5a474e 100644 --- a/crates/handlers/src/oauth2/consent.rs +++ b/crates/handlers/src/oauth2/consent.rs @@ -20,6 +20,7 @@ use hyper::StatusCode; use mas_axum_utils::{ cookies::CookieJar, csrf::{CsrfExt, ProtectedForm}, + sentry::SentryEventID, SessionInfoExt, }; use mas_data_model::{AuthorizationGrantStage, Device}; @@ -63,8 +64,12 @@ impl_from_error_for_route!(mas_policy::EvaluationError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - StatusCode::INTERNAL_SERVER_ERROR.into_response() + let event_id = sentry::capture_error(&self); + ( + SentryEventID::from(event_id), + StatusCode::INTERNAL_SERVER_ERROR, + ) + .into_response() } } diff --git a/crates/handlers/src/oauth2/introspection.rs b/crates/handlers/src/oauth2/introspection.rs index 83cf9d38..8a597367 100644 --- a/crates/handlers/src/oauth2/introspection.rs +++ b/crates/handlers/src/oauth2/introspection.rs @@ -17,6 +17,7 @@ use hyper::StatusCode; use mas_axum_utils::{ client_authorization::{ClientAuthorization, CredentialsVerificationError}, http_client_factory::HttpClientFactory, + sentry::SentryEventID, }; use mas_data_model::{TokenFormatError, TokenType, User}; use mas_iana::oauth::{OAuthClientAuthenticationMethod, OAuthTokenTypeHint}; @@ -59,8 +60,8 @@ pub enum RouteError { impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(e) => ( StatusCode::INTERNAL_SERVER_ERROR, Json( @@ -92,7 +93,9 @@ impl IntoResponse for RouteError { Json(ClientError::from(ClientErrorCode::InvalidRequest)), ) .into_response(), - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/oauth2/registration.rs b/crates/handlers/src/oauth2/registration.rs index 99cefc7a..55cc2614 100644 --- a/crates/handlers/src/oauth2/registration.rs +++ b/crates/handlers/src/oauth2/registration.rs @@ -14,6 +14,7 @@ use axum::{extract::State, response::IntoResponse, Json}; use hyper::StatusCode; +use mas_axum_utils::sentry::SentryEventID; use mas_iana::oauth::OAuthClientAuthenticationMethod; use mas_keystore::Encrypter; use mas_policy::{Policy, Violation}; @@ -52,8 +53,8 @@ impl_from_error_for_route!(mas_keystore::aead::Error); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(_) => ( StatusCode::INTERNAL_SERVER_ERROR, Json(ClientError::from(ClientErrorCode::ServerError)), @@ -124,7 +125,9 @@ impl IntoResponse for RouteError { ) .into_response() } - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/oauth2/revoke.rs b/crates/handlers/src/oauth2/revoke.rs index c5a591b0..977d0cac 100644 --- a/crates/handlers/src/oauth2/revoke.rs +++ b/crates/handlers/src/oauth2/revoke.rs @@ -17,6 +17,7 @@ use hyper::StatusCode; use mas_axum_utils::{ client_authorization::{ClientAuthorization, CredentialsVerificationError}, http_client_factory::HttpClientFactory, + sentry::SentryEventID, }; use mas_data_model::{Device, TokenType}; use mas_iana::oauth::OAuthTokenTypeHint; @@ -62,8 +63,8 @@ pub(crate) enum RouteError { impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(_) => ( StatusCode::INTERNAL_SERVER_ERROR, Json(ClientError::from(ClientErrorCode::ServerError)), @@ -96,7 +97,9 @@ impl IntoResponse for RouteError { // If the token is unknown, we still return a 200 OK response. Self::UnknownToken => StatusCode::OK.into_response(), - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/oauth2/token.rs b/crates/handlers/src/oauth2/token.rs index f68d1d92..555fb698 100644 --- a/crates/handlers/src/oauth2/token.rs +++ b/crates/handlers/src/oauth2/token.rs @@ -19,6 +19,7 @@ use hyper::StatusCode; use mas_axum_utils::{ client_authorization::{ClientAuthorization, CredentialsVerificationError}, http_client_factory::HttpClientFactory, + sentry::SentryEventID, }; use mas_data_model::{AuthorizationGrantStage, Client, Device, TokenType}; use mas_keystore::{Encrypter, Keystore}; @@ -113,8 +114,9 @@ pub(crate) enum RouteError { impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + + let response = match self { Self::Internal(_) | Self::NoSuchBrowserSession | Self::NoSuchOAuthSession => ( StatusCode::INTERNAL_SERVER_ERROR, Json(ClientError::from(ClientErrorCode::ServerError)), @@ -158,8 +160,9 @@ impl IntoResponse for RouteError { StatusCode::BAD_REQUEST, Json(ClientError::from(ClientErrorCode::UnsupportedGrantType)), ), - } - .into_response() + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/oauth2/userinfo.rs b/crates/handlers/src/oauth2/userinfo.rs index dbd8370e..6f619979 100644 --- a/crates/handlers/src/oauth2/userinfo.rs +++ b/crates/handlers/src/oauth2/userinfo.rs @@ -20,6 +20,7 @@ use axum::{ use hyper::StatusCode; use mas_axum_utils::{ jwt::JwtResponse, + sentry::SentryEventID, user_authorization::{AuthorizationVerificationError, UserAuthorization}, }; use mas_jose::{ @@ -84,15 +85,17 @@ impl_from_error_for_route!(mas_jose::jwt::JwtSignatureError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::Internal(_) | Self::InvalidSigningKey | Self::NoSuchClient | Self::NoSuchUser => { (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()).into_response() } Self::AuthorizationVerificationError(_) | Self::Unauthorized => { StatusCode::UNAUTHORIZED.into_response() } - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/upstream_oauth2/authorize.rs b/crates/handlers/src/upstream_oauth2/authorize.rs index 09ca2635..abf40513 100644 --- a/crates/handlers/src/upstream_oauth2/authorize.rs +++ b/crates/handlers/src/upstream_oauth2/authorize.rs @@ -17,7 +17,9 @@ use axum::{ response::{IntoResponse, Redirect}, }; use hyper::StatusCode; -use mas_axum_utils::{cookies::CookieJar, http_client_factory::HttpClientFactory}; +use mas_axum_utils::{ + cookies::CookieJar, http_client_factory::HttpClientFactory, sentry::SentryEventID, +}; use mas_oidc_client::requests::authorization_code::AuthorizationRequestData; use mas_router::UrlBuilder; use mas_storage::{ @@ -49,11 +51,13 @@ impl_from_error_for_route!(mas_storage::RepositoryError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::ProviderNotFound => (StatusCode::NOT_FOUND, "Provider not found").into_response(), Self::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/upstream_oauth2/callback.rs b/crates/handlers/src/upstream_oauth2/callback.rs index 5a32f949..58129712 100644 --- a/crates/handlers/src/upstream_oauth2/callback.rs +++ b/crates/handlers/src/upstream_oauth2/callback.rs @@ -17,7 +17,9 @@ use axum::{ response::IntoResponse, }; use hyper::StatusCode; -use mas_axum_utils::{cookies::CookieJar, http_client_factory::HttpClientFactory}; +use mas_axum_utils::{ + cookies::CookieJar, http_client_factory::HttpClientFactory, sentry::SentryEventID, +}; use mas_jose::claims::ClaimError; use mas_keystore::{Encrypter, Keystore}; use mas_oidc_client::requests::{ @@ -107,13 +109,15 @@ impl_from_error_for_route!(super::cookie::UpstreamSessionNotFound); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::ProviderNotFound => (StatusCode::NOT_FOUND, "Provider not found").into_response(), Self::SessionNotFound => (StatusCode::NOT_FOUND, "Session not found").into_response(), Self::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), e => (StatusCode::BAD_REQUEST, e.to_string()).into_response(), - } + }; + + (SentryEventID::from(event_id), response).into_response() } } diff --git a/crates/handlers/src/upstream_oauth2/link.rs b/crates/handlers/src/upstream_oauth2/link.rs index 9464960f..c8fa1052 100644 --- a/crates/handlers/src/upstream_oauth2/link.rs +++ b/crates/handlers/src/upstream_oauth2/link.rs @@ -21,6 +21,7 @@ use hyper::StatusCode; use mas_axum_utils::{ cookies::CookieJar, csrf::{CsrfExt, ProtectedForm}, + sentry::SentryEventID, FancyError, SessionInfoExt, }; use mas_data_model::{UpstreamOAuthProviderImportPreference, User}; @@ -96,8 +97,8 @@ impl_from_error_for_route!(mas_jose::jwt::JwtDecodeError); impl IntoResponse for RouteError { fn into_response(self) -> axum::response::Response { - sentry::capture_error(&self); - match self { + let event_id = sentry::capture_error(&self); + let response = match self { Self::LinkNotFound => (StatusCode::NOT_FOUND, "Link not found").into_response(), Self::PolicyViolation { violations } => { let details = violations.iter().map(|v| v.msg.clone()).collect::>(); @@ -111,7 +112,9 @@ impl IntoResponse for RouteError { } Self::Internal(e) => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), e => (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()).into_response(), - } + }; + + (SentryEventID::from(event_id), response).into_response() } }