checkpoint

This commit is contained in:
Brian Cao 2022-07-29 22:30:09 -07:00
parent 3e2c098c05
commit 8f934c7e6c
14 changed files with 73 additions and 63 deletions

View File

@ -12,7 +12,7 @@ export default function EventsChart({ websiteId, className, token }) {
const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId); const [{ startDate, endDate, unit, modified }] = useDateRange(websiteId);
const [timezone] = useTimezone(); const [timezone] = useTimezone();
const { const {
query: { url, eventType }, query: { url, eventName },
} = usePageQuery(); } = usePageQuery();
const { data, loading } = useFetch( const { data, loading } = useFetch(
@ -24,11 +24,11 @@ export default function EventsChart({ websiteId, className, token }) {
unit, unit,
tz: timezone, tz: timezone,
url, url,
event_type: eventType, event_name: eventName,
token, token,
}, },
}, },
[modified, eventType], [modified, eventName],
); );
const datasets = useMemo(() => { const datasets = useMemo(() => {

View File

@ -92,8 +92,7 @@ export default function RealtimeLog({ data, websites, websiteId }) {
} }
function getDetail({ function getDetail({
event_type, event_name,
event_value,
view_id, view_id,
session_id, session_id,
url, url,
@ -103,10 +102,10 @@ export default function RealtimeLog({ data, websites, websiteId }) {
device, device,
website_id, website_id,
}) { }) {
if (event_type) { if (event_name) {
return ( return (
<div> <div>
<Tag>{event_type}</Tag> {event_value} <Tag>{event_name}</Tag>
</div> </div>
); );
} }

View File

@ -37,7 +37,8 @@ export default function TestConsole() {
function handleClick() { function handleClick() {
window.umami('event (default)'); window.umami('event (default)');
window.umami.trackView('/page-view', 'https://www.google.com'); window.umami.trackView('/page-view', 'https://www.google.com');
window.umami.trackEvent('event (custom)', 'custom-type'); window.umami.trackEvent('event (custom)', null, 'custom-type');
window.umami.trackEvent('event (custom)', { test: 'test-data' }, 'custom-data-type');
} }
return ( return (

View File

@ -36,8 +36,7 @@ ALTER TABLE `website` RENAME INDEX `website_uuid` TO `website_website_uuid_key`;
*/ */
-- Populate event_name -- Populate event_name
update `event` update `event`
set event_name = concat(event_value, "-", event_type) set event_name = event_value;
where 1 = 1;
-- Set event_name not null -- Set event_name not null
ALTER TABLE `event` ALTER TABLE `event`

View File

@ -9,7 +9,7 @@ datasource db {
model account { model account {
user_id Int @id @default(autoincrement()) @db.UnsignedInt user_id Int @id @default(autoincrement()) @db.UnsignedInt
username String @unique(map: "username") @db.VarChar(255) username String @unique() @db.VarChar(255)
password String @db.VarChar(60) password String @db.VarChar(60)
is_admin Boolean @default(false) is_admin Boolean @default(false)
created_at DateTime? @default(now()) @db.Timestamp(0) created_at DateTime? @default(now()) @db.Timestamp(0)
@ -18,21 +18,28 @@ model account {
} }
model event { model event {
event_id Int @id @default(autoincrement()) @db.UnsignedInt event_id Int @id @default(autoincrement()) @db.UnsignedInt
website_id Int @db.UnsignedInt website_id Int @db.UnsignedInt
session_id Int @db.UnsignedInt session_id Int @db.UnsignedInt
created_at DateTime? @default(now()) @db.Timestamp(0) created_at DateTime? @default(now()) @db.Timestamp(0)
url String @db.VarChar(500) url String @db.VarChar(500)
event_type String @db.VarChar(50) event_name String @db.VarChar(50)
event_value String @db.VarChar(50) session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade, onUpdate: NoAction, map: "event_ibfk_2")
session session @relation(fields: [session_id], references: [session_id], onDelete: Cascade, onUpdate: NoAction, map: "event_ibfk_2") website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction, map: "event_ibfk_1")
website website @relation(fields: [website_id], references: [website_id], onDelete: Cascade, onUpdate: NoAction, map: "event_ibfk_1") event_data event_data?
@@index([created_at]) @@index([created_at])
@@index([session_id]) @@index([session_id])
@@index([website_id]) @@index([website_id])
} }
model event_data {
id Int @id @default(autoincrement()) @map("event_data_id")
eventId Int @unique @map("event_id") @db.UnsignedInt
eventData Json @map("event_data")
event event @relation(fields: [eventId], references: [event_id])
}
model pageview { model pageview {
view_id Int @id @default(autoincrement()) @db.UnsignedInt view_id Int @id @default(autoincrement()) @db.UnsignedInt
website_id Int @db.UnsignedInt website_id Int @db.UnsignedInt
@ -52,7 +59,7 @@ model pageview {
model session { model session {
session_id Int @id @default(autoincrement()) @db.UnsignedInt session_id Int @id @default(autoincrement()) @db.UnsignedInt
session_uuid String @unique(map: "session_uuid") @db.VarChar(36) session_uuid String @unique() @db.VarChar(36)
website_id Int @db.UnsignedInt website_id Int @db.UnsignedInt
created_at DateTime? @default(now()) @db.Timestamp(0) created_at DateTime? @default(now()) @db.Timestamp(0)
hostname String? @db.VarChar(100) hostname String? @db.VarChar(100)
@ -72,11 +79,11 @@ model session {
model website { model website {
website_id Int @id @default(autoincrement()) @db.UnsignedInt website_id Int @id @default(autoincrement()) @db.UnsignedInt
website_uuid String @unique(map: "website_uuid") @db.VarChar(36) website_uuid String @unique() @db.VarChar(36)
user_id Int @db.UnsignedInt user_id Int @db.UnsignedInt
name String @db.VarChar(100) name String @db.VarChar(100)
domain String? @db.VarChar(500) domain String? @db.VarChar(500)
share_id String? @unique(map: "share_id") @db.VarChar(64) share_id String? @unique() @db.VarChar(64)
created_at DateTime? @default(now()) @db.Timestamp(0) created_at DateTime? @default(now()) @db.Timestamp(0)
account account @relation(fields: [user_id], references: [user_id], onDelete: Cascade, onUpdate: NoAction, map: "website_ibfk_1") account account @relation(fields: [user_id], references: [user_id], onDelete: Cascade, onUpdate: NoAction, map: "website_ibfk_1")
event event[] event event[]

View File

@ -1,5 +1,5 @@
-- AlterTable -- AlterTable
ALTER TABLE "event" ADD COLUMN "event_name" VARCHAR(50); ALTER TABLE event RENAME TO event_old;
-- CreateTable -- CreateTable
CREATE TABLE "event_data" ( CREATE TABLE "event_data" (
@ -37,7 +37,7 @@ ALTER INDEX "website.website_uuid_unique" RENAME TO "website_website_uuid_key";
*/ */
-- Populate event_name -- Populate event_name
update event update event
set "event_name" = event.event_value || '-' || event.event_type; set "event_name" = event.event_value;
-- Set event_name not null -- Set event_name not null
ALTER TABLE "event" ALTER COLUMN "event_name" SET NOT NULL; ALTER TABLE "event" ALTER COLUMN "event_name" SET NOT NULL;

View File

@ -182,7 +182,7 @@ export function getFilterQuery(table, column, filters = {}, params = []) {
} }
break; break;
case 'event_type': case 'event_name':
if (table === 'event') { if (table === 'event') {
arr.push(`and ${table}.${key}=$${params.length + 1}`); arr.push(`and ${table}.${key}=$${params.length + 1}`);
params.push(decodeURIComponent(filter)); params.push(decodeURIComponent(filter));
@ -212,17 +212,17 @@ export function getFilterQuery(table, column, filters = {}, params = []) {
} }
export function parseFilters(table, column, filters = {}, params = [], sessionKey = 'session_id') { export function parseFilters(table, column, filters = {}, params = [], sessionKey = 'session_id') {
const { domain, url, event_url, referrer, os, browser, device, country, event_type } = filters; const { domain, url, event_url, referrer, os, browser, device, country, event_name } = filters;
const pageviewFilters = { domain, url, referrer }; const pageviewFilters = { domain, url, referrer };
const sessionFilters = { os, browser, device, country }; const sessionFilters = { os, browser, device, country };
const eventFilters = { url: event_url, event_type }; const eventFilters = { url: event_url, event_name };
return { return {
pageviewFilters, pageviewFilters,
sessionFilters, sessionFilters,
eventFilters, eventFilters,
event: { event_type }, event: { event_name },
joinSession: joinSession:
os || browser || device || country os || browser || device || country
? `inner join session on ${table}.${sessionKey} = session.${sessionKey}` ? `inner join session on ${table}.${sessionKey} = session.${sessionKey}`

View File

@ -65,7 +65,7 @@ export default async (req, res) => {
const { type, payload } = getJsonBody(req); const { type, payload } = getJsonBody(req);
let { url, referrer, event_type, event_value } = payload; let { url, referrer, event_name, event_data } = payload;
if (process.env.REMOVE_TRAILING_SLASH) { if (process.env.REMOVE_TRAILING_SLASH) {
url = removeTrailingSlash(url); url = removeTrailingSlash(url);
@ -74,7 +74,7 @@ export default async (req, res) => {
if (type === 'pageview') { if (type === 'pageview') {
await savePageView(website_id, { session_id, session_uuid, url, referrer }); await savePageView(website_id, { session_id, session_uuid, url, referrer });
} else if (type === 'event') { } else if (type === 'event') {
await saveEvent(website_id, { session_id, session_uuid, url, event_type, event_value }); await saveEvent(website_id, { session_id, session_uuid, url, event_name, event_data });
} else { } else {
return badRequest(res); return badRequest(res);
} }

View File

@ -14,7 +14,7 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const { id, start_at, end_at, unit, tz, url, event_type } = req.query; const { id, start_at, end_at, unit, tz, url, event_name } = req.query;
if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) { if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) {
return badRequest(res); return badRequest(res);
@ -26,7 +26,7 @@ export default async (req, res) => {
const events = await getEventMetrics(websiteId, startDate, endDate, tz, unit, { const events = await getEventMetrics(websiteId, startDate, endDate, tz, unit, {
url, url,
event_type, event_name,
}); });
return ok(res, events); return ok(res, events);

View File

@ -22,7 +22,8 @@ function getTable(type) {
function getColumn(type) { function getColumn(type) {
if (type === 'event') { if (type === 'event') {
return `concat(event_type, '\t', event_value)`; //return `concat(event_type, '\t', event_value)`;
return `event_name`;
} }
return type; return type;
} }

View File

@ -29,7 +29,7 @@ async function relationalQuery(
return rawQuery( return rawQuery(
` `
select select
event_value x, event_name x,
${getDateQuery('created_at', unit, timezone)} t, ${getDateQuery('created_at', unit, timezone)} t,
count(*) y count(*) y
from event from event

View File

@ -40,7 +40,7 @@ function clickhouseQuery(websites, start_at) {
session_id, session_id,
created_at, created_at,
url, url,
event_type event_name
from event from event
where website_id in (${websites.join[',']} where website_id in (${websites.join[',']}
and created_at >= ${getDateFormatClickhouse(start_at)}) and created_at >= ${getDateFormatClickhouse(start_at)})

View File

@ -14,33 +14,36 @@ export async function saveEvent(...args) {
}); });
} }
async function relationalQuery(website_id, { session_id, url, event_type, event_value }) { async function relationalQuery(website_id, { session_id, url, event_name, event_data }) {
const data = {
website_id,
session_id,
url: url?.substr(0, URL_LENGTH),
event_name: event_name?.substr(0, 50),
};
if (event_data) {
data.eventData = {
create: {
eventData: event_data,
},
};
}
return runQuery( return runQuery(
prisma.event.create({ prisma.event.create({
data: { data,
website_id,
session_id,
url: url?.substr(0, URL_LENGTH),
event_type: event_type?.substr(0, 50),
event_value: event_value?.substr(0, 50),
},
}), }),
); );
} }
async function clickhouseQuery(website_id, { session_uuid, url, event_type, event_value }) { async function clickhouseQuery(website_id, { session_uuid, url, event_name }) {
const params = [ const params = [website_id, session_uuid, url?.substr(0, URL_LENGTH), event_name?.substr(0, 50)];
website_id,
session_uuid,
url?.substr(0, URL_LENGTH),
event_type?.substr(0, 50),
event_value?.substr(0, 50),
];
return rawQueryClickhouse( return rawQueryClickhouse(
` `
insert into umami_dev.event (created_at, website_id, session_uuid, url, event_type, event_value) insert into umami_dev.event (created_at, website_id, session_uuid, url, event_name)
values (${getDateFormatClickhouse(new Date())}, $1, $2, $3, $4, $5);`, values (${getDateFormatClickhouse(new Date())}, $1, $2, $3, $4);`,
params, params,
); );
} }

View File

@ -97,25 +97,24 @@ import { removeTrailingSlash } from '../lib/url';
); );
}; };
const trackEvent = (event_value, event_type = 'custom', url = currentUrl, uuid = website) => { const trackEvent = (event_name = 'custom', event_data, url = currentUrl, uuid = website) => {
collect( collect(
'event', 'event',
assign(getPayload(), { assign(getPayload(), {
website: uuid, website: uuid,
url, url,
event_type, event_name,
event_value, event_data,
}), }),
); );
}; };
/* Handle events */ /* Handle events */
const sendEvent = (value, type) => { const sendEvent = name => {
const payload = getPayload(); const payload = getPayload();
payload.event_type = type; payload.event_name = name;
payload.event_value = value;
const data = JSON.stringify({ const data = JSON.stringify({
type: 'event', type: 'event',
@ -138,14 +137,15 @@ import { removeTrailingSlash } from '../lib/url';
(element.getAttribute('class') || '').split(' ').forEach(className => { (element.getAttribute('class') || '').split(' ').forEach(className => {
if (!eventClass.test(className)) return; if (!eventClass.test(className)) return;
const [, type, value] = className.split('--'); const [, type, name] = className.split('--');
const listener = listeners[className] const listener = listeners[className]
? listeners[className] ? listeners[className]
: (listeners[className] = () => { : (listeners[className] = () => {
if (element.tagName === 'A') { if (element.tagName === 'A') {
sendEvent(value, type); sendEvent(name);
} else { } else {
trackEvent(value, type); trackEvent(name);
} }
}); });