diff --git a/relay-cogs/src/lib.rs b/relay-cogs/src/lib.rs index 8e04c7cf029..7b17f0c9d7c 100644 --- a/relay-cogs/src/lib.rs +++ b/relay-cogs/src/lib.rs @@ -71,6 +71,8 @@ mod test; pub(crate) mod time; +use std::fmt; + pub use self::cogs::*; pub use self::recorder::*; #[cfg(test)] @@ -237,9 +239,27 @@ pub struct CogsMeasurement { pub value: Value, } +impl fmt::Display for CogsMeasurement { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}@{}", self.resource, self.feature.as_str())?; + if let Some(category) = self.category { + write!(f, "[{category}]")?; + } + write!(f, "={}", self.value) + } +} + /// A COGS measurement value. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Value { /// A time measurement. Time(std::time::Duration), } + +impl fmt::Display for Value { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Time(duration) => write!(f, "{duration:?}"), + } + } +} diff --git a/relay-server/src/envelope/item.rs b/relay-server/src/envelope/item.rs index af6da5a5056..b5b6c239af2 100644 --- a/relay-server/src/envelope/item.rs +++ b/relay-server/src/envelope/item.rs @@ -1094,7 +1094,7 @@ pub enum ItemHeaderKey { #[serde(transparent)] pub struct ItemHeaderValue(serde_json::Value); -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize)] pub struct ItemHeaders { /// The type of the item. #[serde(rename = "type")] @@ -1183,6 +1183,61 @@ impl ItemHeaders { } } +impl fmt::Debug for ItemHeaders { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + ty, + stored_key, + routing_hint, + rate_limited, + source_quantities, + inner, + } = self; + + let mut map = f.debug_map(); + + map.entry(&"type", &ty); + if let Some(stored_key) = stored_key { + map.entry(&"stored_key", stored_key); + } + if let Some(routing_hint) = routing_hint { + map.entry(&"routing_hint", routing_hint); + } + if *rate_limited { + map.entry(&"rate_limited", rate_limited); + } + if let Some(source_quantities) = source_quantities { + map.entry(&"source_quantities", source_quantities); + } + + for (k, v) in inner { + match k { + MaybeKnown::Known(v) => map.key(&v), + MaybeKnown::Unknown(s) => map.key(&s), + }; + + match &v.0 { + serde_json::Value::Null => map.value(&"null"), + serde_json::Value::Bool(b) => map.value(&b), + serde_json::Value::Number(number) => { + if let Some(n) = number.as_u128() { + map.value(&n) + } else if let Some(n) = number.as_f64() { + map.value(&n) + } else { + map.value(&number) + } + } + serde_json::Value::String(s) => map.value(&s), + v @ serde_json::Value::Array(_) => map.value(&v), + v @ serde_json::Value::Object(_) => map.value(&v), + }; + } + + map.finish() + } +} + /// An item key which is potentially known to Relay. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Deserialize, Serialize)] #[serde(untagged)] @@ -1389,29 +1444,11 @@ mod tests { .unwrap(); insta::assert_debug_snapshot!(&item.headers, @r#" - ItemHeaders { - ty: Attachment, - stored_key: None, - routing_hint: None, - rate_limited: false, - source_quantities: None, - inner: { - Known( - Length, - ): ItemHeaderValue( - Number(5), - ), - Unknown( - "unknown1", - ): ItemHeaderValue( - String("foo"), - ), - Unknown( - "unknown2", - ): ItemHeaderValue( - String("bar"), - ), - }, + { + "type": Attachment, + Length: 5, + "unknown1": "foo", + "unknown2": "bar", } "#); diff --git a/relay-server/src/envelope/mod.rs b/relay-server/src/envelope/mod.rs index e678e05a5c4..b7822af22d5 100644 --- a/relay-server/src/envelope/mod.rs +++ b/relay-server/src/envelope/mod.rs @@ -33,6 +33,7 @@ use relay_base_schema::project::ProjectKey; use std::borrow::Borrow; use std::collections::BTreeMap; +use std::fmt; use std::io::{self, Write}; use std::time::Duration; @@ -82,7 +83,7 @@ pub enum EnvelopeError { PayloadIoFailed(#[source] io::Error), } -#[derive(Clone, Debug, Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize)] pub struct EnvelopeHeaders { /// Unique identifier of the event associated to this envelope. /// @@ -221,6 +222,51 @@ impl EnvelopeHeaders { } } +impl fmt::Debug for EnvelopeHeaders +where + M: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + event_id, + meta, + retention, + downsampled_retention, + sent_at, + trace, + required_features, + other, + } = self; + + let mut map = f.debug_map(); + + if let Some(event_id) = event_id { + map.entry(&"event_id", &event_id.0); + } + map.entry(&"meta", &meta); + if let Some(retention) = retention { + map.entry(&"retention", retention); + } + if let Some(downsampled_retention) = downsampled_retention { + map.entry(&"downsampled_retention", downsampled_retention); + } + if let Some(sent_at) = sent_at { + map.entry(&"sent_at", sent_at); + } + if let Some(trace) = trace { + map.entry(&"trace", trace); + } + if !required_features.is_empty() { + map.entry(&"required_features", required_features); + } + for (key, value) in other { + map.entry(key, value); + } + + map.finish() + } +} + #[doc(hidden)] #[derive(Clone, Debug)] pub struct Envelope { diff --git a/relay-server/src/extractors/request_meta.rs b/relay-server/src/extractors/request_meta.rs index 69fa598d660..1243a0da307 100644 --- a/relay-server/src/extractors/request_meta.rs +++ b/relay-server/src/extractors/request_meta.rs @@ -86,7 +86,7 @@ impl IntoResponse for BadEventMeta { /// /// This type caches the parsed project key in addition to the DSN. Other than that, it /// transparently serializes to and deserializes from a DSN string. -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Clone, Eq, PartialEq)] pub struct PartialDsn { pub scheme: Scheme, pub public_key: ProjectKey, @@ -154,6 +154,12 @@ impl fmt::Display for PartialDsn { } } +impl fmt::Debug for PartialDsn { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{self}") + } +} + impl FromStr for PartialDsn { type Err = ParseDsnError; @@ -194,7 +200,7 @@ fn make_false() -> bool { } /// Request information for sentry ingest data, such as events, envelopes or metrics. -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[derive(Clone, Serialize, Deserialize, PartialEq)] pub struct RequestMeta { /// The DSN describing the target of this envelope. dsn: D, @@ -425,6 +431,65 @@ impl RequestMeta { } } +impl fmt::Debug for RequestMeta +where + D: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let Self { + dsn, + client, + version, + origin, + remote_addr, + forwarded_for, + user_agent, + client_hints, + no_cache, + received_at, + signature, + request_trust, + } = self; + + let mut map = f.debug_map(); + + map.entry(&"dsn", &dsn); + + if let Some(client) = client { + map.entry(&"client", client); + } + map.entry(&"version", version); + + if let Some(origin) = origin { + map.entry(&"origin", origin); + } + if let Some(remote_addr) = remote_addr { + map.entry(&"remote_addr", remote_addr); + } + if !forwarded_for.is_empty() { + map.entry(&"forwarded_for", forwarded_for); + } + if let Some(user_agent) = user_agent { + map.entry(&"user_agent", user_agent); + } + if !client_hints.is_empty() { + map.entry(&"client_hints", client_hints); + } + if *no_cache { + map.entry(&"no_cache", no_cache); + } + map.entry(&"received_at", received_at); + if let Some(signature) = signature { + map.entry(&"signature", signature); + } + if let Some(request_trust) = request_trust { + map.entry(&"request_trust", request_trust); + } + + map.finish() + } +} + /// A partial [`Scoping`]. /// /// The scoping may not be complete and missing information compared to a full scoping. diff --git a/relay-server/src/services/cogs.rs b/relay-server/src/services/cogs.rs index fdf5ac7f593..392377e459b 100644 --- a/relay-server/src/services/cogs.rs +++ b/relay-server/src/services/cogs.rs @@ -31,7 +31,7 @@ impl CogsService { } fn handle_report(&mut self, CogsReport(measurement): CogsReport) { - relay_log::trace!("recording measurement: {measurement:?}"); + relay_log::trace!("recording measurement: {measurement}"); let resource_id = match measurement.resource { ResourceId::Relay => &self.relay_resource_id,