Skip to content

Commit 9a3a2a4

Browse files
authored
Merge branch 'master' into dav1d/rate-before-card
2 parents 2733076 + 23a48f2 commit 9a3a2a4

24 files changed

+243
-234
lines changed

.github/workflows/build_library.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
7070
- uses: actions/setup-python@v5
7171
with:
72-
python-version: '3.10'
72+
python-version: '3.11'
7373

7474
- name: Build Wheel
7575
run: |
@@ -96,7 +96,7 @@ jobs:
9696

9797
- uses: actions/setup-python@v5
9898
with:
99-
python-version: '3.10'
99+
python-version: '3.11'
100100

101101
- name: Build sdist
102102
run: python setup.py sdist --format=zip

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434

3535
- uses: actions/setup-python@v5
3636
with:
37-
python-version: "3.10"
37+
python-version: "3.11"
3838

3939
- name: Install Rust Toolchain
4040
run: rustup toolchain install stable --profile minimal --component clippy rustfmt rust-docs --no-self-update
@@ -145,7 +145,7 @@ jobs:
145145
strategy:
146146
fail-fast: false
147147
matrix:
148-
python-version: ["3.10"]
148+
python-version: ["3.11"]
149149

150150
# Skip redundant checks for binary releases
151151
if: "!startsWith(github.ref, 'refs/heads/release/')"
@@ -539,7 +539,7 @@ jobs:
539539

540540
- uses: actions/setup-python@v5
541541
with:
542-
python-version: "3.10"
542+
python-version: "3.11"
543543

544544
- run: make test-integration
545545
env:

.python-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.10.13
1+
3.11.9

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
**Bug fixes:**
1010

1111
- Properly handle AI metrics from the Python SDK's `@ai_track` decorator ([#3539](https://github.com/getsentry/relay/pull/3539))
12+
- Mitigates occasional slowness and timeouts of the healthcheck endpoint. The endpoint will now respond promptly an unhealthy state. ([#3567](https://github.com/getsentry/relay/pull/3567))
1213

1314
**Internal**:
1415

@@ -21,6 +22,7 @@
2122
- Emit negative outcomes for denied metrics. ([#3508](https://github.com/getsentry/relay/pull/3508))
2223
- Increase size limits for internal batch endpoints. ([#3562](https://github.com/getsentry/relay/pull/3562))
2324
- Emit negative outcomes when metrics are rejected because of a disabled namespace. ([#3544](https://github.com/getsentry/relay/pull/3544))
25+
- Add support for `event.` in the `Span` `Getter` implementation. ([#3577](https://github.com/getsentry/relay/pull/3577))
2426

2527
## 24.4.2
2628

py/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
### Unreleased
4+
5+
- This release requires Python 3.11 or later. There are no intentionally breaking changes included in this release, but we stopped testing against Python 3.10.
6+
37
## 0.8.61
48

59
- Update data category metirc hours to metric seconds. [#3558](https://github.com/getsentry/relay/pull/3558)

py/setup.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@ def find_dylib():
113113
package_data={"sentry_relay": ["py.typed", "_lowlevel.pyi"]},
114114
zip_safe=False,
115115
platforms="any",
116-
python_requires=">=3.10",
116+
python_requires=">=3.11",
117117
install_requires=["milksnake>=0.1.6"],
118118
setup_requires=["milksnake>=0.1.6"],
119119
milksnake_tasks=[build_native],
120-
cmdclass={"sdist": CustomSDist},
120+
cmdclass={"sdist": CustomSDist}, # type: ignore
121121
)

relay-config/src/config.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -1329,10 +1329,13 @@ impl Default for CardinalityLimiter {
13291329
#[derive(Serialize, Deserialize, Debug)]
13301330
#[serde(default)]
13311331
pub struct Health {
1332-
/// Interval in which Relay will refresh system information, like current memory usage.
1332+
/// Interval to refresh internal health checks.
13331333
///
1334-
/// Defaults to 3 seconds.
1335-
pub sys_info_refresh_interval_secs: u64,
1334+
/// Shorter intervals will decrease the time it takes the health check endpoint to report
1335+
/// issues, but can also increase sporadic unhealthy responses.
1336+
///
1337+
/// Defaults to `3000`` (3 seconds).
1338+
pub refresh_interval_ms: u64,
13361339
/// Maximum memory watermark in bytes.
13371340
///
13381341
/// By default there is no absolute limit set and the watermark
@@ -1354,7 +1357,7 @@ pub struct Health {
13541357
impl Default for Health {
13551358
fn default() -> Self {
13561359
Self {
1357-
sys_info_refresh_interval_secs: 3,
1360+
refresh_interval_ms: 3000,
13581361
max_memory_bytes: None,
13591362
max_memory_percent: 0.95,
13601363
probe_timeout_ms: 900,
@@ -2272,9 +2275,9 @@ impl Config {
22722275
Duration::from_secs(self.values.cardinality_limiter.cache_vacuum_interval)
22732276
}
22742277

2275-
/// Interval to refresh system information.
2276-
pub fn health_sys_info_refresh_interval(&self) -> Duration {
2277-
Duration::from_secs(self.values.health.sys_info_refresh_interval_secs)
2278+
/// Interval to refresh internal health checks.
2279+
pub fn health_refresh_interval(&self) -> Duration {
2280+
Duration::from_millis(self.values.health.refresh_interval_ms)
22782281
}
22792282

22802283
/// Maximum memory watermark in bytes.

relay-event-schema/src/protocol/span.rs

+74-33
Original file line numberDiff line numberDiff line change
@@ -111,41 +111,56 @@ pub struct Span {
111111

112112
impl Getter for Span {
113113
fn get_value(&self, path: &str) -> Option<Val<'_>> {
114-
Some(match path.strip_prefix("span.")? {
115-
"exclusive_time" => self.exclusive_time.value()?.into(),
116-
"description" => self.description.as_str()?.into(),
117-
"op" => self.op.as_str()?.into(),
118-
"span_id" => self.span_id.as_str()?.into(),
119-
"parent_span_id" => self.parent_span_id.as_str()?.into(),
120-
"trace_id" => self.trace_id.as_str()?.into(),
121-
"status" => self.status.as_str()?.into(),
122-
"origin" => self.origin.as_str()?.into(),
123-
"duration" => {
124-
let start_timestamp = *self.start_timestamp.value()?;
125-
let timestamp = *self.timestamp.value()?;
126-
relay_common::time::chrono_to_positive_millis(timestamp - start_timestamp).into()
127-
}
128-
"was_transaction" => self.was_transaction.value().unwrap_or(&false).into(),
129-
path => {
130-
if let Some(key) = path.strip_prefix("tags.") {
131-
self.tags.value()?.get(key)?.as_str()?.into()
132-
} else if let Some(key) = path.strip_prefix("data.") {
133-
self.data.value()?.get_value(key)?
134-
} else if let Some(key) = path.strip_prefix("sentry_tags.") {
135-
self.sentry_tags.value()?.get(key)?.as_str()?.into()
136-
} else if let Some(rest) = path.strip_prefix("measurements.") {
137-
let name = rest.strip_suffix(".value")?;
138-
self.measurements
139-
.value()?
140-
.get(name)?
141-
.value()?
142-
.value
143-
.value()?
114+
let span_prefix = path.strip_prefix("span.");
115+
if let Some(span_prefix) = span_prefix {
116+
return Some(match span_prefix {
117+
"exclusive_time" => self.exclusive_time.value()?.into(),
118+
"description" => self.description.as_str()?.into(),
119+
"op" => self.op.as_str()?.into(),
120+
"span_id" => self.span_id.as_str()?.into(),
121+
"parent_span_id" => self.parent_span_id.as_str()?.into(),
122+
"trace_id" => self.trace_id.as_str()?.into(),
123+
"status" => self.status.as_str()?.into(),
124+
"origin" => self.origin.as_str()?.into(),
125+
"duration" => {
126+
let start_timestamp = *self.start_timestamp.value()?;
127+
let timestamp = *self.timestamp.value()?;
128+
relay_common::time::chrono_to_positive_millis(timestamp - start_timestamp)
144129
.into()
145-
} else {
146-
return None;
147130
}
148-
}
131+
"was_transaction" => self.was_transaction.value().unwrap_or(&false).into(),
132+
path => {
133+
if let Some(key) = path.strip_prefix("tags.") {
134+
self.tags.value()?.get(key)?.as_str()?.into()
135+
} else if let Some(key) = path.strip_prefix("data.") {
136+
self.data.value()?.get_value(key)?
137+
} else if let Some(key) = path.strip_prefix("sentry_tags.") {
138+
self.sentry_tags.value()?.get(key)?.as_str()?.into()
139+
} else if let Some(rest) = path.strip_prefix("measurements.") {
140+
let name = rest.strip_suffix(".value")?;
141+
self.measurements
142+
.value()?
143+
.get(name)?
144+
.value()?
145+
.value
146+
.value()?
147+
.into()
148+
} else {
149+
return None;
150+
}
151+
}
152+
});
153+
}
154+
155+
// For backward compatibility with event-based rules, we try to support `event.` fields also
156+
// for a span.
157+
let event_prefix = path.strip_prefix("event.")?;
158+
Some(match event_prefix {
159+
"release" => self.data.value()?.release.as_str()?.into(),
160+
"environment" => self.data.value()?.environment.as_str()?.into(),
161+
"transaction" => self.data.value()?.segment_name.as_str()?.into(),
162+
// TODO: we might want to add additional fields once they are added to the span.
163+
_ => return None,
149164
})
150165
}
151166
}
@@ -513,6 +528,32 @@ mod tests {
513528
assert!(!RuleCondition::eq("span.was_transaction", false).matches(&span));
514529
}
515530

531+
#[test]
532+
fn test_span_fields_as_event() {
533+
let span = Annotated::<Span>::from_json(
534+
r#"{
535+
"data": {
536+
"release": "1.0",
537+
"environment": "prod",
538+
"sentry.segment.name": "/api/endpoint"
539+
}
540+
}"#,
541+
)
542+
.unwrap()
543+
.into_value()
544+
.unwrap();
545+
546+
assert_eq!(span.get_value("event.release"), Some(Val::String("1.0")));
547+
assert_eq!(
548+
span.get_value("event.environment"),
549+
Some(Val::String("prod"))
550+
);
551+
assert_eq!(
552+
span.get_value("event.transaction"),
553+
Some(Val::String("/api/endpoint"))
554+
);
555+
}
556+
516557
#[test]
517558
fn test_span_duration() {
518559
let span = Annotated::<Span>::from_json(

0 commit comments

Comments
 (0)