Skip to content

Commit d81be1a

Browse files
committed
feat: add project metric
1 parent bcd4407 commit d81be1a

File tree

1 file changed

+80
-19
lines changed
  • services/libs/data-access-layer/src/dashboards

1 file changed

+80
-19
lines changed

services/libs/data-access-layer/src/dashboards/base.ts

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,53 @@ export async function getMetrics(
66
qx: QueryExecutor,
77
segmentId?: string,
88
): Promise<IDashboardMetrics> {
9+
try {
10+
const [snapshotData, projectsData] = await Promise.all([
11+
getSnapshotMetrics(qx, segmentId),
12+
getProjectsCount(qx, segmentId),
13+
])
14+
15+
if (!snapshotData) {
16+
// TODO: remove this mock once Tinybird sinks are available
17+
const mockMetrics = getMockMetrics()
18+
return {
19+
...mockMetrics,
20+
projectsTotal: projectsData.projectsTotal,
21+
projectsLast30Days: projectsData.projectsLast30Days,
22+
}
23+
}
24+
25+
return {
26+
...snapshotData,
27+
projectsTotal: projectsData.projectsTotal,
28+
projectsLast30Days: projectsData.projectsLast30Days,
29+
}
30+
} catch (error: unknown) {
31+
const msg = error instanceof Error ? error.message : ''
32+
const code = error && typeof error === 'object' && 'code' in error ? error.code : null
33+
34+
// Detect missing table
35+
const isMissingTable = code === '42P01' || /does not exist/i.test(msg)
36+
37+
if (isMissingTable) {
38+
// TODO: remove this mock once Tinybird sinks are available
39+
const mockMetrics = getMockMetrics()
40+
const projectsData = await getProjectsCount(qx, segmentId)
41+
return {
42+
...mockMetrics,
43+
projectsTotal: projectsData.projectsTotal,
44+
projectsLast30Days: projectsData.projectsLast30Days,
45+
}
46+
}
47+
48+
throw error
49+
}
50+
}
51+
52+
async function getSnapshotMetrics(
53+
qx: QueryExecutor,
54+
segmentId?: string,
55+
): Promise<Omit<IDashboardMetrics, 'projectsTotal' | 'projectsLast30Days'> | null> {
956
const tableName = segmentId
1057
? 'dashboardMetricsPerSegmentSnapshot'
1158
: 'dashboardMetricsTotalSnapshot'
@@ -31,29 +78,43 @@ export async function getMetrics(
3178
`
3279

3380
const params = segmentId ? { segmentId } : {}
81+
const [row] = await qx.select(query, params)
3482

35-
try {
36-
const [row] = await qx.select(query, params)
37-
38-
if (!row) {
39-
// TODO: remove this mock once Tinybird sinks are available
40-
return getMockMetrics()
41-
}
42-
43-
return row
44-
} catch (error: unknown) {
45-
const msg = error instanceof Error ? error.message : ''
46-
const code = error && typeof error === 'object' && 'code' in error ? error.code : null
83+
return row || null
84+
}
4785

48-
// Detect missing table
49-
const isMissingTable = code === '42P01' || /does not exist/i.test(msg)
86+
async function getProjectsCount(
87+
qx: QueryExecutor,
88+
segmentId?: string,
89+
): Promise<{ projectsTotal: number; projectsLast30Days: number }> {
90+
let query: string
91+
let params: Record<string, any>
5092

51-
if (isMissingTable) {
52-
// TODO: remove this mock once Tinybird sinks are available
53-
return getMockMetrics()
54-
}
93+
if (!segmentId) {
94+
// Count all segments
95+
query = `
96+
SELECT
97+
COUNT(*) as "projectsTotal",
98+
COUNT(CASE WHEN "createdAt" >= NOW() - INTERVAL '30 days' THEN 1 END) as "projectsLast30Days"
99+
FROM segments
100+
`
101+
params = {}
102+
} else {
103+
// Count segments where the provided segmentId is current, parent, or grandparent
104+
query = `
105+
SELECT
106+
COUNT(*) as "projectsTotal",
107+
COUNT(CASE WHEN s."createdAt" >= NOW() - INTERVAL '30 days' THEN 1 END) as "projectsLast30Days"
108+
FROM segments s
109+
WHERE (s.id = $(segmentId) OR s."parentId" = $(segmentId) OR s."grandparentId" = $(segmentId))
110+
`
111+
params = { segmentId }
112+
}
55113

56-
throw error
114+
const [result] = await qx.select(query, params)
115+
return {
116+
projectsTotal: parseInt(result.projectsTotal) || 0,
117+
projectsLast30Days: parseInt(result.projectsLast30Days) || 0,
57118
}
58119
}
59120

0 commit comments

Comments
 (0)