forked from windmill-labs/windmill
-
Notifications
You must be signed in to change notification settings - Fork 0
/
scraper.ts
88 lines (78 loc) · 2.43 KB
/
scraper.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
/// <reference no-default-lib="true" />
/// <reference lib="deno.worker" />
import { sleep } from "https://deno.land/x/[email protected]/sleep.ts";
import parsePrometheusTextFormat from "npm:parse-prometheus-text-format";
const promise = new Promise<{
host: string;
histogramBuckets: string[];
exportHistograms: string[];
exportSimple: string[];
}>((resolve, _reject) => {
self.onmessage = (evt) => {
resolve(evt.data);
self.onmessage = null;
};
});
const { host, histogramBuckets, exportHistograms, exportSimple } =
await promise;
const columns = exportHistograms
.flatMap((x) => (histogramBuckets as string[]).map((b) => x + "_" + b))
.concat(exportSimple.map((x) => x + "_value"));
const values: Float32Array[] = [];
let cont = true;
self.onmessage = (_evt) => {
cont = false;
};
while (cont) {
const start = Date.now();
const response = await fetch(host);
const text = await response.text();
// TODO: parsePrometheusTextFormat seems incomplete. Consider rewriting for deno with actual completeness.
// Specifically histogram labels seem to not be reported.
const prometheusValues: [
{
name: string;
help: string;
} & (
| {
type: "COUNTER" | "GAUGE";
metrics: [{ value: string; labels: Record<string, string> }];
}
| {
type: "HISTOGRAM";
metrics: [{ buckets: Record<string, number> }];
}
)
] = parsePrometheusTextFormat(text);
const new_values: Float32Array = new Float32Array(columns.length);
prometheusValues.forEach((x) => {
if (
x.type == "HISTOGRAM" &&
exportHistograms.findIndex((e) => e == x.name) !== -1
) {
x.metrics.forEach((m) => {
histogramBuckets.forEach((e) => {
new_values[columns.indexOf(x.name + "_" + e)] = m.buckets[e];
});
});
}
if (
(x.type == "GAUGE" || x.type == "COUNTER") &&
exportSimple.findIndex((e) => e == x.name) !== -1
) {
// TODO: is there something smarter we can do then take the mean of all labels?
let v = 0;
let n = 0;
x.metrics.forEach((m) => {
n++;
v += Number(m.value);
});
new_values[columns.indexOf(x.name + "_value")] = v / n;
}
});
values.push(new_values);
const timeTaken = Date.now() - start;
await sleep((100 - timeTaken) / 1000);
}
const transfer_values = values.map((x) => x.buffer);
self.postMessage({ columns, transfer_values }, transfer_values);