Skip to content

feat(web-vitals): Emit web-vitals as metrics#6118

Draft
klochek wants to merge 2 commits into
masterfrom
christopherklochek/ingest-962-implement-double-writes-for-web-vitals
Draft

feat(web-vitals): Emit web-vitals as metrics#6118
klochek wants to merge 2 commits into
masterfrom
christopherklochek/ingest-962-implement-double-writes-for-web-vitals

Conversation

@klochek

@klochek klochek commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

No description provided.

@linear-code

linear-code Bot commented Jun 23, 2026

Copy link
Copy Markdown

INGEST-962

Comment thread relay-server/src/services/store.rs Outdated
Ok(())
}

fn produce_web_vital_metrics(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we should do these things now-a-days in the respective Forward::forward_store implementation of the processing pipeline.
Even if that means we need a separate story for transactions and spans atm.

@jjbayer wdyt?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah IMO we should put data type specifics into the processing pipeline as much as possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

moved

Comment on lines +20 to +21
pub(crate) mod store;
pub(crate) mod utils;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These should stay private, if we have to change visibility (especially scoped visibility) it's usually a sign of bad code organization.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done--but more generally, even pub(crate)?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'd try to avoid it, generally it can either be public or not, with a good module hierarchy it's generally not necessary (as child modules can access private modules of parents).

In this case I am a bit behind it, because I want every processor to be independent and avoid having processor start sharing code that isn't explicitly moved into a shared component, that was a big mistake of the old processing code.

Comment thread relay-server/src/services/store.rs Outdated
Comment thread tests/integration/test_webvital_metrics.py Outdated
Comment thread relay-server/src/services/store.rs Outdated
name: "browser.web_vital.lcp.value",
unit: MetricUnit::Duration(relay_metrics::DurationUnit::MilliSecond),
attribute_keys: &[
"browser.web_vital.lcp.value",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think these are missing the performance scores?

Comment thread relay-server/src/services/store.rs Outdated
name: "browser.web_vital.cls.value",
unit: MetricUnit::None,
attribute_keys: &[
"browser.web_vital.cls.value",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is attribute_value always also part of attribute_keys? In that case I would rename attribute_keys to something like additional_attributes and omit the value-holding attribute from it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

On second inspection, why do we add the metric value as an attribute? Isn't that redundant?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I'll be double-checking with the web-vitals folks about this, but this is as outlined in their rfc.

Comment thread relay-server/src/services/store.rs Outdated
name: web_vital.name.to_owned().into(),
ty: relay_event_schema::protocol::MetricType::Distribution.into(),
unit: web_vital.unit.into(),
value: Value::F64(value.as_f64().unwrap_or(0.0)).into(),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If the value is not a number, I would rather not emit a metric here at all. This is basically a product question: how do we want to surface unexpected data to the user? IMO silent failure is better than sending 0.0 because the latter skews the average, etc.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fair enough, I've moved it to filter it--I'll add some logging in case we see it in the wild

Comment thread relay-server/src/services/store.rs Outdated
Ok(())
}

fn produce_web_vital_metrics(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah IMO we should put data type specifics into the processing pipeline as much as possible.

Comment thread relay-server/src/services/store.rs Outdated
};

message.try_accept(|span| {
self.produce_web_vital_metrics(scoping, received_at, &span)?;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this call need to be guarded by a global option or feature flag in any way?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, it should--once I've got the rest of the pinned down.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants