/
histogram.ts
103 lines (86 loc) · 2.56 KB
/
histogram.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import { Collector } from "./collector.ts";
import { Labels, Metric, Observe } from "./metric.ts";
import { Registry } from "./registry.ts";
export class Histogram extends Metric implements Observe {
private collector: Collector;
private buckets: number[];
private count: number;
private sum: number;
private values: number[];
static with(
config: {
name: string;
help: string;
labels?: string[];
buckets: number[];
registry?: Registry[];
},
): Histogram {
const collector = new Collector(
config.name,
config.help,
"histogram",
config.registry,
);
const labels = config.labels || [];
const buckets = config.buckets || [];
buckets.push(Infinity);
return new Histogram(collector, labels, buckets);
}
private constructor(
collector: Collector,
labels: string[],
buckets: number[],
) {
super(labels, new Array(labels.length).fill(undefined));
this.collector = collector;
this.buckets = buckets.sort((a, b) => a < b ? -1 : 1);
this.count = 0;
this.sum = 0;
this.values = new Array(this.buckets.length).fill(0);
this.collector.getOrSetMetric(this);
}
get description(): string {
const labels = this.getLabelsAsString();
return `${this.collector.name}${labels}`;
}
expose(): string | undefined {
if (this.count == 0) {
return undefined;
}
let text = "";
for (let i = 0; i < this.buckets.length; i++) {
let labels = this.getLabelsAsString({ le: `${this.buckets[i]}` });
labels = labels.replace("Infinity", "+Inf");
text += `${this.collector.name}_bucket${labels} ${this.values[i]}\n`;
}
const labels = this.getLabelsAsString();
text += `${this.collector.name}_sum${labels} ${this.sum}\n`;
text += `${this.collector.name}_count${labels} ${this.count}`;
return text;
}
labels(labels: Labels): Observe {
let child = new Histogram(this.collector, this.labelNames, this.buckets);
for (const key of Object.keys(labels)) {
const index = child.labelNames.indexOf(key);
if (index === -1) {
throw new Error(`label with name ${key} not defined`);
}
child.labelValues[index] = labels[key];
}
child = child.collector.getOrSetMetric(child) as Histogram;
return {
observe: (n) => {
child.observe(n);
},
};
}
observe(n: number) {
const index = this.buckets.findIndex((v) => v >= n);
for (let i = index; i < this.values.length; i++) {
this.values[i] += 1;
}
this.sum += n;
this.count += 1;
}
}