From de62722b33d829735f3df875af391a9cd29aa130 Mon Sep 17 00:00:00 2001 From: lcian Date: Wed, 30 Jul 2025 14:50:25 +0200 Subject: [PATCH 1/5] feat(types): add Response context --- sentry-types/src/protocol/v7.rs | 27 +++++++++++++++++++ sentry-types/tests/test_protocol_v7.rs | 37 ++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/sentry-types/src/protocol/v7.rs b/sentry-types/src/protocol/v7.rs index ced3bd3e..fa60152c 100644 --- a/sentry-types/src/protocol/v7.rs +++ b/sentry-types/src/protocol/v7.rs @@ -1100,6 +1100,8 @@ pub enum Context { Gpu(Box), /// OpenTelemetry data. Otel(Box), + /// HTTP response data. + Response(Box), /// Generic other context data. #[serde(rename = "unknown")] Other(Map), @@ -1117,6 +1119,7 @@ impl Context { Context::Trace(..) => "trace", Context::Gpu(..) => "gpu", Context::Otel(..) => "otel", + Context::Response(..) => "response", Context::Other(..) => "unknown", } } @@ -1351,6 +1354,29 @@ pub struct OtelContext { pub other: Map, } +/// Holds information about an HTTP response. +#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)] +pub struct ResponseContext { + /// The unparsed cookie values. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub cookies: Option, + /// A map of submitted headers. + /// + /// If a header appears multiple times, it needs to be merged according to the HTTP standard + /// for header merging. Header names are treated case-insensitively by Sentry. + #[serde(default, skip_serializing_if = "Map::is_empty")] + pub headers: Map, + /// The HTTP response status code. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub status_code: Option, + /// The response body size in bytes. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub body_size: Option, + /// Response data in any format that makes sense. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub data: Option, +} + /// Holds the identifier for a Span #[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Hash)] #[serde(try_from = "String", into = "String")] @@ -1501,6 +1527,7 @@ into_context!(Browser, BrowserContext); into_context!(Trace, TraceContext); into_context!(Gpu, GpuContext); into_context!(Otel, OtelContext); +into_context!(Response, ResponseContext); const INFERABLE_CONTEXTS: &[&str] = &[ "device", "os", "runtime", "app", "browser", "trace", "gpu", "otel", diff --git a/sentry-types/tests/test_protocol_v7.rs b/sentry-types/tests/test_protocol_v7.rs index 5638d314..841cf19d 100644 --- a/sentry-types/tests/test_protocol_v7.rs +++ b/sentry-types/tests/test_protocol_v7.rs @@ -1313,6 +1313,43 @@ mod test_contexts { ); } + #[test] + fn test_response_context() { + let event = v7::Event { + event_id: event_id(), + timestamp: event_time(), + contexts: { + let mut m = v7::Map::new(); + m.insert( + "response".into(), + v7::ResponseContext { + status_code: Some(400), + cookies: Some("sessionId=abc123; Path=/; HttpOnly,authToken=xyz789; Secure; SameSite=Strict".into()), + headers: { + let mut hm = v7::Map::new(); + hm.insert("Content-Type".into(), "text/plain".into()); + hm + }, + body_size: Some(1000), + data: Some("lol".into()), + } + .into(), + ); + m + }, + ..Default::default() + }; + + assert_roundtrip(&event); + assert_eq!( + serde_json::to_string(&event).unwrap(), + "{\"event_id\":\"d43e86c96e424a93a4fbda156dd17341\",\"timestamp\":1514103120,\ + \"contexts\":{\"response\":{\"type\":\"response\",\ + \"cookies\":\"sessionId=abc123; Path=/; HttpOnly,authToken=xyz789; Secure; SameSite=Strict\",\ + \"headers\":{\"Content-Type\":\"text/plain\"},\"status_code\":400,\"body_size\":1000,\"data\":\"lol\"}}}" + ); + } + #[test] fn test_renamed_contexts() { let event = v7::Event { From deadc7a8d608844466f3b36d8c84e55bcb5a5af6 Mon Sep 17 00:00:00 2001 From: lcian Date: Wed, 30 Jul 2025 15:16:50 +0200 Subject: [PATCH 2/5] changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8e9b12d..201ccec6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## Unreleased + +## Features + +- feat(core): add Response context ([#874](https://github.com/getsentry/sentry-rust/pull/874)) by @lcian + - The `Response` context can be attached to events, to include information about HTTP responses such as headers, cookies and status code. + ## 0.42.0 ### Features From 28809759671da20075e4ce94fbc4e97ec9a43c8c Mon Sep 17 00:00:00 2001 From: lcian Date: Wed, 30 Jul 2025 15:17:50 +0200 Subject: [PATCH 3/5] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 201ccec6..4c3f58a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ## Features - feat(core): add Response context ([#874](https://github.com/getsentry/sentry-rust/pull/874)) by @lcian - - The `Response` context can be attached to events, to include information about HTTP responses such as headers, cookies and status code. + - The `Response` context can now be attached to events, to include information about HTTP responses such as headers, cookies and status code. ## 0.42.0 From a9d3071b6279773dfcc246d6e29649a473cff698 Mon Sep 17 00:00:00 2001 From: lcian Date: Wed, 30 Jul 2025 15:21:27 +0200 Subject: [PATCH 4/5] improve --- sentry-types/src/protocol/v7.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry-types/src/protocol/v7.rs b/sentry-types/src/protocol/v7.rs index fa60152c..617fd5e8 100644 --- a/sentry-types/src/protocol/v7.rs +++ b/sentry-types/src/protocol/v7.rs @@ -1530,7 +1530,7 @@ into_context!(Otel, OtelContext); into_context!(Response, ResponseContext); const INFERABLE_CONTEXTS: &[&str] = &[ - "device", "os", "runtime", "app", "browser", "trace", "gpu", "otel", + "device", "os", "runtime", "app", "browser", "trace", "gpu", "otel", "response", ]; struct ContextsVisitor; From 1de6b99669d1b05fbe1e44d9214d825967e9a27a Mon Sep 17 00:00:00 2001 From: lcian Date: Mon, 4 Aug 2025 17:58:57 +0200 Subject: [PATCH 5/5] changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c3f58a8..dedcc18d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,20 @@ - feat(core): add Response context ([#874](https://github.com/getsentry/sentry-rust/pull/874)) by @lcian - The `Response` context can now be attached to events, to include information about HTTP responses such as headers, cookies and status code. + - Example: + ```rust + let mut event = Event::new(); + let response = ResponseContext { + cookies: Some(r#""csrftoken": "1234567""#.to_owned()), + headers: Some(headers_map), + status_code: Some(500), + body_size: Some(15), + data: Some("Invalid request"), + }; + event + .contexts + .insert("response".to_owned(), response.into()); + ``` ## 0.42.0