Skip to content

Commit 86bafc5

Browse files
authored
feat(metrics): Always extract distinct_id (#1275)
The javascript SDK apparently does not always send a session.distinct_id with the initial session update, but only on subsequent updates. To make sure we count those users as well, extract them under the tag session.status=ok. We will need to update queries in sentry to include these users.
1 parent 14a9d33 commit 86bafc5

File tree

2 files changed

+34
-4
lines changed

2 files changed

+34
-4
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
**Compatibility:** This version of Relay requires Sentry server `22.6.0` or newer.
66

7-
**Features**:
7+
**Bug Fixes**:
8+
9+
- Session metrics extraction: Count distinct_ids from all session updates to prevent undercounting users. ([#1275](https://github.com/getsentry/relay/pull/1275))
810

911
- Session metrics extraction: Count crashed+abnormal towards errored_preaggr. ([#1274](https://github.com/getsentry/relay/pull/1274))
1012

relay-server/src/metrics_extraction/sessions.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,25 @@ pub fn extract_session_metrics<T: SessionLike>(
197197
with_tag(&tags, "session.status", status),
198198
));
199199
}
200+
201+
// Some SDKs only provide user information on subsequent updates (not when init==true), so
202+
// collect the user ID here as well.
203+
// We could also add the user ID to the "init" tag, but collecting it under a separate "ok" tag
204+
// might help us with validation / debugging.
205+
if let Some(distinct_id) = nil_to_none(session.distinct_id()) {
206+
if session.total_count() == 0 && session.all_errors().is_none() {
207+
// Assuming that aggregate items always have a total_count > 0,
208+
// this is a session update to a healthy, individual session (init == false).
209+
target.push(Metric::new_mri(
210+
METRIC_NAMESPACE,
211+
"user",
212+
MetricUnit::None,
213+
MetricValue::set_from_str(distinct_id),
214+
timestamp,
215+
with_tag(&tags, "session.status", SessionStatus::Ok),
216+
));
217+
}
218+
}
200219
}
201220

202221
#[cfg(test)]
@@ -292,8 +311,12 @@ mod tests {
292311

293312
extract_session_metrics(&session.attributes, &session, None, &mut metrics);
294313

295-
// A none-initial update will not trigger any metric if it's not errored/crashed
296-
assert_eq!(metrics.len(), 0);
314+
// A none-initial update which is not errored/crashed/abnormal will only emit a user metric.
315+
assert_eq!(metrics.len(), 1);
316+
let user_metric = &metrics[0];
317+
assert_eq!(user_metric.name, "s:sessions/user@none");
318+
assert!(matches!(user_metric.value, MetricValue::Set(_)));
319+
assert_eq!(user_metric.tags["session.status"], "ok");
297320
}
298321

299322
#[test]
@@ -406,14 +429,19 @@ mod tests {
406429

407430
extract_session_metrics(&session.attributes, &session, None, &mut metrics);
408431

409-
assert_eq!(metrics.len(), 1);
432+
assert_eq!(metrics.len(), 2); // duration and user ID
410433

411434
let duration_metric = &metrics[0];
412435
assert_eq!(duration_metric.name, "d:sessions/duration@second");
413436
assert!(matches!(
414437
duration_metric.value,
415438
MetricValue::Distribution(_)
416439
));
440+
441+
let user_metric = &metrics[1];
442+
assert_eq!(user_metric.name, "s:sessions/user@none");
443+
assert!(matches!(user_metric.value, MetricValue::Set(_)));
444+
assert_eq!(user_metric.tags["session.status"], "ok");
417445
}
418446

419447
#[test]

0 commit comments

Comments
 (0)