· 5 min read

Integrating Sentry's Web Vitals into Slack

This article was auto-translated from Chinese. Some nuances may be lost in translation.

Introduction

Web Vitals is an initiative by Google aimed at providing various metrics to quantify website performance. Previously, the Google Chrome Developers channel published a video introducing Core Web Vitals in Taiwanese Hokkien—the examples were super fun, and I highly recommend checking it out ↓

Nowadays, many websites implement workflows to measure Web Vitals, using quantified metrics to find areas for improvement. Currently, quite a few tools help developers measure Web Vitals, such as:

  • Lighthouse
  • PageSpeed Insights
  • CrUX
  • Search Console

Sentry’s Web Vitals Analytics Feature

However, fewer people might know that Sentry previously introduced a Web Vitals analytics feature1. It tracks various Web Vitals metrics such as LCP, FP, and CLS, allowing developers to view related charts in the dashboard and even conveniently marking the averages for you—very thoughtful.

sentry web vitals

However, Sentry only seems to retain data for 30 days, and it lacks comparison features—such as comparing last week’s metrics against this week’s metrics. Moreover, charts can only be viewed inside Sentry, which introduces context-switching overhead for other teams. As developers, it’s only natural to want to automate this entire workflow.

Looking into it further, although Sentry provides API integrations (if you have an API token), there didn’t seem to be any official API documentation for Web Vitals. Out of curiosity, I opened the browser console and found that the charts were actually fetched via an API. After copying the API endpoint and parameters and calling it via cURL, it worked! It turns out it just wasn’t documented.

webvitals related API in sentry

There are two main APIs: (Since they are undocumented, parameters or paths might change over time)

  • /events-measurements-histogram/?...
  • /eventsv2

Designing the Automation Workflow

Now that we have the data, we can integrate it into Slack for scheduled tracking. This also makes it easy to share with other teams, while anyone needing deeper details can jump directly into Sentry’s dashboard. Here is how the workflow looks:

automation flow

A cron job calls the API (or you could implement it via serverless functions), fetches the data from Sentry, uploads it, and generates a report.

One thing to watch out for is the presence of + in the query parameters. If passed directly to encodeURIComponent or handled by URLSearchParams, it becomes %2B, which triggers an error on Sentry’s side. You’ll need to handle the + separately or ensure it doesn’t get encoded.

For example, the API’s query parameter looks like this: field=percentile(measurements.fp%2C+0.75)&field=percentile(measurements.fcp%2C+0.75)&.... You can define the data to return using a function-call-like syntax; for instance, percentile(measurements.fp,+0.75) returns the 75th percentile of FP data (the unit should be milliseconds). Notice that while , is encoded as %2C, the + is not encoded. If you encounter errors when building query parameters, this is a good place to start debugging.

The returned data structure looks like this:

{
  "path": "/my-page",
  "data": [
    {
      "count": 10,
      "bin": 2000
    },
    ...
  ]
}

Next, simply generate a .json file and upload it to S3 (or any other storage service). This allows you to compare it against yesterday’s (or earlier) data, generate a report, and send it to Slack:

slack report example

Additionally, if you want to generate chart images, you can use chart.js and chartjs-node-canvas in Node.js. This allows you to render charts without running a browser (canvas). The only caveat is that if the corresponding fonts are not installed on the server, the layout might break or the font rendering might look distorted.

report image example

Regarding the choice of cron job runner: while there are many mature solutions available today—even hardcoding a crontab on a server works—we used the cron job feature in Drone CI. The main reason is that Drone’s configuration syntax is very straightforward, we have dedicated Drone CI servers internally, and company policies restrict using arbitrary external services. Integrating with Drone CI was the simplest approach to keep setup easy.

However, for reasons unknown, every time a cron event triggered, other pipelines would also run. So I ended up creating a separate branch with an adjusted .yaml to trigger the API:

steps:
  - name: upload and report
    image: byrnedo/alpine-curl
    commands:
      - curl -X POST YOUR_SERVER_ENDPOINT

And that completes the entire automation workflow! Now reports are posted to Slack daily, making it much easier for developers to track changes and see feedback.

Footnotes

  1. https://sentry.io/for/web-vitals ↩

Related Posts

Explore Other Topics