Skip to content

Instantly share code, notes, and snippets.

@mitsuhiko
Created August 19, 2023 13:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mitsuhiko/79cee882eae2ab479c34e4a4b7032161 to your computer and use it in GitHub Desktop.
Save mitsuhiko/79cee882eae2ab479c34e4a4b7032161 to your computer and use it in GitHub Desktop.
function crc32(value: string): number {
return 0xd0d0deadbeef;
}
type SerializedMetric = Array<number> | number;
interface Metric<T> {
add(value: T): void;
flush(): SerializedMetric;
}
class CounterMetric implements Metric<number> {
value = 0.0;
add(value: number): void {
this.value += value;
}
flush(): SerializedMetric {
return this.value;
}
}
class DistributionMetric implements Metric<number> {
value: Array<number> = [];
add(value: number): void {
this.value.push(value);
}
flush(): SerializedMetric {
return this.value;
}
}
class SetMetric implements Metric<string | number> {
value: Set<string | number> = new Set();
add(value: string | number): void {
this.value.add(value);
}
flush(): SerializedMetric {
return Array.from(this.value).map((v) => {
return typeof v == "string" ? crc32(v) : v;
});
}
}
const METRICS = {
c: CounterMetric,
d: DistributionMetric,
s: SetMetric,
};
type MetricTypes = {
[K in keyof typeof METRICS]: InstanceType<typeof METRICS[K]>
}
type MetricType = keyof MetricTypes;
type ExtractMetricValue<T> = T extends Metric<infer V> ? V : never;
type MetricValue<T extends keyof MetricTypes> = ExtractMetricValue<MetricTypes[T]>;
class Aggregator {
buckets: Record<string, Metric<unknown>> = {};
add<T extends MetricType, V extends MetricValue<T>>(
ty: T,
key: string,
value: V,
timestamp?: Date,
) {
let ts = Math.floor(+(timestamp || new Date) / 10000);
let bucket = `${ty}|${key}|${ts}`;
let agg = this.buckets[bucket];
if (!agg) {
agg = new METRICS[ty]();
this.buckets[bucket] = agg;
}
agg.add(value);
}
}
class Client {
aggregator = new Aggregator();
incr(key: string, value: number, timestamp?: Date): void {
this.aggregator.add("c", key, value, timestamp);
}
timing(key: string, value: number, timestamp?: Date): void {
this.aggregator.add("d", key, value, timestamp);
}
set(key: string, value: number | string, timestamp?: Date): void {
this.aggregator.add("s", key, value, timestamp);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment