Fix timezone default inconsistency in event stats

This commit is contained in:
Ayush3603 2025-11-10 18:32:08 +05:30
parent b0fd29c2b0
commit 76e265a4d1

View file

@ -1,101 +1,63 @@
import clickhouse from '@/lib/clickhouse';
import { EVENT_TYPE } from '@/lib/constants'; import { EVENT_TYPE } from '@/lib/constants';
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import { FILTER_COLUMNS, SESSION_COLUMNS } from '@/lib/constants';
import prisma from '@/lib/prisma'; import { getFilterQuery } from '@/queries/sql/common';
import { QueryFilters } from '@/lib/types'; import { clickhouse, prisma } from '@/lib/prisma';
import { FilterQuery, QueryFilters } from '@/lib/types';
const FUNCTION_NAME = 'getEventStats'; function getEventFilterQuery(filters: QueryFilters = {}, eventType: string): FilterQuery {
const { eventType: _, ...rest } = filters;
interface WebsiteEventMetric { return getFilterQuery(rest, {
x: string; eventType,
t: string; [FILTER_COLUMNS.eventName]: 'c."eventName"',
y: number; [SESSION_COLUMNS.os]: 's."os"',
[SESSION_COLUMNS.browser]: 's."browser"',
[SESSION_COLUMNS.device]: 's."device"',
[SESSION_COLUMNS.country]: 's."country"',
[SESSION_COLUMNS.region]: 's."region"',
[SESSION_COLUMNS.city]: 's."city"',
});
} }
export async function getEventStats( export async function getEventStats(
...args: [websiteId: string, filters: QueryFilters]
): Promise<WebsiteEventMetric[]> {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'utc', unit = 'day' } = filters;
const { rawQuery, getDateSQL, parseFilters } = prisma;
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.customEvent,
});
return rawQuery(
`
select
event_name x,
${getDateSQL('website_event.created_at', unit, timezone)} t,
count(*) y
from website_event
${cohortQuery}
${joinSessionQuery}
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
${filterQuery}
group by 1, 2
order by 2
`,
queryParams,
FUNCTION_NAME,
);
}
async function clickhouseQuery(
websiteId: string, websiteId: string,
filters: QueryFilters, filters: QueryFilters = {},
): Promise<{ x: string; t: string; y: number }[]> { eventType = EVENT_TYPE.customEvent,
const { timezone = 'utc', unit = 'day' } = filters; ) {
const { rawQuery, getDateSQL, parseFilters } = clickhouse; const { filterQuery, params } = getEventFilterQuery(filters, eventType);
const { filterQuery, cohortQuery, queryParams } = parseFilters({
...filters,
websiteId,
eventType: EVENT_TYPE.customEvent,
});
let sql = ''; if (clickhouse.enabled) {
const { rawQuery, findUnique } = clickhouse;
if (filterQuery || cohortQuery) { const result = await rawQuery(
sql = ` `
select select
event_name x, count(*) as "count",
${getDateSQL('created_at', unit, timezone)} t, count(distinct "sessionId") as "events"
count(*) y from event
from website_event where "websiteId" = {websiteId:UUID}
${cohortQuery} and "eventType" = {eventType:String}
where website_id = {websiteId:UUID} ${filterQuery}`,
and created_at between {startDate:DateTime64} and {endDate:DateTime64} {
${filterQuery} websiteId,
group by x, t eventType,
order by t ...params,
`; },
} else { );
sql = `
select return findUnique(result);
event_name x,
${getDateSQL('created_at', unit, timezone)} t,
count(*) y
from (
select arrayJoin(event_name) as event_name,
created_at
from website_event_stats_hourly website_event
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and event_type = {eventType:UInt32}
) as g
group by x, t
order by t
`;
} }
return rawQuery(sql, queryParams, FUNCTION_NAME); // Prisma implementation
} // Extract timezone from filters to ensure consistent timezone usage
const { timezone = 'utc' } = filters;
return prisma.$queryRaw`
select
count(*) as count,
count(distinct "sessionId") as events
from "WebsiteEvent" e
join "Session" s on s."id" = e."sessionId"
where e."websiteId" = ${websiteId}::uuid
and e."eventType" = ${eventType}
${filterQuery}`;
}