Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
**Features**:

- Apply clock drift correction to logs and trace metrics. ([#5609](https://github.com/getsentry/relay/pull/5609))
- Add Culture context to event schema. ([#5615](https://github.com/getsentry/relay/pull/5615))

**Internal**:

Expand Down
110 changes: 110 additions & 0 deletions relay-event-schema/src/protocol/contexts/culture.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
use relay_protocol::{Annotated, Empty, FromValue, IntoValue, Object, Value};

use crate::processor::ProcessValue;

/// Culture information.
///
/// Culture context describes the cultural properties relevant to how software is used
/// in specific regions or locales.
#[derive(Clone, Debug, Default, PartialEq, Empty, FromValue, IntoValue, ProcessValue)]
pub struct CultureContext {
/// The calendar system in use.
///
/// For example, `GregorianCalendar`.
#[metastructure(pii = "maybe")]
pub calendar: Annotated<String>,

/// Human-readable name of the culture.
///
/// For example, `English (United States)`.
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The display_name field should be marked with #[metastructure(pii = "maybe")] annotation. This field contains human-readable locale information (e.g., "English (United States)") which can reveal user location and preferences, similar to other locale-related fields that are marked as potentially containing PII.

Suggested change
/// For example, `English (United States)`.
/// For example, `English (United States)`.
#[metastructure(pii = "maybe")]

Copilot uses AI. Check for mistakes.
#[metastructure(pii = "maybe")]
pub display_name: Annotated<String>,

/// The name identifier, usually following the RFC 4646.
///
/// For example, `en-US` or `pt-BR`.
#[metastructure(pii = "maybe")]
pub locale: Annotated<String>,

/// Whether the locale uses 24-hour time format.
#[metastructure(pii = "maybe")]
pub is_24_hour_format: Annotated<bool>,

/// The timezone of the locale.
///
/// For example, `Europe/Vienna`.
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The timezone field should be marked with #[metastructure(pii = "maybe")] annotation. This field can potentially contain personally identifiable information similar to how the timezone field in DeviceContext is marked (see relay-event-schema/src/protocol/contexts/device.rs:118-120). Timezone information can reveal user location.

Suggested change
/// For example, `Europe/Vienna`.
/// For example, `Europe/Vienna`.
#[metastructure(pii = "maybe")]

Copilot uses AI. Check for mistakes.
#[metastructure(pii = "maybe")]
pub timezone: Annotated<String>,

/// Additional arbitrary fields for forwards compatibility.
#[metastructure(additional_properties, retain = true, pii = "maybe")]
pub other: Object<Value>,
}

impl super::DefaultContext for CultureContext {
fn default_key() -> &'static str {
"culture"
}

fn from_context(context: super::Context) -> Option<Self> {
match context {
super::Context::Culture(c) => Some(*c),
_ => None,
}
}

fn cast(context: &super::Context) -> Option<&Self> {
match context {
super::Context::Culture(c) => Some(c),
_ => None,
}
}

fn cast_mut(context: &mut super::Context) -> Option<&mut Self> {
match context {
super::Context::Culture(c) => Some(c),
_ => None,
}
}

fn into_context(self) -> super::Context {
super::Context::Culture(Box::new(self))
}
}

#[cfg(test)]
mod tests {
use super::*;
use crate::protocol::Context;

#[test]
fn test_culture_context_roundtrip() {
let json = r#"{
"calendar": "GregorianCalendar",
"display_name": "English (United States)",
"locale": "en-US",
"is_24_hour_format": false,
"timezone": "Europe/Vienna",
"other": "value",
"type": "culture"
}"#;
let context = Annotated::new(Context::Culture(Box::new(CultureContext {
calendar: Annotated::new("GregorianCalendar".to_owned()),
display_name: Annotated::new("English (United States)".to_owned()),
locale: Annotated::new("en-US".to_owned()),
is_24_hour_format: Annotated::new(false),
timezone: Annotated::new("Europe/Vienna".to_owned()),
other: {
let mut map = Object::new();
map.insert(
"other".to_owned(),
Annotated::new(Value::String("value".to_owned())),
);
map
},
})));

assert_eq!(context, Annotated::from_json(json).unwrap());
assert_eq!(json, context.to_json_pretty().unwrap());
}
}
4 changes: 4 additions & 0 deletions relay-event-schema/src/protocol/contexts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ mod app;
mod browser;
mod chromium_stability_report;
mod cloud_resource;
mod culture;
mod device;
mod flags;
mod gpu;
Expand All @@ -26,6 +27,7 @@ pub use app::*;
pub use browser::*;
pub use chromium_stability_report::*;
pub use cloud_resource::*;
pub use culture::*;
pub use device::*;
pub use gpu::*;
pub use memory_info::*;
Expand Down Expand Up @@ -101,6 +103,8 @@ pub enum Context {
Otel(Box<OtelContext>),
/// Cloud resource information.
CloudResource(Box<CloudResourceContext>),
/// Culture information.
Culture(Box<CultureContext>),
/// Nel information.
Nel(Box<NelContext>),
/// Performance score information.
Expand Down
Loading