| 147 | } |
| 148 | |
| 149 | async function inspectClickhouse( |
| 150 | projects: string[] | null, |
| 151 | hours: number |
| 152 | ): Promise<Map<string, ChCounts>> { |
| 153 | const projectClause = projects?.length |
| 154 | ? `AND project_id IN (${projects.map((p) => `'${p.replace(/'/g, "''")}'`).join(',')})` |
| 155 | : ''; |
| 156 | const query = ` |
| 157 | SELECT |
| 158 | project_id, |
| 159 | name, |
| 160 | sum(if(created_at > now() - INTERVAL 1 HOUR, 1, 0)) AS h1, |
| 161 | sum(if(created_at > now() - INTERVAL ${hours} HOUR, 1, 0)) AS hN |
| 162 | FROM events |
| 163 | WHERE name IN ('session_start', 'session_end') |
| 164 | AND created_at > now() - INTERVAL ${hours} HOUR |
| 165 | ${projectClause} |
| 166 | GROUP BY project_id, name |
| 167 | `; |
| 168 | const res = await ch.query({ query, format: 'JSONEachRow' }); |
| 169 | const rows = await res.json<{ |
| 170 | project_id: string; |
| 171 | name: string; |
| 172 | h1: string; |
| 173 | hN: string; |
| 174 | }>(); |
| 175 | |
| 176 | const byProject = new Map<string, ChCounts>(); |
| 177 | for (const r of rows) { |
| 178 | const cur = byProject.get(r.project_id) ?? { |
| 179 | starts1h: 0, |
| 180 | ends1h: 0, |
| 181 | starts24h: 0, |
| 182 | ends24h: 0, |
| 183 | }; |
| 184 | if (r.name === 'session_start') { |
| 185 | cur.starts1h = Number(r.h1); |
| 186 | cur.starts24h = Number(r.hN); |
| 187 | } else { |
| 188 | cur.ends1h = Number(r.h1); |
| 189 | cur.ends24h = Number(r.hN); |
| 190 | } |
| 191 | byProject.set(r.project_id, cur); |
| 192 | } |
| 193 | return byProject; |
| 194 | } |
| 195 | |
| 196 | async function inspectSessionEndClaims() { |
| 197 | const redis = getRedisCache(); |