performance updates checkpoint
This commit is contained in:
1 parent
8563fe1d30
commit
f6a6d2cc31
25 files changed
+488
-343
No files matched your search
@@ -53,6 +53,13 @@ export interface SaveEventArgs {
|
||||
ttclid?: string;
|
||||
lifatid?: string;
|
||||
twclid?: string;
|
||||
|
||||
// Performance
|
||||
lcp?: number;
|
||||
inp?: number;
|
||||
cls?: number;
|
||||
fcp?: number;
|
||||
ttfb?: number;
|
||||
}
|
||||
|
||||
export async function saveEvent(args: SaveEventArgs) {
|
||||
@@ -89,6 +96,11 @@ async function relationalQuery({
|
||||
ttclid,
|
||||
lifatid,
|
||||
twclid,
|
||||
lcp,
|
||||
inp,
|
||||
cls,
|
||||
fcp,
|
||||
ttfb,
|
||||
}: SaveEventArgs) {
|
||||
const websiteEventId = uuid();
|
||||
|
||||
@@ -119,6 +131,11 @@ async function relationalQuery({
|
||||
eventName: eventName ? eventName?.substring(0, EVENT_NAME_LENGTH) : null,
|
||||
tag,
|
||||
hostname,
|
||||
lcp,
|
||||
inp,
|
||||
cls,
|
||||
fcp,
|
||||
ttfb,
|
||||
createdAt,
|
||||
},
|
||||
});
|
||||
@@ -186,6 +203,11 @@ async function clickhouseQuery({
|
||||
ttclid,
|
||||
lifatid,
|
||||
twclid,
|
||||
lcp,
|
||||
inp,
|
||||
cls,
|
||||
fcp,
|
||||
ttfb,
|
||||
}: SaveEventArgs) {
|
||||
const { insert, getUTCString } = clickhouse;
|
||||
const { sendMessage } = kafka;
|
||||
@@ -221,12 +243,17 @@ async function clickhouseQuery({
|
||||
tag: tag,
|
||||
distinct_id: distinctId,
|
||||
created_at: getUTCString(createdAt),
|
||||
browser,
|
||||
os,
|
||||
device,
|
||||
screen,
|
||||
language,
|
||||
hostname,
|
||||
browser: browser,
|
||||
os: os,
|
||||
device: device,
|
||||
screen: screen,
|
||||
language: language,
|
||||
hostname: hostname,
|
||||
lcp: lcp,
|
||||
inp: inp,
|
||||
cls: cls,
|
||||
fcp: fcp,
|
||||
ttfb: ttfb,
|
||||
};
|
||||
|
||||
if (kafka.enabled) {
|
||||
|
||||
@@ -68,7 +68,7 @@ async function relationalQuery(
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
group by prefix,
|
||||
@@ -163,7 +163,7 @@ async function clickhouseQuery(
|
||||
VIDEO_DOMAINS,
|
||||
)}]) != 0 or position(lower(utm_medium), 'video') > 0 then concat(prefix, 'Video')
|
||||
when referrer_domain != hostname and referrer_domain != '' then 'referral'
|
||||
else '' end AS name,
|
||||
else '' end AS "name",
|
||||
session_id,
|
||||
visit_id,
|
||||
count(*) c,
|
||||
@@ -174,7 +174,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
and name != ''
|
||||
${filterQuery}
|
||||
group by prefix, name, session_id, visit_id
|
||||
|
||||
@@ -45,7 +45,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
${excludeBounceQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${dateQuery}
|
||||
${filterQuery}),
|
||||
|
||||
@@ -123,7 +123,7 @@ async function clickhouseQuery(
|
||||
${cohortQuery}
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${dateQuery}
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
|
||||
@@ -58,7 +58,7 @@ async function relationalQuery(
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by 1, 2
|
||||
|
||||
@@ -103,7 +103,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by session_id, visit_id
|
||||
) as t;
|
||||
@@ -127,7 +127,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by session_id, visit_id
|
||||
) as t;
|
||||
|
||||
@@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by time
|
||||
order by 1
|
||||
@@ -63,7 +63,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by time
|
||||
order by time
|
||||
@@ -78,7 +78,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by time
|
||||
order by time
|
||||
|
||||
@@ -24,7 +24,6 @@ export * from './pageviews/getPageviewExpandedMetrics';
|
||||
export * from './pageviews/getPageviewMetrics';
|
||||
export * from './pageviews/getPageviewStats';
|
||||
export * from './performance/getPerformanceStats';
|
||||
export * from './performance/savePerformance';
|
||||
export * from './replays/getReplayChunks';
|
||||
export * from './replays/getSessionReplays';
|
||||
export * from './replays/saveRecording';
|
||||
|
||||
@@ -68,7 +68,7 @@ async function relationalQuery(
|
||||
from website_event
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
group by visit_id
|
||||
) x
|
||||
on x.visit_id = website_event.visit_id
|
||||
@@ -100,7 +100,7 @@ async function relationalQuery(
|
||||
${entryExitQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${excludeDomain}
|
||||
${filterQuery}
|
||||
group by ${column}, website_event.session_id, website_event.visit_id
|
||||
@@ -149,7 +149,7 @@ async function clickhouseQuery(
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
group by visit_id) x
|
||||
ON x.visit_id = website_event.visit_id`;
|
||||
}
|
||||
@@ -177,7 +177,7 @@ async function clickhouseQuery(
|
||||
${entryExitQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
and name != ''
|
||||
${excludeDomain}
|
||||
${filterQuery}
|
||||
|
||||
@@ -63,7 +63,7 @@ async function relationalQuery(
|
||||
from website_event
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
order by visit_id, created_at ${order}
|
||||
) x
|
||||
on x.visit_id = website_event.visit_id
|
||||
@@ -81,7 +81,7 @@ async function relationalQuery(
|
||||
${entryExitQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${excludeDomain}
|
||||
${filterQuery}
|
||||
group by 1
|
||||
@@ -127,7 +127,7 @@ async function clickhouseQuery(
|
||||
from website_event
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
group by visit_id) x
|
||||
ON x.visit_id = website_event.visit_id`;
|
||||
}
|
||||
@@ -141,7 +141,7 @@ async function clickhouseQuery(
|
||||
${entryExitQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${excludeDomain}
|
||||
${filterQuery}
|
||||
group by x
|
||||
@@ -180,7 +180,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${excludeDomain}
|
||||
${filterQuery}
|
||||
${groupByQuery}) as g
|
||||
|
||||
@@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by 1
|
||||
order by 1
|
||||
@@ -70,7 +70,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by t
|
||||
) as g
|
||||
@@ -90,7 +90,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by t
|
||||
) as g
|
||||
|
||||
@@ -23,8 +23,11 @@ async function relationalQuery(
|
||||
websiteId: string,
|
||||
filters: QueryFilters,
|
||||
): Promise<PerformanceStatsResult> {
|
||||
const { rawQuery } = prisma;
|
||||
const { startDate, endDate } = filters;
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
const result = await rawQuery(
|
||||
`
|
||||
@@ -35,11 +38,15 @@ async function relationalQuery(
|
||||
percentile_cont(0.75) within group (order by fcp) as fcp,
|
||||
percentile_cont(0.75) within group (order by ttfb) as ttfb,
|
||||
count(*) as count
|
||||
from performance
|
||||
where website_id = {{websiteId::uuid}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
queryParams,
|
||||
);
|
||||
|
||||
return result?.[0] || { lcp: 0, inp: 0, cls: 0, fcp: 0, ttfb: 0, count: 0 };
|
||||
@@ -49,8 +56,8 @@ async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
filters: QueryFilters,
|
||||
): Promise<PerformanceStatsResult> {
|
||||
const { rawQuery } = clickhouse;
|
||||
const { startDate, endDate } = filters;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId });
|
||||
|
||||
const result = await rawQuery<PerformanceStatsResult>(
|
||||
`
|
||||
@@ -61,11 +68,14 @@ async function clickhouseQuery(
|
||||
quantile(0.75)(fcp) as fcp,
|
||||
quantile(0.75)(ttfb) as ttfb,
|
||||
count() as count
|
||||
from website_performance
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
queryParams,
|
||||
);
|
||||
|
||||
return result?.[0] || { lcp: 0, inp: 0, cls: 0, fcp: 0, ttfb: 0, count: 0 };
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { uuid } from '@/lib/crypto';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import kafka from '@/lib/kafka';
|
||||
import prisma from '@/lib/prisma';
|
||||
|
||||
export interface SavePerformanceArgs {
|
||||
websiteId: string;
|
||||
sessionId: string;
|
||||
visitId: string;
|
||||
urlPath: string;
|
||||
lcp?: number;
|
||||
inp?: number;
|
||||
cls?: number;
|
||||
fcp?: number;
|
||||
ttfb?: number;
|
||||
createdAt: Date;
|
||||
}
|
||||
|
||||
export async function savePerformance(args: SavePerformanceArgs) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(data: SavePerformanceArgs) {
|
||||
const { websiteId, sessionId, visitId, urlPath, lcp, inp, cls, fcp, ttfb, createdAt } = data;
|
||||
|
||||
await prisma.client.performance.create({
|
||||
data: {
|
||||
id: uuid(),
|
||||
websiteId,
|
||||
sessionId,
|
||||
visitId,
|
||||
urlPath: urlPath?.substring(0, 500),
|
||||
lcp,
|
||||
inp,
|
||||
cls,
|
||||
fcp,
|
||||
ttfb,
|
||||
createdAt,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function clickhouseQuery(data: SavePerformanceArgs) {
|
||||
const { websiteId, sessionId, visitId, urlPath, lcp, inp, cls, fcp, ttfb, createdAt } = data;
|
||||
const { insert, getUTCString } = clickhouse;
|
||||
const { sendMessage } = kafka;
|
||||
|
||||
const message = {
|
||||
website_id: websiteId,
|
||||
session_id: sessionId,
|
||||
visit_id: visitId,
|
||||
url_path: urlPath?.substring(0, 500),
|
||||
lcp: lcp ?? null,
|
||||
inp: inp ?? null,
|
||||
cls: cls ?? null,
|
||||
fcp: fcp ?? null,
|
||||
ttfb: ttfb ?? null,
|
||||
created_at: getUTCString(createdAt),
|
||||
};
|
||||
|
||||
if (kafka.enabled) {
|
||||
await sendMessage('performance', message);
|
||||
} else {
|
||||
await insert('website_performance', [message]);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,6 @@ export interface PerformanceParameters {
|
||||
|
||||
export interface PerformanceResult {
|
||||
chart: { t: string; p50: number; p75: number; p95: number }[];
|
||||
pages: { urlPath: string; p75: number; count: number }[];
|
||||
summary: {
|
||||
lcp: { p50: number; p75: number; p95: number };
|
||||
inp: { p50: number; p75: number; p95: number };
|
||||
@@ -39,7 +38,11 @@ async function relationalQuery(
|
||||
filters: QueryFilters,
|
||||
): Promise<PerformanceResult> {
|
||||
const { startDate, endDate, unit = 'day', timezone = 'utc', metric = 'lcp' } = parameters;
|
||||
const { getDateSQL, rawQuery } = prisma;
|
||||
const { getDateSQL, rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
const chart = await rawQuery(
|
||||
`
|
||||
@@ -48,29 +51,17 @@ async function relationalQuery(
|
||||
percentile_cont(0.5) within group (order by ${metric}) as p50,
|
||||
percentile_cont(0.75) within group (order by ${metric}) as p75,
|
||||
percentile_cont(0.95) within group (order by ${metric}) as p95
|
||||
from performance
|
||||
where website_id = {{websiteId::uuid}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
group by t
|
||||
order by t
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
);
|
||||
|
||||
const pages = await rawQuery(
|
||||
`
|
||||
select
|
||||
url_path as "urlPath",
|
||||
percentile_cont(0.75) within group (order by ${metric}) as p75,
|
||||
count(*) as count
|
||||
from performance
|
||||
where website_id = {{websiteId::uuid}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
group by url_path
|
||||
order by p75 desc
|
||||
limit 100
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
{ ...queryParams, startDate, endDate },
|
||||
);
|
||||
|
||||
const summaryResult = await rawQuery(
|
||||
@@ -92,11 +83,15 @@ async function relationalQuery(
|
||||
percentile_cont(0.75) within group (order by ttfb) as ttfb_p75,
|
||||
percentile_cont(0.95) within group (order by ttfb) as ttfb_p95,
|
||||
count(*) as count
|
||||
from performance
|
||||
where website_id = {{websiteId::uuid}}
|
||||
and created_at between {{startDate}} and {{endDate}}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
{ ...queryParams, startDate, endDate },
|
||||
).then(result => result?.[0]);
|
||||
|
||||
const summary = {
|
||||
@@ -128,7 +123,7 @@ async function relationalQuery(
|
||||
count: Number(summaryResult?.count || 0),
|
||||
};
|
||||
|
||||
return { chart, pages, summary };
|
||||
return { chart, summary };
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
@@ -137,38 +132,26 @@ async function clickhouseQuery(
|
||||
filters: QueryFilters,
|
||||
): Promise<PerformanceResult> {
|
||||
const { startDate, endDate, unit = 'day', timezone = 'utc', metric = 'lcp' } = parameters;
|
||||
const { getDateSQL, rawQuery } = clickhouse;
|
||||
const { getDateSQL, rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId });
|
||||
|
||||
const chart = await rawQuery<{ t: string; p50: number; p75: number; p95: number }[]>(
|
||||
`
|
||||
select
|
||||
${getDateSQL('created_at', unit, timezone)} t,
|
||||
${getDateSQL('created_at', 'minute', timezone)} t,
|
||||
quantile(0.5)(${metric}) as p50,
|
||||
quantile(0.75)(${metric}) as p75,
|
||||
quantile(0.95)(${metric}) as p95
|
||||
from website_performance
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
group by t
|
||||
order by t
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
);
|
||||
|
||||
const pages = await rawQuery<{ urlPath: string; p75: number; count: number }[]>(
|
||||
`
|
||||
select
|
||||
url_path as "urlPath",
|
||||
quantile(0.75)(${metric}) as p75,
|
||||
count() as count
|
||||
from website_performance
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
group by url_path
|
||||
order by p75 desc
|
||||
limit 100
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
{ ...queryParams, startDate, endDate },
|
||||
);
|
||||
|
||||
const summaryResult = await rawQuery<any>(
|
||||
@@ -190,11 +173,14 @@ async function clickhouseQuery(
|
||||
quantile(0.75)(ttfb) as ttfb_p75,
|
||||
quantile(0.95)(ttfb) as ttfb_p95,
|
||||
count() as count
|
||||
from website_performance
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
`,
|
||||
{ websiteId, startDate, endDate },
|
||||
{ ...queryParams, startDate, endDate },
|
||||
).then(result => result?.[0]);
|
||||
|
||||
const summary = {
|
||||
@@ -226,5 +212,5 @@ async function clickhouseQuery(
|
||||
count: Number(summaryResult?.count || 0),
|
||||
};
|
||||
|
||||
return { chart, pages, summary };
|
||||
return { chart, summary };
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { QueryFilters } from '@/lib/types';
|
||||
import type { PerformanceParameters } from './getPerformance';
|
||||
|
||||
export interface PerformanceMetricsData {
|
||||
name: string;
|
||||
p50: number;
|
||||
p75: number;
|
||||
p95: number;
|
||||
count: number;
|
||||
}
|
||||
|
||||
export async function getPerformanceMetrics(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
parameters: PerformanceParameters,
|
||||
filters: QueryFilters,
|
||||
column: string,
|
||||
limit?: number,
|
||||
]
|
||||
) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
parameters: PerformanceParameters,
|
||||
filters: QueryFilters,
|
||||
column: string,
|
||||
limit?: number,
|
||||
): Promise<PerformanceMetricsData[]> {
|
||||
const { startDate, endDate, metric = 'lcp' } = parameters;
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
${column} as "name",
|
||||
percentile_cont(0.5) within group (order by ${metric}) as p50,
|
||||
percentile_cont(0.75) within group (order by ${metric}) as p75,
|
||||
percentile_cont(0.95) within group (order by ${metric}) as p95,
|
||||
count(*) as count
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
group by ${column}
|
||||
order by p75 desc
|
||||
${limit ? `limit ${limit}` : ''}
|
||||
`,
|
||||
{ ...queryParams, startDate, endDate },
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
parameters: PerformanceParameters,
|
||||
filters: QueryFilters,
|
||||
column: string,
|
||||
limit?: number,
|
||||
): Promise<PerformanceMetricsData[]> {
|
||||
const { startDate, endDate, metric = 'lcp' } = parameters;
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId });
|
||||
|
||||
return rawQuery<PerformanceMetricsData[]>(
|
||||
`
|
||||
select
|
||||
${column} as "name",
|
||||
quantile(0.5)(${metric}) as p50,
|
||||
quantile(0.75)(${metric}) as p75,
|
||||
quantile(0.95)(${metric}) as p95,
|
||||
count() as count
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.event_type = 5
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
group by ${column}
|
||||
order by p75 desc
|
||||
${limit ? `limit ${limit}` : ''}
|
||||
`,
|
||||
{ ...queryParams, startDate, endDate },
|
||||
);
|
||||
}
|
||||
@@ -79,7 +79,7 @@ async function relationalQuery(
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by name, website_event.session_id, website_event.visit_id
|
||||
${includeCountry ? ', country' : ''}
|
||||
@@ -138,7 +138,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
and name != ''
|
||||
${filterQuery}
|
||||
group by name, session_id, visit_id
|
||||
|
||||
@@ -57,7 +57,7 @@ async function relationalQuery(
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by 1
|
||||
${includeCountry ? ', 3' : ''}
|
||||
@@ -101,7 +101,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by x
|
||||
${includeCountry ? ', country' : ''}
|
||||
@@ -120,7 +120,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by x
|
||||
${includeCountry ? ', country' : ''}
|
||||
|
||||
@@ -33,7 +33,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_type != 2
|
||||
and website_event.event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by 1
|
||||
order by 1
|
||||
@@ -70,7 +70,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by t
|
||||
) as g
|
||||
@@ -90,7 +90,7 @@ async function clickhouseQuery(
|
||||
${excludeBounceQuery}
|
||||
where website_id = {websiteId:UUID}
|
||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_type != 2
|
||||
and event_type NOT IN (2, 5)
|
||||
${filterQuery}
|
||||
group by t
|
||||
) as g
|
||||
|
||||
Reference in new issue
Block a user