umami/queries/analytics/event/getEventMetrics.ts

228 lines
5.1 KiB
TypeScript
Raw Normal View History

import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA, MONGODB } from 'lib/db';
import { WebsiteEventMetric } from 'lib/types';
import { EVENT_TYPE } from 'lib/constants';
2023-04-02 02:38:35 +02:00
import { loadWebsite } from 'lib/query';
export async function getEventMetrics(
...args: [
websiteId: string,
data: {
startDate: Date;
endDate: Date;
timezone: string;
unit: string;
filters: {
url: string;
eventName: string;
};
},
]
): Promise<WebsiteEventMetric[]> {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
[MONGODB]: () => mongodbQuery(...args),
});
}
async function relationalQuery(
websiteId: string,
{
startDate,
endDate,
timezone = 'utc',
unit = 'day',
filters,
}: {
startDate: Date;
endDate: Date;
timezone: string;
unit: string;
filters: {
url: string;
eventName: string;
};
},
) {
const { toUuid, rawQuery, getDateQuery, getFilterQuery } = prisma;
2023-04-02 02:38:35 +02:00
const website = await loadWebsite(websiteId);
2023-04-20 06:16:56 +02:00
const resetDate = new Date(website?.resetAt || website?.createdAt);
const params: any = [websiteId, resetDate, startDate, endDate];
2023-04-02 00:44:30 +02:00
const filterQuery = getFilterQuery(filters, params);
return rawQuery(
`select
event_name x,
${getDateQuery('created_at', unit, timezone)} t,
count(*) y
from website_event
where website_id = $1${toUuid()}
and created_at >= $2
and created_at between $3 and $4
and event_type = ${EVENT_TYPE.customEvent}
2023-04-02 00:44:30 +02:00
${filterQuery}
group by 1, 2
order by 2`,
params,
);
}
async function clickhouseQuery(
websiteId: string,
{
startDate,
endDate,
timezone = 'utc',
unit = 'day',
filters,
}: {
startDate: Date;
endDate: Date;
timezone: string;
unit: string;
filters: {
url: string;
eventName: string;
};
},
) {
const { rawQuery, getDateQuery, getDateFormat, getBetweenDates, getFilterQuery } = clickhouse;
2023-04-02 02:38:35 +02:00
const website = await loadWebsite(websiteId);
2023-04-20 06:16:56 +02:00
const resetDate = new Date(website?.resetAt || website?.createdAt);
const params = { websiteId };
return rawQuery(
`select
event_name x,
${getDateQuery('created_at', unit, timezone)} t,
count(*) y
2023-03-29 20:06:12 +02:00
from website_event
where website_id = {websiteId:UUID}
and event_type = ${EVENT_TYPE.customEvent}
and created_at >= ${getDateFormat(resetDate)}
and ${getBetweenDates('created_at', startDate, endDate)}
${getFilterQuery(filters, params)}
group by x, t
order by t`,
params,
);
}
async function mongodbQuery(
websiteId: string,
{
startDate,
endDate,
timezone = 'utc',
unit = 'day',
filters,
}: {
startDate: Date;
endDate: Date;
timezone: string;
unit: string;
filters: {
url: string;
eventName: string;
};
},
) {
const { getDateQuery, parseMongoFilter, client } = prisma;
const website = await loadWebsite(websiteId);
const resetDate = new Date(website?.resetAt || website?.createdAt);
const mongoFilter = parseMongoFilter(filters);
return await client.websiteEvent.aggregateRaw({
pipeline: [
mongoFilter,
{
$match: {
$expr: {
$and: [
{
$eq: ['$event_type', EVENT_TYPE.customEvent],
},
{
$eq: ['$website_id', websiteId],
},
{
$gte: [
'$created_at',
{
$dateFromString: {
dateString: resetDate.toISOString(),
},
},
],
},
{
$gte: [
'$created_at',
{
$dateFromString: {
dateString: startDate.toISOString(),
},
},
],
},
{
$lte: [
'$created_at',
{
$dateFromString: {
dateString: endDate.toISOString(),
},
},
],
},
],
},
},
},
{
$project: {
t: {
$dateTrunc: {
date: '$created_at',
unit: unit,
timezone: timezone,
},
},
event_name: 1,
},
},
{
$group: {
_id: {
t: '$t',
name: '$event_name',
},
y: {
$sum: 1,
},
},
},
{
$project: {
x: '$_id.name',
t: {
$dateToString: {
date: '$_id.t',
format: getDateQuery('', unit, timezone),
timezone: timezone,
},
},
y: 1,
_id: 0,
},
},
{
$sort: {
t: 1,
},
},
],
});
}