From 7460ad5ed4ae028de50845d6e482bae1edaad23e Mon Sep 17 00:00:00 2001 From: Emily Date: Tue, 11 Jun 2024 18:41:45 +0200 Subject: [PATCH] adding event tracker --- dashboard/pages/test.vue | 68 +++++++++++++++++++ .../events/metadata_field_group.ts | 31 +++++++++ .../[project_id]/events/metadata_fields.ts | 33 +++++++++ .../api/metrics/[project_id]/events/names.ts | 13 +--- dashboard/server/api/user/max_projects.ts | 9 +++ dashboard/server/services/CacheService.ts | 2 + shared/schema/metrics/EventSchema.ts | 2 +- 7 files changed, 146 insertions(+), 12 deletions(-) create mode 100644 dashboard/pages/test.vue create mode 100644 dashboard/server/api/metrics/[project_id]/events/metadata_field_group.ts create mode 100644 dashboard/server/api/metrics/[project_id]/events/metadata_fields.ts create mode 100644 dashboard/server/api/user/max_projects.ts diff --git a/dashboard/pages/test.vue b/dashboard/pages/test.vue new file mode 100644 index 0000000..9a6c7d1 --- /dev/null +++ b/dashboard/pages/test.vue @@ -0,0 +1,68 @@ + + + + \ No newline at end of file diff --git a/dashboard/server/api/metrics/[project_id]/events/metadata_field_group.ts b/dashboard/server/api/metrics/[project_id]/events/metadata_field_group.ts new file mode 100644 index 0000000..b511252 --- /dev/null +++ b/dashboard/server/api/metrics/[project_id]/events/metadata_field_group.ts @@ -0,0 +1,31 @@ + +import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA"; +import { EventModel } from "@schema/metrics/EventSchema"; +import { EVENT_METADATA_FIELDS_EXPIRE_TIME, Redis } from "~/server/services/CacheService"; + + +export default defineEventHandler(async event => { + + const project_id = getRequestProjectId(event); + if (!project_id) return; + + const user = getRequestUser(event); + + const project = await getUserProjectFromId(project_id, user); + if (!project) return; + + const { name: eventName, field } = getQuery(event); + if (!eventName || !field) return []; + + const aggregation = [ + { $match: { project_id: project._id, name: eventName } }, + { $group: { _id: `$metadata.${field}`, count: { $sum: 1 } } } + ] + + const metadataGrouped = await EventModel.aggregate(aggregation); + + console.log(metadataGrouped); + return metadataGrouped; + + +}); \ No newline at end of file diff --git a/dashboard/server/api/metrics/[project_id]/events/metadata_fields.ts b/dashboard/server/api/metrics/[project_id]/events/metadata_fields.ts new file mode 100644 index 0000000..69f1bfa --- /dev/null +++ b/dashboard/server/api/metrics/[project_id]/events/metadata_fields.ts @@ -0,0 +1,33 @@ + +import { getUserProjectFromId } from "~/server/LIVE_DEMO_DATA"; +import { EventModel } from "@schema/metrics/EventSchema"; +import { EVENT_METADATA_FIELDS_EXPIRE_TIME, Redis } from "~/server/services/CacheService"; + + +export default defineEventHandler(async event => { + + const project_id = getRequestProjectId(event); + if (!project_id) return; + + const user = getRequestUser(event); + + const project = await getUserProjectFromId(project_id, user); + if (!project) return; + + const { name: eventName } = getQuery(event); + if (!eventName) return []; + + const fields: string[] = await Redis.useCache({ key: `metadata_fields:${project_id}:${eventName}`, exp: EVENT_METADATA_FIELDS_EXPIRE_TIME }, async () => { + const eventsWithName = await EventModel.find({ project_id, name: eventName }, { metadata: 1 }, { limit: 10, sort: { created_at: -1 } }); + const allMetadata = eventsWithName.map(e => e.metadata); + const allFields = new Set(); + for (const metadata of allMetadata) { + const keys = Object.keys(metadata || {}); + keys.forEach(key => allFields.add(key)); + } + return Array.from(allFields.values()); + }); + + return fields; + +}); \ No newline at end of file diff --git a/dashboard/server/api/metrics/[project_id]/events/names.ts b/dashboard/server/api/metrics/[project_id]/events/names.ts index 3cf18bc..c12d69f 100644 --- a/dashboard/server/api/metrics/[project_id]/events/names.ts +++ b/dashboard/server/api/metrics/[project_id]/events/names.ts @@ -14,18 +14,9 @@ export default defineEventHandler(async event => { const project = await getUserProjectFromId(project_id, user); if (!project) return; - const names: string[] = await Redis.useCache({ - key: `counts:${project_id}:event_names`, - exp: EVENT_NAMES_EXPIRE_TIME - }, async () => { - - const namesAggregation = await EventModel.aggregate([ - { $match: { project_id: project._id } }, - { $group: { _id: "$name" } } - ]); - + const names: string[] = await Redis.useCache({ key: `event_names:${project_id}`, exp: EVENT_NAMES_EXPIRE_TIME }, async () => { + const namesAggregation = await EventModel.aggregate([{ $match: { project_id: project._id } }, { $group: { _id: "$name" } }]); return namesAggregation.map(e => e._id); - }); return names; diff --git a/dashboard/server/api/user/max_projects.ts b/dashboard/server/api/user/max_projects.ts new file mode 100644 index 0000000..cc82c41 --- /dev/null +++ b/dashboard/server/api/user/max_projects.ts @@ -0,0 +1,9 @@ +import { UserSettingsModel } from "@schema/UserSettings"; +import { AuthContext } from "~/server/middleware/01-authorization"; + +export default defineEventHandler(async event => { + const userData: AuthContext = getRequestUser(event) as any; + if (!userData.logged) return; + const userSettings = await UserSettingsModel.findOne({ user_id: userData.id }, { max_projects: 1 }); + return userSettings?.max_projects || 3; +}); \ No newline at end of file diff --git a/dashboard/server/services/CacheService.ts b/dashboard/server/services/CacheService.ts index 535cda3..62cafc0 100644 --- a/dashboard/server/services/CacheService.ts +++ b/dashboard/server/services/CacheService.ts @@ -12,6 +12,8 @@ export const COUNTS_SESSIONS_EXPIRE_TIME = 60 * 3; export const EVENT_NAMES_EXPIRE_TIME = 60; +export const EVENT_METADATA_FIELDS_EXPIRE_TIME = 120; + export class Redis { diff --git a/shared/schema/metrics/EventSchema.ts b/shared/schema/metrics/EventSchema.ts index 2a11723..a0c17d2 100644 --- a/shared/schema/metrics/EventSchema.ts +++ b/shared/schema/metrics/EventSchema.ts @@ -11,7 +11,7 @@ export type TEvent = { const EventSchema = new Schema({ project_id: { type: Types.ObjectId, index: 1 }, - name: { type: String, required: true }, + name: { type: String, required: true, index: 1 }, metadata: Schema.Types.Mixed, session: { type: String }, flowHash: { type: String },