Skip to content

Commit

Permalink
feat: show web vitals average
Browse files Browse the repository at this point in the history
Signed-off-by: David Dal Busco <[email protected]>
  • Loading branch information
peterpeterparker committed Aug 18, 2024
1 parent 5cbfef1 commit 36a4e50
Show file tree
Hide file tree
Showing 13 changed files with 197 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/declarations/orbiter/orbiter.did.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ export interface _SERVICE {
get_page_views_analytics_metrics: ActorMethod<[GetAnalytics], AnalyticsMetricsPageViews>;
get_page_views_analytics_top_10: ActorMethod<[GetAnalytics], AnalyticsTop10PageViews>;
get_performance_metrics: ActorMethod<[GetAnalytics], Array<[AnalyticKey, PerformanceMetric]>>;
get_performance_metrics_web_vitals: ActorMethod<
get_performance_metrics_analytics_web_vitals: ActorMethod<
[GetAnalytics],
AnalyticsWebVitalsPerformanceMetrics
>;
Expand Down
2 changes: 1 addition & 1 deletion src/declarations/orbiter/orbiter.factory.did.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export const idlFactory = ({ IDL }) => {
[IDL.Vec(IDL.Tuple(AnalyticKey, PerformanceMetric))],
['query']
),
get_performance_metrics_web_vitals: IDL.Func(
get_performance_metrics_analytics_web_vitals: IDL.Func(
[GetAnalytics],
[AnalyticsWebVitalsPerformanceMetrics],
['query']
Expand Down
2 changes: 1 addition & 1 deletion src/declarations/orbiter/orbiter.factory.did.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export const idlFactory = ({ IDL }) => {
[IDL.Vec(IDL.Tuple(AnalyticKey, PerformanceMetric))],
['query']
),
get_performance_metrics_web_vitals: IDL.Func(
get_performance_metrics_analytics_web_vitals: IDL.Func(
[GetAnalytics],
[AnalyticsWebVitalsPerformanceMetrics],
['query']
Expand Down
17 changes: 17 additions & 0 deletions src/frontend/src/lib/api/orbiter.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
AnalyticsMetricsPageViews,
AnalyticsTop10PageViews,
AnalyticsTrackEvents,
AnalyticsWebVitalsPerformanceMetrics,
Controller,
GetAnalytics,
PageView,
Expand Down Expand Up @@ -129,6 +130,22 @@ export const getTrackEventsAnalytics = async ({
});
};

export const getPerformanceMetricsAnalyticsWebVitals = async ({
satelliteId,
orbiterId,
from,
to,
identity
}: PageViewsParams): Promise<AnalyticsWebVitalsPerformanceMetrics> => {
const { get_performance_metrics_analytics_web_vitals } = await getOrbiterActor({ orbiterId, identity });
return getAnalytics({
satelliteId,
from,
to,
fn: get_performance_metrics_analytics_web_vitals
});
};

export const listOrbiterControllers = async ({
orbiterId,
identity
Expand Down
25 changes: 21 additions & 4 deletions src/frontend/src/lib/components/analytics/Analytics.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
import { i18n } from '$lib/stores/i18n.store';
import SpinnerParagraph from '$lib/components/ui/SpinnerParagraph.svelte';
import { toasts } from '$lib/stores/toasts.store';
import type { AnalyticsTrackEvents } from '$declarations/orbiter/orbiter.did';
import type {
AnalyticsTrackEvents,
AnalyticsWebVitalsPerformanceMetrics
} from '$declarations/orbiter/orbiter.did';
import AnalyticsChart from '$lib/components/analytics/AnalyticsChart.svelte';
import { isNullish, nonNullish } from '@dfinity/utils';
import { orbiterStore } from '$lib/stores/orbiter.store';
Expand All @@ -22,13 +25,19 @@
import NoAnalytics from '$lib/components/analytics/NoAnalytics.svelte';
import { authStore } from '$lib/stores/auth.store';
import { versionStore } from '$lib/stores/version.store';
import { getAnalyticsPageViews, getAnalyticsTrackEvents } from '$lib/services/orbiters.services';
import {
getAnalyticsPageViews,
getAnalyticsPerformanceMetrics,
getAnalyticsTrackEvents
} from '$lib/services/orbiters.services';
import { addMonths } from 'date-fns';
import AnalyticsPerformanceMetrics from '$lib/components/analytics/AnalyticsPerformanceMetrics.svelte';
let loading = true;
let pageViews: AnalyticsPageViewsType | undefined = undefined;
let trackEvents: AnalyticsTrackEvents | undefined = undefined;
let performanceMetrics: AnalyticsWebVitalsPerformanceMetrics | undefined = undefined;
let period: PageViewsPeriod = {
from: addMonths(new Date(), -1)
Expand All @@ -52,13 +61,15 @@
...period
};
const [views, events] = await Promise.all([
const [views, events, metrics] = await Promise.all([
getAnalyticsPageViews({ params, orbiterVersion: $versionStore.orbiter.current }),
getAnalyticsTrackEvents({ params, orbiterVersion: $versionStore.orbiter.current })
getAnalyticsTrackEvents({ params, orbiterVersion: $versionStore.orbiter.current }),
getAnalyticsPerformanceMetrics({ params, orbiterVersion: $versionStore.orbiter.current })
]);
pageViews = views;
trackEvents = events;
performanceMetrics = metrics;
loading = false;
} catch (err: unknown) {
Expand Down Expand Up @@ -90,6 +101,12 @@

<AnalyticsPageViews {pageViews} />

{#if nonNullish(performanceMetrics)}
<hr />

<AnalyticsPerformanceMetrics {performanceMetrics} />
{/if}

{#if nonNullish(trackEvents) && trackEvents.total.length > 0}
<hr />

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<script lang="ts">
import { i18n } from '$lib/stores/i18n.store';
import type { AnalyticsWebVitalsPerformanceMetrics } from '$declarations/orbiter/orbiter.did';
import {formatNumber} from "$lib/utils/number.utils";
export let performanceMetrics: AnalyticsWebVitalsPerformanceMetrics;
let cls: number;
let fcp: number;
let inp: number;
let lcp: number;
let ttfb: number;
$: ({cls, fcp, inp, lcp, ttfb} = performanceMetrics);
type Rating = 'good' | 'needs_improvement' | 'poor';
// https://github.com/GoogleChrome/web-vitals/blob/9b932519b16f72328c6d8e9814b811f1bc1a0bb5/src/lib/bindReporter.ts#L19
const getRating = ({value, thresholds: [improve, poor]}: {value: number, thresholds: [number, number]}): Rating => {
if (value > poor) {
return 'poor';
}
if (value > improve) {
return 'needs_improvement';
}
return 'good';
}
// https://github.com/GoogleChrome/web-vitals/blob/9b932519b16f72328c6d8e9814b811f1bc1a0bb5/src/onCLS.ts#L28
// https://web.dev/articles/cls#what_is_a_good_cls_score
let clsRating: Rating;
$: clsRating = getRating({value: cls, thresholds: [0.1, 0.25]});
// https://github.com/GoogleChrome/web-vitals/blob/9b932519b16f72328c6d8e9814b811f1bc1a0bb5/src/onFCP.ts#L28
// https://web.dev/articles/fcp#what_is_a_good_fcp_score
let fcpRating: Rating;
$: fcpRating = getRating({value: fcp, thresholds: [1800, 3000]});
// https://github.com/GoogleChrome/web-vitals/blob/9b932519b16f72328c6d8e9814b811f1bc1a0bb5/src/onINP.ts#L35C55-L35C63
// https://web.dev/articles/inp#what_is_a_good_inp_score
let inpRating: Rating;
$: inpRating = getRating({value: inp, thresholds: [200, 500]});
// https://github.com/GoogleChrome/web-vitals/blob/9b932519b16f72328c6d8e9814b811f1bc1a0bb5/src/onLCP.ts#L31
// https://web.dev/articles/lcp#what_is_a_good_lcp_score
let lcpRating: Rating;
$: lcpRating = getRating({value: lcp, thresholds: [2500, 4000]});
// https://web.dev/articles/ttfb#what_is_a_good_ttfb_score
// https://github.com/GoogleChrome/web-vitals/blob/9b932519b16f72328c6d8e9814b811f1bc1a0bb5/src/onTTFB.ts#L26C56-L26C65
let ttfbRating: Rating;
$: ttfbRating = getRating({value: ttfb, thresholds: [800, 1800]});
</script>

<div class="table-container">
<table>
<thead>
<tr>
<th> {$i18n.analytics.web_vitals} </th>
<th class="score"> {$i18n.analytics.score} </th>
<th> {$i18n.analytics.rating} </th>
</tr>
</thead>

<tbody>
<tr>
<td>{@html $i18n.analytics.ttfb}</td>
<td>{formatNumber(ttfb)}</td>
<td>{$i18n.analytics[ttfbRating]}</td>
</tr>

<tr>
<td>{@html $i18n.analytics.fcp}</td>
<td>{formatNumber(fcp)}</td>
<td>{$i18n.analytics[fcpRating]}</td>
</tr>

<tr>
<td>{@html $i18n.analytics.lcp}</td>
<td>{formatNumber(lcp)}</td>
<td>{$i18n.analytics[lcpRating]}</td>
</tr>

<tr>
<td>{@html $i18n.analytics.cls}</td>
<td>{formatNumber(cls)}</td>
<td>{$i18n.analytics[clsRating]}</td>
</tr>

<tr>
<td>{@html $i18n.analytics.inp}</td>
<td>{formatNumber(inp)}</td>
<td>{$i18n.analytics[inpRating]}</td>
</tr>
</tbody>
</table>
</div>

<style lang="scss">
@use '../../styles/mixins/media';
.status {
display: none;
@include media.min-width(medium) {
display: table-cell;
vertical-align: middle;
}
}
</style>
13 changes: 12 additions & 1 deletion src/frontend/src/lib/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,18 @@
"others": "Others",
"browsers": "Browsers",
"attach": "Attach existing Analytics",
"attach_id": "Enter Orbiter ID"
"attach_id": "Enter Orbiter ID",
"score": "Score",
"rating": "Rating",
"web_vitals": "Web Vitals",
"ttfb": "Time to First Byte <small>(TTFB)</small>",
"fcp": "First Contentful Paint <small>(FCP)</small>",
"lcp": "Largest Contentful Paint <small>(LCP)",
"cls": "Cumulative Layout Shift <small>(CLS)</small>",
"inp": "Interaction to Next Paint <small>(INP)</small>",
"good": "Good",
"needs_improvement": "Needs improvement",
"poor": "Poor"
},
"hosting": {
"title": "Hosting",
Expand Down
20 changes: 19 additions & 1 deletion src/frontend/src/lib/services/orbiters.services.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { Orbiter } from '$declarations/mission_control/mission_control.did';
import type { AnalyticsTrackEvents } from '$declarations/orbiter/orbiter.did';
import type {
AnalyticsTrackEvents,
AnalyticsWebVitalsPerformanceMetrics
} from '$declarations/orbiter/orbiter.did';
import {
getAnalyticsClientsPageViews,
getAnalyticsMetricsPageViews,
getAnalyticsTop10PageViews,
getPerformanceMetricsAnalyticsWebVitals,
getTrackEventsAnalytics
} from '$lib/api/orbiter.api';
import {
Expand Down Expand Up @@ -126,3 +130,17 @@ export const getAnalyticsTrackEvents = async ({
// TODO: support for deprecated version of the Orbiter where the analytics are calculated in the frontend. To be removed.
return getDeprecatedAnalyticsTrackEvents(params);
};

export const getAnalyticsPerformanceMetrics = async ({
orbiterVersion,
params
}: {
params: PageViewsParams;
orbiterVersion: string;
}): Promise<AnalyticsWebVitalsPerformanceMetrics | undefined> => {
if (compare(orbiterVersion, '0.0.8') >= 0) {
return getPerformanceMetricsAnalyticsWebVitals(params);
}

return undefined;
};
11 changes: 11 additions & 0 deletions src/frontend/src/lib/types/i18n.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,17 @@ interface I18nAnalytics {
browsers: string;
attach: string;
attach_id: string;
score: string;
rating: string;
web_vitals: string;
ttfb: string;
fcp: string;
lcp: string;
cls: string;
inp: string;
good: string;
needs_improvement: string;
poor: string;
}

interface I18nHosting {
Expand Down
2 changes: 1 addition & 1 deletion src/orbiter/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "orbiter"
version = "0.0.7"
version = "0.0.8"
edition = "2021"
publish = false

Expand Down
2 changes: 1 addition & 1 deletion src/orbiter/orbiter.did
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ service : () -> {
get_performance_metrics : (GetAnalytics) -> (
vec record { AnalyticKey; PerformanceMetric },
) query;
get_performance_metrics_web_vitals : (GetAnalytics) -> (
get_performance_metrics_analytics_web_vitals : (GetAnalytics) -> (
AnalyticsWebVitalsPerformanceMetrics,
) query;
get_track_events : (GetAnalytics) -> (
Expand Down
2 changes: 1 addition & 1 deletion src/orbiter/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ fn get_performance_metrics(filter: GetAnalytics) -> Vec<(AnalyticKey, Performanc
}

#[query(guard = "caller_is_controller")]
fn get_performance_metrics_web_vitals(
fn get_performance_metrics_analytics_web_vitals(
filter: GetAnalytics,
) -> AnalyticsWebVitalsPerformanceMetrics {
let metrics = get_performance_metrics_store(&filter);
Expand Down

0 comments on commit 36a4e50

Please sign in to comment.