Code Demo · TypeScript · Typed Pipeline

typescript
type Event = { service: string; durationMs: number; ok: boolean };

function groupBy<T, K extends PropertyKey>(items: T[], keyOf: (item: T) => K) {
  return items.reduce<Record<K, T[]>>((groups, item) => {
    const key = keyOf(item);
    const bucket = groups[key] || [];
    bucket.push(item);
    groups[key] = bucket;
    return groups;
  }, {} as Record<K, T[]>);
}

const events: Event[] = [
  { service: 'api', durationMs: 120, ok: true },
  { service: 'api', durationMs: 280, ok: false },
  { service: 'worker', durationMs: 90, ok: true },
];

const report = Object.entries(groupBy(events, (event) => event.service)).map(([service, rows]) => ({
  service,
  requests: rows.length,
  successRate: rows.filter((row) => row.ok).length / rows.length,
  averageMs: rows.reduce((sum, row) => sum + row.durationMs, 0) / rows.length,
}));

console.log(report);
860 characters26 lines< 2.5 KB