feat: telemetry add workspaceId and eventName

This commit is contained in:
moonrailgun 2023-09-18 00:13:03 +08:00
parent bd15e47765
commit 66f713e8f6
4 changed files with 91 additions and 41 deletions

View File

@ -106,7 +106,6 @@ model WebsiteEvent {
id String @id() @default(uuid()) @db.Uuid
websiteId String @db.Uuid
sessionId String @db.Uuid
createdAt DateTime? @default(now()) @db.Timestamptz(6)
urlPath String @db.VarChar(500)
urlQuery String? @db.VarChar(500)
referrerPath String? @db.VarChar(500)
@ -115,6 +114,7 @@ model WebsiteEvent {
pageTitle String? @db.VarChar(500)
eventType Int @default(1) @db.Integer
eventName String? @db.VarChar(50)
createdAt DateTime? @default(now()) @db.Timestamptz(6)
eventData WebsiteEventData[]
session WebsiteSession @relation(fields: [sessionId], references: [id])
@ -173,6 +173,7 @@ model WebsiteSessionData {
model TelemetrySession {
id String @id @unique @db.Uuid
workspaceId String @db.Uuid
hostname String? @db.VarChar(100)
browser String? @db.VarChar(20)
os String? @db.VarChar(20)
@ -185,17 +186,22 @@ model TelemetrySession {
telemetryEvent TelemetryEvent[]
@@index([createdAt])
@@index([workspaceId, createdAt])
}
model TelemetryEvent {
id String @id() @default(uuid()) @db.Uuid
sessionId String @db.Uuid
createdAt DateTime? @default(now()) @db.Timestamptz(6)
workspaceId String @db.Uuid
eventName String? @db.VarChar(100)
urlOrigin String @db.VarChar(500)
urlPath String @db.VarChar(500)
createdAt DateTime? @default(now()) @db.Timestamptz(6)
session TelemetrySession @relation(fields: [sessionId], references: [id])
@@index([createdAt])
@@index([sessionId])
@@index([workspaceId])
@@index([workspaceId, createdAt])
}

View File

@ -9,17 +9,25 @@ export async function recordTelemetryEvent(req: Request) {
if (!(url && typeof url === 'string')) {
return;
}
const eventName = req.query.name ? String(req.query.name) : undefined;
const session = await findSession(req, url);
if (!session) {
return;
}
const workspaceId = req.params.workspaceId;
if (!workspaceId) {
return;
}
const { origin, pathname } = new URL(url);
await prisma.telemetryEvent.create({
data: {
sessionId: session.id,
workspaceId,
eventName,
urlOrigin: origin,
urlPath: pathname,
},
@ -32,10 +40,19 @@ export async function sumTelemetryEvent(req: Request): Promise<number> {
return 0;
}
const eventName = req.query.name ? String(req.query.name) : undefined;
const workspaceId = req.params.workspaceId;
if (!workspaceId) {
return 0;
}
const { origin, pathname } = new URL(url);
const number = await prisma.telemetryEvent.count({
where: {
workspaceId,
eventName,
urlOrigin: origin,
urlPath: pathname,
},
@ -46,6 +63,10 @@ export async function sumTelemetryEvent(req: Request): Promise<number> {
async function findSession(req: Request, url: string) {
const { hostname } = new URL(url);
const workspaceId = req.params.workspaceId;
if (!workspaceId) {
throw new Error('Not found workspaceId');
}
const {
userAgent,
@ -58,7 +79,7 @@ async function findSession(req: Request, url: string) {
city,
} = await getRequestInfo(req);
const sessionId = hashUuid(hostname, ip, userAgent!);
const sessionId = hashUuid(workspaceId, hostname, ip, userAgent!);
let session = await loadSession(sessionId);
if (!session) {
@ -66,6 +87,7 @@ async function findSession(req: Request, url: string) {
session = await prisma.telemetrySession.create({
data: {
id: sessionId,
workspaceId,
hostname,
browser,
os,

View File

@ -1,7 +1,6 @@
import { prisma } from './_client';
import { QueryFilters, parseFilters, getDateQuery } from '../utils/prisma';
import { DEFAULT_RESET_DATE, EVENT_TYPE } from '../utils/const';
import { Prisma } from '@prisma/client';
export async function getWorkspaceUser(workspaceId: string, userId: string) {
const info = await prisma.workspacesOnUsers.findFirst({
@ -27,6 +26,14 @@ export async function checkIsWorkspaceUser(
}
}
export async function getWorkspace(workspaceId: string) {
return prisma.workspace.findUnique({
where: {
id: workspaceId,
},
});
}
export async function getWorkspaceWebsites(workspaceId: string) {
const workspace = await prisma.workspace.findUnique({
where: {

View File

@ -1,11 +1,18 @@
import { Router } from 'express';
import { query, validate } from '../middleware/validate';
import { recordTelemetryEvent, sumTelemetryEvent } from '../model/telemetry';
import { numify } from '../utils/common';
const openBadge = require('openbadge');
export const telemetryRouter = Router();
telemetryRouter.get('/blank.gif', async (req, res) => {
telemetryRouter.get(
'/:workspaceId/blank.gif',
validate(
query('name').optional().isString(),
query('url').optional().isURL()
),
async (req, res) => {
const buffer = Buffer.from(
'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7',
'base64'
@ -14,9 +21,16 @@ telemetryRouter.get('/blank.gif', async (req, res) => {
recordTelemetryEvent(req);
res.header('Content-Type', 'image/gif').send(buffer);
});
}
);
telemetryRouter.get('/badge.svg', async (req, res) => {
telemetryRouter.get(
'/:workspaceId/badge.svg',
validate(
query('name').optional().isString(),
query('url').optional().isURL()
),
async (req, res) => {
const title = req.query.title || 'visitor';
const start = req.query.start ? Number(req.query.start) : 0;
@ -39,4 +53,5 @@ telemetryRouter.get('/badge.svg', async (req, res) => {
});
res.header('Content-Type', 'image/svg+xml').send(svg);
});
}
);