update getSessionActivity / getWebsiteSession

This commit is contained in:
Francis Cao 2024-08-09 15:49:30 -07:00
parent c7d39a3e94
commit a1c0ec9c81
7 changed files with 69 additions and 30 deletions

View File

@ -8,12 +8,16 @@ import styles from './SessionActivity.module.css';
export function SessionActivity({
websiteId,
sessionId,
startDate,
endDate,
}: {
websiteId: string;
sessionId: string;
startDate: string;
endDate: string;
}) {
const { locale } = useLocale();
const { data, isLoading } = useSessionActivity(websiteId, sessionId);
const { data, isLoading } = useSessionActivity(websiteId, sessionId, startDate, endDate);
if (isLoading) {
return <Loading position="page" />;

View File

@ -1,13 +1,13 @@
'use client';
import WebsiteHeader from '../../WebsiteHeader';
import SessionInfo from './SessionInfo';
import { useWebsiteSession } from 'components/hooks';
import Avatar from 'components/common/Avatar';
import { LoadingPanel } from 'components/common/LoadingPanel';
import { useWebsiteSession } from 'components/hooks';
import WebsiteHeader from '../../WebsiteHeader';
import { SessionActivity } from './SessionActivity';
import { SessionStats } from './SessionStats';
import { SessionData } from './SessionData';
import styles from './SessionDetailsPage.module.css';
import { LoadingPanel } from 'components/common/LoadingPanel';
import SessionInfo from './SessionInfo';
import { SessionStats } from './SessionStats';
export default function SessionDetailsPage({
websiteId,
@ -28,7 +28,12 @@ export default function SessionDetailsPage({
</div>
<div className={styles.content}>
<SessionStats data={data} />
<SessionActivity websiteId={websiteId} sessionId={sessionId} />
<SessionActivity
websiteId={websiteId}
sessionId={sessionId}
startDate={data?.firstAt}
endDate={data?.lastAt}
/>
</div>
<div className={styles.data}>
<SessionData websiteId={websiteId} sessionId={sessionId} />

View File

@ -1,12 +1,17 @@
import { useApi } from './useApi';
export function useSessionActivity(websiteId: string, sessionId: string) {
export function useSessionActivity(
websiteId: string,
sessionId: string,
startDate: string,
endDate: string,
) {
const { get, useQuery } = useApi();
return useQuery({
queryKey: ['session:activity', { websiteId, sessionId }],
queryFn: () => {
return get(`/websites/${websiteId}/sessions/${sessionId}/activity`);
return get(`/websites/${websiteId}/sessions/${sessionId}/activity`, { startDate, endDate });
},
});
}

View File

@ -9,12 +9,16 @@ import { getSessionActivity } from 'queries';
export interface SessionActivityRequestQuery extends PageParams {
websiteId: string;
sessionId: string;
startDate: string;
endDate: string;
}
const schema = {
GET: yup.object().shape({
websiteId: yup.string().uuid().required(),
sessionId: yup.string().uuid().required(),
startDate: yup.string().required(),
endDate: yup.string().required(),
}),
};
@ -26,14 +30,19 @@ export default async (
await useAuth(req, res);
await useValidate(schema, req, res);
const { websiteId, sessionId } = req.query;
const { websiteId, sessionId, startDate, endDate } = req.query;
if (req.method === 'GET') {
if (!(await canViewWebsite(req.auth, websiteId))) {
return unauthorized(res);
}
const data = await getSessionActivity(websiteId, sessionId);
const data = await getSessionActivity(
websiteId,
sessionId,
new Date(startDate),
new Date(endDate),
);
return ok(res, data);
}

View File

@ -33,7 +33,7 @@ export default async (
return unauthorized(res);
}
const data = await getWebsiteSession(sessionId);
const data = await getWebsiteSession(websiteId, sessionId);
return ok(res, data);
}

View File

@ -1,24 +1,37 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, PRISMA, CLICKHOUSE } from 'lib/db';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
export async function getSessionActivity(...args: [websiteId: string, sessionId: string]) {
export async function getSessionActivity(
...args: [websiteId: string, sessionId: string, startDate: Date, endDate: Date]
) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(websiteId: string, sessionId: string) {
async function relationalQuery(
websiteId: string,
sessionId: string,
startDate: Date,
endDate: Date,
) {
return prisma.client.websiteEvent.findMany({
where: {
id: sessionId,
websiteId,
createdAt: { gte: startDate, lte: endDate },
},
});
}
async function clickhouseQuery(websiteId: string, sessionId: string) {
async function clickhouseQuery(
websiteId: string,
sessionId: string,
startDate: Date,
endDate: Date,
) {
const { rawQuery } = clickhouse;
return rawQuery(
@ -36,9 +49,10 @@ async function clickhouseQuery(websiteId: string, sessionId: string) {
visit_id as visitId
from website_event
where website_id = {websiteId:UUID}
and session_id = {sessionId:UUID}
and session_id = {sessionId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
order by created_at desc
`,
{ websiteId, sessionId },
{ websiteId, sessionId, startDate, endDate },
);
}

View File

@ -2,22 +2,23 @@ import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, PRISMA, CLICKHOUSE } from 'lib/db';
export async function getWebsiteSession(...args: [sessionId: string]) {
export async function getWebsiteSession(...args: [websiteId: string, sessionId: string]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(sessionId: string) {
async function relationalQuery(websiteId: string, sessionId: string) {
return prisma.client.session.findUnique({
where: {
id: sessionId,
websiteId,
},
});
}
async function clickhouseQuery(sessionId: string) {
async function clickhouseQuery(websiteId: string, sessionId: string) {
const { rawQuery } = clickhouse;
return rawQuery(
@ -34,15 +35,16 @@ async function clickhouseQuery(sessionId: string) {
country,
subdivision1,
city,
min(created_at) as firstAt,
max(created_at) as lastAt,
min(min_time) as firstAt,
max(max_time) as lastAt,
uniq(visit_id) as visits,
sumIf(1, event_type = 1) as views,
sumIf(1, event_type = 2) as events
from website_event
where session_id = {sessionId:UUID}
group by session_id, website_id, hostname, browser, os, device, screen, language, country, subdivision1, city
sumIf(views, event_type = 1) as views,
length(groupArrayArray(event_name)) as events
from website_event_stats_hourly
where website_id = {websiteId:UUID}
and session_id = {sessionId:UUID}
group by session_id, website_id, hostname, browser, os, device, screen, language, country, subdivision1, city;
`,
{ sessionId },
{ websiteId, sessionId },
).then(result => result?.[0]);
}