diff --git a/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx b/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx index 700e83ae..97fb1659 100644 --- a/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx +++ b/src/app/(main)/websites/[websiteId]/realtime/RealtimeLog.tsx @@ -54,7 +54,7 @@ export function RealtimeLog({ data }: { data: RealtimeData }) { }, ]; - const getTime = ({ timestamp }) => format(timestamp * 1000, 'h:mm:ss'); + const getTime = ({ createdAt }) => format(new Date(createdAt), 'h:mm:ss'); const getColor = ({ id, sessionId }) => stringToColor(sessionId || id); @@ -149,7 +149,7 @@ export function RealtimeLog({ data }: { data: RealtimeData }) { ...e, })), ...visitors.map(v => ({ __type: TYPE_SESSION, ...v })), - ].sort(thenby.firstBy('timestamp', -1)); + ].sort(thenby.firstBy('createdAt', -1)); if (search) { logs = logs.filter(({ eventName, urlPath, browser, os, country, device }) => { diff --git a/src/lib/clickhouse.ts b/src/lib/clickhouse.ts index e716d649..2bda9bfa 100644 --- a/src/lib/clickhouse.ts +++ b/src/lib/clickhouse.ts @@ -9,11 +9,12 @@ import { maxDate } from './date'; import { filtersToArray } from './params'; export const CLICKHOUSE_DATE_FORMATS = { - minute: '%Y-%m-%d %H:%i:00', - hour: '%Y-%m-%d %H:00:00', - day: '%Y-%m-%d', - month: '%Y-%m-01', - year: '%Y-01-01', + second: '%Y-%m-%dT%H:%i:%S', + minute: '%Y-%m-%dT%H:%i:00', + hour: '%Y-%m-%dT%H:00:00', + day: '%Y-%m-%dT00:00:00', + month: '%Y-%m-01T00:00:00', + year: '%Y-01-01T00:00:00', }; const log = debug('umami:clickhouse'); @@ -47,7 +48,11 @@ function getClient() { return client; } -function getDateStringSQL(data: any, unit: string | number) { +function getDateStringSQL(data: any, unit: string | number, timezone?: string) { + if (timezone) { + return `formatDateTime(${data}, '${CLICKHOUSE_DATE_FORMATS[unit]}', '${timezone}')`; + } + return `formatDateTime(${data}, '${CLICKHOUSE_DATE_FORMATS[unit]}')`; } diff --git a/src/lib/date.ts b/src/lib/date.ts index de76f7f3..2fb24073 100644 --- a/src/lib/date.ts +++ b/src/lib/date.ts @@ -292,7 +292,7 @@ export function getDateArray(data: any[], startDate: Date, endDate: Date, unit: for (let i = 0; i <= n; i++) { const t = start(add(startDate, i)); - const y = data.find(({ x }) => start(getDateFromString(x)).getTime() === t.getTime())?.y || 0; + const y = data.find(({ x }) => start(new Date(x)).getTime() === t.getTime())?.y || 0; arr.push({ x: t, y }); } diff --git a/src/queries/analytics/events/getEvents.ts b/src/queries/analytics/events/getEvents.ts index a00f6848..540c1a05 100644 --- a/src/queries/analytics/events/getEvents.ts +++ b/src/queries/analytics/events/getEvents.ts @@ -24,7 +24,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters, pagePar } async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) { - const { pagedQuery, parseFilters } = clickhouse; + const { pagedQuery, parseFilters, getDateStringSQL } = clickhouse; const { params, dateQuery, filterQuery } = await parseFilters(websiteId, filters); return pagedQuery( @@ -33,8 +33,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters, pagePar event_id as id, website_id as websiteId, session_id as sessionId, - created_at as createdAt, - toUnixTimestamp(created_at) as timestamp, + ${getDateStringSQL('created_at', 'second', filters.timezone)} as createdAt, url_path as urlPath, url_query as urlQuery, referrer_path as referrerPath, diff --git a/src/queries/analytics/getRealtimeData.ts b/src/queries/analytics/getRealtimeData.ts index afc7ff8f..5a9c5a36 100644 --- a/src/queries/analytics/getRealtimeData.ts +++ b/src/queries/analytics/getRealtimeData.ts @@ -19,8 +19,8 @@ export async function getRealtimeData( const { startDate, timezone } = criteria; const filters = { startDate, endDate: new Date(), unit: 'minute', timezone }; const [events, sessions, pageviews, sessionviews] = await Promise.all([ - getEvents(websiteId, { startDate }, { pageSize: 10000 }), - getSessions(websiteId, { startDate }, { pageSize: 10000 }), + getEvents(websiteId, { startDate, timezone }, { pageSize: 10000 }), + getSessions(websiteId, { startDate, timezone }, { pageSize: 10000 }), getPageviewStats(websiteId, filters), getSessionStats(websiteId, filters), ]); diff --git a/src/queries/analytics/sessions/getSessions.ts b/src/queries/analytics/sessions/getSessions.ts index 47471d98..538133ba 100644 --- a/src/queries/analytics/sessions/getSessions.ts +++ b/src/queries/analytics/sessions/getSessions.ts @@ -24,7 +24,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters, pagePar } async function clickhouseQuery(websiteId: string, filters: QueryFilters, pageParams?: PageParams) { - const { pagedQuery, parseFilters } = clickhouse; + const { pagedQuery, parseFilters, getDateStringSQL } = clickhouse; const { params, dateQuery, filterQuery } = await parseFilters(websiteId, filters); return pagedQuery( @@ -32,8 +32,7 @@ async function clickhouseQuery(websiteId: string, filters: QueryFilters, pagePar select session_id as id, website_id as websiteId, - created_at as createdAt, - toUnixTimestamp(created_at) as timestamp, + ${getDateStringSQL('created_at', 'second', filters.timezone)} as createdAt, hostname, browser, os,