feat(telemetry): geo distribution endpoint (GET /telemetry/geo) with Cosmos GROUP BY aggregation
This commit is contained in:
parent
70fa6f4738
commit
0bfd4bdf22
@ -113,6 +113,35 @@ export async function queryEvents(
|
||||
};
|
||||
}
|
||||
|
||||
export async function queryGeoDistribution(
|
||||
productId: string,
|
||||
from?: string,
|
||||
to?: string
|
||||
): Promise<Array<{ countryCode: string; count: number }>> {
|
||||
const conditions: string[] = [
|
||||
'c.productId = @productId',
|
||||
'IS_DEFINED(c.countryCode)',
|
||||
'c.countryCode != null',
|
||||
];
|
||||
const parameters: Array<{ name: string; value: string }> = [
|
||||
{ name: '@productId', value: productId },
|
||||
];
|
||||
if (from) {
|
||||
conditions.push('c.occurredAt >= @from');
|
||||
parameters.push({ name: '@from', value: from });
|
||||
}
|
||||
if (to) {
|
||||
conditions.push('c.occurredAt <= @to');
|
||||
parameters.push({ name: '@to', value: to });
|
||||
}
|
||||
|
||||
const query = `SELECT c.countryCode, COUNT(1) AS count FROM c WHERE ${conditions.join(' AND ')} GROUP BY c.countryCode`;
|
||||
const { resources } = await eventsContainer()
|
||||
.items.query<{ countryCode: string; count: number }>({ query, parameters })
|
||||
.fetchAll();
|
||||
return resources.sort((a, b) => b.count - a.count);
|
||||
}
|
||||
|
||||
export async function deleteEventsByUserId(productId: string, userId: string): Promise<number> {
|
||||
// Find all events for this user, then delete them
|
||||
const { resources } = await eventsContainer()
|
||||
|
||||
@ -880,6 +880,15 @@ export async function telemetryRoutes(app: FastifyInstance) {
|
||||
return updated;
|
||||
});
|
||||
|
||||
// ── Admin: geo distribution ─────────────────────────────
|
||||
app.get('/telemetry/geo', async req => {
|
||||
requireAdmin(req);
|
||||
const productId = getRequestProductId(req);
|
||||
const { from, to } = req.query as { from?: string; to?: string };
|
||||
const distribution = await repo.queryGeoDistribution(productId, from, to);
|
||||
return { distribution };
|
||||
});
|
||||
|
||||
// ── Admin: ingestion metrics (JSON) ─────────────────────
|
||||
app.get('/telemetry/metrics', async req => {
|
||||
requireAdmin(req);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user