Updates to insights, event data, telemetry.

This commit is contained in:
Mike Cao 2023-07-23 13:18:01 -07:00
parent 39562d4a64
commit e4bd314bd6
44 changed files with 413 additions and 278 deletions

View file

@ -0,0 +1,45 @@
import { Prisma } from '@prisma/client';
import cache from 'lib/cache';
import prisma from 'lib/prisma';
export async function createSession(data: Prisma.SessionCreateInput) {
const {
id,
websiteId,
hostname,
browser,
os,
device,
screen,
language,
country,
subdivision1,
subdivision2,
city,
} = data;
return prisma.client.session
.create({
data: {
id,
websiteId,
hostname,
browser,
os,
device,
screen,
language,
country,
subdivision1: country && subdivision1 ? `${country}-${subdivision1}` : null,
subdivision2,
city,
},
})
.then(async data => {
if (cache.enabled) {
await cache.storeSession(data);
}
return data;
});
}

View file

@ -0,0 +1,8 @@
import { Prisma } from '@prisma/client';
import prisma from 'lib/prisma';
export async function getSession(where: Prisma.SessionWhereUniqueInput) {
return prisma.client.session.findUnique({
where,
});
}

View file

@ -0,0 +1,75 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { DEFAULT_RESET_DATE, EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/query';
export async function getSessionMetrics(
...args: [
websiteId: string,
criteria: { startDate: Date; endDate: Date; column: string; filters: object },
]
) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(
websiteId: string,
criteria: { startDate: Date; endDate: Date; column: string; filters: object },
) {
const website = await loadWebsite(websiteId);
const resetDate = new Date(website?.resetAt || DEFAULT_RESET_DATE);
const { startDate, endDate, column, filters = {} } = criteria;
const { toUuid, parseFilters, rawQuery } = prisma;
const params: any = [websiteId, resetDate, startDate, endDate];
const { filterQuery, joinSession } = parseFilters(filters, params);
return rawQuery(
`select ${column} x, count(*) y
from session as x
where x.session_id in (
select website_event.session_id
from website_event
join website
on website_event.website_id = website.website_id
${joinSession}
where website.website_id = $1${toUuid()}
and website_event.created_at >= $2
and website_event.created_at between $3 and $4
${filterQuery}
)
group by 1
order by 2 desc
limit 100`,
params,
);
}
async function clickhouseQuery(
websiteId: string,
data: { startDate: Date; endDate: Date; column: string; filters: object },
) {
const { startDate, endDate, column, filters = {} } = data;
const { getDateFormat, parseFilters, rawQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const resetDate = new Date(website?.resetAt || DEFAULT_RESET_DATE);
const params = { websiteId };
const { filterQuery } = parseFilters(filters, params);
return rawQuery(
`select ${column} x, count(distinct session_id) y
from website_event as x
where website_id = {websiteId:UUID}
and event_type = ${EVENT_TYPE.pageView}
and created_at >= ${getDateFormat(resetDate)}
and created_at between ${getDateFormat(startDate)} and ${getDateFormat(endDate)}
${filterQuery}
group by x
order by y desc
limit 100`,
params,
);
}

View file

@ -0,0 +1,50 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, PRISMA, CLICKHOUSE } from 'lib/db';
export async function getSessions(...args: [websiteId: string, startAt: Date]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(websiteId: string, startAt: Date) {
return prisma.client.session.findMany({
where: {
websiteId,
createdAt: {
gte: startAt,
},
},
});
}
async function clickhouseQuery(websiteId: string, startAt: Date) {
const { rawQuery } = clickhouse;
return rawQuery(
`select distinct
session_id as id,
website_id as websiteId,
created_at as createdAt,
toUnixTimestamp(created_at) as timestamp,
hostname,
browser,
os,
device,
screen,
language,
country,
subdivision1,
subdivision2,
city
from website_event
where website_id = {websiteId:UUID}
and created_at >= {startAt:DateTime('UTC')}`,
{
websiteId,
startAt,
},
);
}

View file

@ -0,0 +1,43 @@
import { DATA_TYPE } from 'lib/constants';
import { uuid } from 'next-basics';
import { flattenJSON } from 'lib/dynamicData';
import prisma from 'lib/prisma';
import { DynamicData } from 'lib/types';
export async function saveSessionData(data: {
websiteId: string;
sessionId: string;
sessionData: DynamicData;
}) {
const { client, transaction } = prisma;
const { websiteId, sessionId, sessionData } = data;
const jsonKeys = flattenJSON(sessionData);
const flattendData = jsonKeys.map(a => ({
id: uuid(),
websiteId,
sessionId,
key: a.key,
stringValue:
a.dynamicDataType === DATA_TYPE.number
? parseFloat(a.value).toFixed(4)
: a.dynamicDataType === DATA_TYPE.date
? a.value.split('.')[0] + 'Z'
: a.value.toString(),
numberValue: a.dynamicDataType === DATA_TYPE.number ? a.value : null,
dateValue: a.dynamicDataType === DATA_TYPE.date ? new Date(a.value) : null,
dataType: a.dynamicDataType,
}));
return transaction([
client.sessionData.deleteMany({
where: {
sessionId,
},
}),
client.sessionData.createMany({
data: flattendData as any,
}),
]);
}