add funnels

This commit is contained in:
Carl-Gerhard Lindesvärd
2024-02-24 07:22:39 +01:00
parent 9c92803c4c
commit 15388882be
34 changed files with 916 additions and 131 deletions

View File

@@ -4,6 +4,7 @@ CREATE TABLE openpanel.events (
`device_id` String,
`profile_id` String,
`project_id` String,
`session_id` String,
`path` String,
`referrer` String,
`referrer_name` String,
@@ -56,9 +57,9 @@ ORDER BY
ALTER TABLE
events
ADD
COLUMN device_id String
COLUMN session_id String
AFTER
name;
project_id;
ALTER TABLE
events DROP COLUMN id;
@@ -69,4 +70,4 @@ CREATE TABLE ba (
`b` String
) ENGINE MergeTree
ORDER BY
(a, b) SETTINGS index_granularity = 8192;
(a, b) SETTINGS index_granularity = 8192;

View File

@@ -0,0 +1,2 @@
-- AlterEnum
ALTER TYPE "ChartType" ADD VALUE 'funnel';

View File

@@ -98,6 +98,7 @@ enum ChartType {
metric
area
map
funnel
}
model Dashboard {

View File

@@ -0,0 +1,101 @@
import { createEvent } from '../src/services/event.service';
function c(name: string, createdAt: Date, session_id: string) {
return createEvent({
name,
deviceId: '',
profileId: '',
projectId: '',
sessionId: session_id,
properties: {},
createdAt,
country: '',
city: '',
region: '',
continent: '',
os: '',
osVersion: '',
browser: '',
browserVersion: '',
device: '',
brand: '',
model: '',
duration: 0,
path: '/',
referrer: '',
referrerName: '',
referrerType: '',
profile: undefined,
meta: undefined,
});
}
async function main() {
// Level 5
const s = Math.random().toString(36).substring(7);
await c('session_start', new Date('2024-02-24 10:10:00'), s);
// // Level 2
// s = 's2';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// // Level 5
// s = 's3';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// await c('c', new Date('2024-02-24 10:10:03'), s);
// await c('d', new Date('2024-02-24 10:10:04'), s);
// await c('f', new Date('2024-02-24 10:10:10'), s);
// // Level 4
// s = 's4';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// await c('c', new Date('2024-02-24 10:10:03'), s);
// await c('d', new Date('2024-02-24 10:10:04'), s);
// // Level 3
// s = 's5';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// await c('c', new Date('2024-02-24 10:10:03'), s);
// // Level 3
// s = 's6';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// await c('c', new Date('2024-02-24 10:10:03'), s);
// // Level 2
// s = 's7';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// // Level 5
// s = 's8';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// await c('c', new Date('2024-02-24 10:10:03'), s);
// await c('d', new Date('2024-02-24 10:10:04'), s);
// await c('f', new Date('2024-02-24 10:10:10'), s);
// // Level 4
// s = 's9';
// await c('session_start', new Date('2024-02-24 10:10:00'), '');
// await c('a', new Date('2024-02-24 10:10:00'), s);
// await c('b', new Date('2024-02-24 10:10:02'), s);
// await c('c', new Date('2024-02-24 10:10:03'), s);
// await c('d', new Date('2024-02-24 10:10:04'), s);
process.exit();
}
main();

View File

@@ -24,6 +24,7 @@ export interface IClickhouseEvent {
device_id: string;
profile_id: string;
project_id: string;
session_id: string;
path: string;
referrer: string;
referrer_name: string;
@@ -56,6 +57,7 @@ export function transformEvent(
deviceId: event.device_id,
profileId: event.profile_id,
projectId: event.project_id,
sessionId: event.session_id,
properties: event.properties,
createdAt: convertClickhouseDateToJs(event.created_at),
country: event.country,
@@ -84,6 +86,7 @@ export interface IServiceCreateEventPayload {
deviceId: string;
profileId: string;
projectId: string;
sessionId: string;
properties: Record<string, unknown> & {
hash?: string;
query?: Record<string, unknown>;
@@ -162,7 +165,7 @@ export async function createEvent(
);
const exists = await getProfileById(payload.profileId);
if (!exists) {
if (!exists && payload.profileId !== '') {
const { firstName, lastName } = randomSplitName();
await upsertProfile({
id: payload.profileId,
@@ -198,6 +201,7 @@ export async function createEvent(
device_id: payload.deviceId,
profile_id: payload.profileId,
project_id: payload.projectId,
session_id: payload.sessionId,
properties: toDots(omit(['_path'], payload.properties)),
path: payload.path ?? '',
created_at: formatClickhouseDate(payload.createdAt),

View File

@@ -6,6 +6,10 @@ import { createSqlBuilder } from '../sql-builder';
import { getEventFiltersWhereClause } from './chart.service';
export async function getProfileById(id: string) {
if (id === '') {
return null;
}
const [profile] = await chQuery<IClickhouseProfile>(
`SELECT * FROM profiles WHERE id = '${id}' ORDER BY created_at DESC LIMIT 1`
);

View File

@@ -14,7 +14,7 @@ export function createSqlBuilder() {
const sb: SqlBuilderObject = {
where: {},
from: 'openpanel.events',
from: 'events',
select: {},
groupBy: {},
orderBy: {},