@libp2p/prometheus-metrics 0.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +4 -0
- package/README.md +31 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +99 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/metric-group.d.ts +12 -0
- package/dist/src/metric-group.d.ts.map +1 -0
- package/dist/src/metric-group.js +40 -0
- package/dist/src/metric-group.js.map +1 -0
- package/dist/src/metric.d.ts +11 -0
- package/dist/src/metric.d.ts.map +1 -0
- package/dist/src/metric.js +30 -0
- package/dist/src/metric.js.map +1 -0
- package/dist/src/moving-average.d.ts +20 -0
- package/dist/src/moving-average.d.ts.map +1 -0
- package/dist/src/moving-average.js +40 -0
- package/dist/src/moving-average.js.map +1 -0
- package/dist/src/utils.d.ts +4 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +6 -0
- package/dist/src/utils.js.map +1 -0
- package/package.json +155 -0
- package/src/index.ts +135 -0
- package/src/metric-group.ts +52 -0
- package/src/metric.ts +39 -0
- package/src/utils.ts +7 -0
package/LICENSE
ADDED
package/README.md
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# @libp2p/prometheus-metrics <!-- omit in toc -->
|
|
2
|
+
|
|
3
|
+
[](http://libp2p.io/)
|
|
4
|
+
[](https://discuss.libp2p.io)
|
|
5
|
+
[](https://codecov.io/gh/libp2p/js-libp2p-prometheus-metrics)
|
|
6
|
+
[](https://github.com/libp2p/js-libp2p-prometheus-metrics/actions/workflows/js-test-and-release.yml)
|
|
7
|
+
|
|
8
|
+
> Collect libp2p metrics for scraping by Prometheus
|
|
9
|
+
|
|
10
|
+
## Table of contents <!-- omit in toc -->
|
|
11
|
+
|
|
12
|
+
- [Install](#install)
|
|
13
|
+
- [License](#license)
|
|
14
|
+
- [Contribute](#contribute)
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```console
|
|
19
|
+
$ npm i @libp2p/prometheus-metrics
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## License
|
|
23
|
+
|
|
24
|
+
Licensed under either of
|
|
25
|
+
|
|
26
|
+
- Apache 2.0, ([LICENSE-APACHE](LICENSE-APACHE) / <http://www.apache.org/licenses/LICENSE-2.0>)
|
|
27
|
+
- MIT ([LICENSE-MIT](LICENSE-MIT) / <http://opensource.org/licenses/MIT>)
|
|
28
|
+
|
|
29
|
+
## Contribute
|
|
30
|
+
|
|
31
|
+
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Metrics } from '@libp2p/interface-metrics';
|
|
2
|
+
import { DefaultMetricsCollectorConfiguration } from 'prom-client';
|
|
3
|
+
import { DefaultMetricsInit } from '@libp2p/metrics';
|
|
4
|
+
export interface PrometheusMetricsInit extends DefaultMetricsInit {
|
|
5
|
+
defaultMetrics?: DefaultMetricsCollectorConfiguration;
|
|
6
|
+
preserveExistingMetrics?: boolean;
|
|
7
|
+
collectDefaultMetrics?: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare function prometheusMetrics(init?: Partial<PrometheusMetricsInit>): () => Metrics;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAgF,OAAO,EAAE,MAAM,2BAA2B,CAAA;AAEtI,OAAO,EAAiD,oCAAoC,EAAY,MAAM,aAAa,CAAA;AAG3H,OAAO,EAAkB,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAEpE,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB;IAC/D,cAAc,CAAC,EAAE,oCAAoC,CAAA;IACrD,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,qBAAqB,CAAC,EAAE,OAAO,CAAA;CAChC;AAuHD,wBAAgB,iBAAiB,CAAE,IAAI,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG,MAAM,OAAO,CAIvF"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { Gauge, collectDefaultMetrics, register } from 'prom-client';
|
|
2
|
+
import { PrometheusMetric } from './metric.js';
|
|
3
|
+
import { PrometheusMetricGroup } from './metric-group.js';
|
|
4
|
+
import { DefaultMetrics } from '@libp2p/metrics';
|
|
5
|
+
class PrometheusMetrics extends DefaultMetrics {
|
|
6
|
+
constructor(init) {
|
|
7
|
+
super(init);
|
|
8
|
+
if (init?.preserveExistingMetrics !== true) {
|
|
9
|
+
// all metrics in prometheus are global so it's necessary to remove
|
|
10
|
+
// existing metrics to make sure we don't error when setting up metrics
|
|
11
|
+
register.clear();
|
|
12
|
+
}
|
|
13
|
+
if (init?.preserveExistingMetrics !== false) {
|
|
14
|
+
// collect memory/CPU and node-specific default metrics
|
|
15
|
+
collectDefaultMetrics(init?.defaultMetrics);
|
|
16
|
+
}
|
|
17
|
+
this.registerMetricGroup('libp2p_data_transfer_bytes', {
|
|
18
|
+
label: 'protocol',
|
|
19
|
+
calculate: () => {
|
|
20
|
+
const output = {};
|
|
21
|
+
const global = this.getGlobal().getSnapshot();
|
|
22
|
+
output['global sent'] = Number(global.dataSent);
|
|
23
|
+
output['global received'] = Number(global.dataReceived);
|
|
24
|
+
for (const protocol of this.getProtocols()) {
|
|
25
|
+
const stats = this.forProtocol(protocol);
|
|
26
|
+
if (stats == null) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const snapshot = stats.getSnapshot();
|
|
30
|
+
output[`${protocol} sent`] = Number(snapshot.dataSent);
|
|
31
|
+
output[`${protocol} received`] = Number(snapshot.dataReceived);
|
|
32
|
+
}
|
|
33
|
+
return output;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
this.registerMetricGroup('nodejs_memory_usage_bytes', {
|
|
37
|
+
label: 'memory',
|
|
38
|
+
calculate: () => {
|
|
39
|
+
return {
|
|
40
|
+
...process.memoryUsage()
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
registerMetric(name, opts) {
|
|
46
|
+
if (name == null ?? name.trim() === '') {
|
|
47
|
+
throw new Error('Metric name is required');
|
|
48
|
+
}
|
|
49
|
+
if (opts?.calculate != null) {
|
|
50
|
+
const calculate = opts.calculate;
|
|
51
|
+
// calculated metric
|
|
52
|
+
const collect = async function () {
|
|
53
|
+
const value = await calculate();
|
|
54
|
+
this.set(value);
|
|
55
|
+
};
|
|
56
|
+
// prom-client metrics are global
|
|
57
|
+
new Gauge({
|
|
58
|
+
name,
|
|
59
|
+
help: opts.help ?? name,
|
|
60
|
+
labelNames: [opts.label ?? name],
|
|
61
|
+
collect
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
return new PrometheusMetric(name, opts ?? {});
|
|
66
|
+
}
|
|
67
|
+
registerMetricGroup(name, opts) {
|
|
68
|
+
if (name == null ?? name.trim() === '') {
|
|
69
|
+
throw new Error('Metric name is required');
|
|
70
|
+
}
|
|
71
|
+
if (opts?.calculate != null) {
|
|
72
|
+
// calculated metric
|
|
73
|
+
const calculate = opts.calculate;
|
|
74
|
+
const label = opts.label ?? name;
|
|
75
|
+
// calculated metric
|
|
76
|
+
const collect = async function () {
|
|
77
|
+
const values = await calculate();
|
|
78
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
79
|
+
this.set({ [label]: key }, value);
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
// prom-client metrics are global
|
|
83
|
+
new Gauge({
|
|
84
|
+
name,
|
|
85
|
+
help: opts.help ?? name,
|
|
86
|
+
labelNames: [opts.label ?? name],
|
|
87
|
+
collect
|
|
88
|
+
});
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
return new PrometheusMetricGroup(name, opts ?? {});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export function prometheusMetrics(init) {
|
|
95
|
+
return () => {
|
|
96
|
+
return new PrometheusMetrics(init);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { MetricOptions, MetricGroup, StopTimer } from '@libp2p/interface-metrics';
|
|
2
|
+
export declare class PrometheusMetricGroup implements MetricGroup {
|
|
3
|
+
private readonly gauge;
|
|
4
|
+
private readonly label;
|
|
5
|
+
constructor(name: string, opts: MetricOptions);
|
|
6
|
+
update(values: Record<string, number>): void;
|
|
7
|
+
increment(values: Record<string, number | unknown>): void;
|
|
8
|
+
decrement(values: Record<string, number | unknown>): void;
|
|
9
|
+
reset(): void;
|
|
10
|
+
timer(key: string): StopTimer;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=metric-group.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric-group.d.ts","sourceRoot":"","sources":["../../src/metric-group.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAItF,qBAAa,qBAAsB,YAAW,WAAW;IACvD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;gBAEjB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa;IAY9C,MAAM,CAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAM7C,SAAS,CAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI;IAQ1D,SAAS,CAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,IAAI;IAQ1D,KAAK,IAAK,IAAI;IAId,KAAK,CAAE,GAAG,EAAE,MAAM,GAAG,SAAS;CAK/B"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Gauge } from 'prom-client';
|
|
2
|
+
import { normaliseString } from './utils.js';
|
|
3
|
+
export class PrometheusMetricGroup {
|
|
4
|
+
constructor(name, opts) {
|
|
5
|
+
name = normaliseString(name);
|
|
6
|
+
const help = normaliseString(opts.help ?? name);
|
|
7
|
+
this.label = normaliseString(opts.label ?? name);
|
|
8
|
+
this.gauge = new Gauge({
|
|
9
|
+
name,
|
|
10
|
+
help,
|
|
11
|
+
labelNames: [this.label]
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
update(values) {
|
|
15
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
16
|
+
this.gauge.set({ [this.label]: key }, value);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
increment(values) {
|
|
20
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
21
|
+
const inc = typeof value === 'number' ? value : 1;
|
|
22
|
+
this.gauge.inc({ [this.label]: key }, inc);
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
decrement(values) {
|
|
26
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
27
|
+
const dec = typeof value === 'number' ? value : 1;
|
|
28
|
+
this.gauge.dec({ [this.label]: key }, dec);
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
reset() {
|
|
32
|
+
this.gauge.reset();
|
|
33
|
+
}
|
|
34
|
+
timer(key) {
|
|
35
|
+
return this.gauge.startTimer({
|
|
36
|
+
key: 0
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=metric-group.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric-group.js","sourceRoot":"","sources":["../../src/metric-group.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,OAAO,qBAAqB;IAIhC,YAAa,IAAY,EAAE,IAAmB;QAC5C,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;QAC/C,IAAI,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAA;QAEhD,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC;YACrB,IAAI;YACJ,IAAI;YACJ,UAAU,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;SACzB,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,CAAE,MAA8B;QACpC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC9C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,KAAK,CAAC,CAAA;QAC9C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,SAAS,CAAE,MAAwC;QACjD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC9C,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YAEjD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,SAAS,CAAE,MAAwC;QACjD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE;YAC9C,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;YAEjD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAED,KAAK,CAAE,GAAW;QAChB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC;YAC3B,GAAG,EAAE,CAAC;SACP,CAAC,CAAA;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Metric, MetricOptions, StopTimer } from '@libp2p/interface-metrics';
|
|
2
|
+
export declare class PrometheusMetric implements Metric {
|
|
3
|
+
private readonly gauge;
|
|
4
|
+
constructor(name: string, opts: MetricOptions);
|
|
5
|
+
update(value: number): void;
|
|
6
|
+
increment(value?: number): void;
|
|
7
|
+
decrement(value?: number): void;
|
|
8
|
+
reset(): void;
|
|
9
|
+
timer(): StopTimer;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=metric.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.d.ts","sourceRoot":"","sources":["../../src/metric.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AAIjF,qBAAa,gBAAiB,YAAW,MAAM;IAC7C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAO;gBAEhB,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa;IAY9C,MAAM,CAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAI5B,SAAS,CAAE,KAAK,SAAI,GAAG,IAAI;IAI3B,SAAS,CAAE,KAAK,SAAI,GAAG,IAAI;IAI3B,KAAK,IAAK,IAAI;IAId,KAAK,IAAK,SAAS;CAGpB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Gauge } from 'prom-client';
|
|
2
|
+
import { normaliseString } from './utils.js';
|
|
3
|
+
export class PrometheusMetric {
|
|
4
|
+
constructor(name, opts) {
|
|
5
|
+
name = normaliseString(name);
|
|
6
|
+
const help = normaliseString(opts.help ?? name);
|
|
7
|
+
const label = opts.label != null ? normaliseString(opts.label) : undefined;
|
|
8
|
+
this.gauge = new Gauge({
|
|
9
|
+
name,
|
|
10
|
+
help,
|
|
11
|
+
labelNames: label != null ? [label] : []
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
update(value) {
|
|
15
|
+
this.gauge.set(value);
|
|
16
|
+
}
|
|
17
|
+
increment(value = 1) {
|
|
18
|
+
this.gauge.inc(value);
|
|
19
|
+
}
|
|
20
|
+
decrement(value = 1) {
|
|
21
|
+
this.gauge.dec(value);
|
|
22
|
+
}
|
|
23
|
+
reset() {
|
|
24
|
+
this.gauge.reset();
|
|
25
|
+
}
|
|
26
|
+
timer() {
|
|
27
|
+
return this.gauge.startTimer();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=metric.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metric.js","sourceRoot":"","sources":["../../src/metric.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAE5C,MAAM,OAAO,gBAAgB;IAG3B,YAAa,IAAY,EAAE,IAAmB;QAC5C,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;QAC5B,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAA;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAE1E,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC;YACrB,IAAI;YACJ,IAAI;YACJ,UAAU,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;SACzC,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,CAAE,KAAa;QACnB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED,SAAS,CAAE,KAAK,GAAG,CAAC;QAClB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED,SAAS,CAAE,KAAK,GAAG,CAAC;QAClB,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;IACvB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAED,KAAK;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAA;IAChC,CAAC;CACF"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface MovingAverage {
|
|
2
|
+
variance: number;
|
|
3
|
+
movingAverage: number;
|
|
4
|
+
deviation: number;
|
|
5
|
+
forecast: number;
|
|
6
|
+
push: (time: number, value: number) => void;
|
|
7
|
+
}
|
|
8
|
+
export declare class DefaultMovingAverage {
|
|
9
|
+
movingAverage: number;
|
|
10
|
+
variance: number;
|
|
11
|
+
deviation: number;
|
|
12
|
+
forecast: number;
|
|
13
|
+
private readonly timespan;
|
|
14
|
+
private previousTime?;
|
|
15
|
+
constructor(timespan: number);
|
|
16
|
+
alpha(t: number, pt: number): number;
|
|
17
|
+
push(time: number, value: number): void;
|
|
18
|
+
}
|
|
19
|
+
export declare function createMovingAverage(timespan: number): MovingAverage;
|
|
20
|
+
//# sourceMappingURL=moving-average.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moving-average.d.ts","sourceRoot":"","sources":["../../src/moving-average.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAEhB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5C;AAED,qBAAa,oBAAoB;IACxB,aAAa,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAQ;IACjC,OAAO,CAAC,YAAY,CAAC,CAAQ;gBAEhB,QAAQ,EAAE,MAAM;IAgB7B,KAAK,CAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM;IAI5B,IAAI,CAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;CAkBlC;AAED,wBAAgB,mBAAmB,CAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAEpE"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export class DefaultMovingAverage {
|
|
2
|
+
constructor(timespan) {
|
|
3
|
+
if (typeof timespan !== 'number') {
|
|
4
|
+
throw new Error('must provide a timespan to the moving average constructor');
|
|
5
|
+
}
|
|
6
|
+
if (timespan <= 0) {
|
|
7
|
+
throw new Error('must provide a timespan > 0 to the moving average constructor');
|
|
8
|
+
}
|
|
9
|
+
this.timespan = timespan;
|
|
10
|
+
this.movingAverage = 0;
|
|
11
|
+
this.variance = 0;
|
|
12
|
+
this.deviation = 0;
|
|
13
|
+
this.forecast = 0;
|
|
14
|
+
}
|
|
15
|
+
alpha(t, pt) {
|
|
16
|
+
return 1 - (Math.exp(-(t - pt) / this.timespan));
|
|
17
|
+
}
|
|
18
|
+
push(time, value) {
|
|
19
|
+
if (this.previousTime != null) {
|
|
20
|
+
// calculate moving average
|
|
21
|
+
const a = this.alpha(time, this.previousTime);
|
|
22
|
+
const diff = value - this.movingAverage;
|
|
23
|
+
const incr = a * diff;
|
|
24
|
+
this.movingAverage = a * value + (1 - a) * this.movingAverage;
|
|
25
|
+
// calculate variance & deviation
|
|
26
|
+
this.variance = (1 - a) * (this.variance + diff * incr);
|
|
27
|
+
this.deviation = Math.sqrt(this.variance);
|
|
28
|
+
// calculate forecast
|
|
29
|
+
this.forecast = this.movingAverage + a * diff;
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.movingAverage = value;
|
|
33
|
+
}
|
|
34
|
+
this.previousTime = time;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function createMovingAverage(timespan) {
|
|
38
|
+
return new DefaultMovingAverage(timespan);
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=moving-average.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"moving-average.js","sourceRoot":"","sources":["../../src/moving-average.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,oBAAoB;IAQ/B,YAAa,QAAgB;QAC3B,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE;YAChC,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAA;SAC7E;QAED,IAAI,QAAQ,IAAI,CAAC,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAA;SACjF;QAED,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAA;QACxB,IAAI,CAAC,aAAa,GAAG,CAAC,CAAA;QACtB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;QACjB,IAAI,CAAC,SAAS,GAAG,CAAC,CAAA;QAClB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAA;IACnB,CAAC;IAED,KAAK,CAAE,CAAS,EAAE,EAAU;QAC1B,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAA;IAClD,CAAC;IAED,IAAI,CAAE,IAAY,EAAE,KAAa;QAC/B,IAAI,IAAI,CAAC,YAAY,IAAI,IAAI,EAAE;YAC7B,2BAA2B;YAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAA;YAC7C,MAAM,IAAI,GAAG,KAAK,GAAG,IAAI,CAAC,aAAa,CAAA;YACvC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,CAAA;YACrB,IAAI,CAAC,aAAa,GAAG,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAA;YAC7D,iCAAiC;YACjC,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,IAAI,CAAC,CAAA;YACvD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;YACzC,qBAAqB;YACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,aAAa,GAAG,CAAC,GAAG,IAAI,CAAA;SAC9C;aAAM;YACL,IAAI,CAAC,aAAa,GAAG,KAAK,CAAA;SAC3B;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAA;IAC1B,CAAC;CACF;AAED,MAAM,UAAU,mBAAmB,CAAE,QAAgB;IACnD,OAAO,IAAI,oBAAoB,CAAC,QAAQ,CAAC,CAAA;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,UAAU,OAAO,CAAA;AAC9B,eAAO,MAAM,UAAU,QAAkB,CAAA;AAEzC,wBAAgB,eAAe,CAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AACA,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAA;AAC9B,MAAM,CAAC,MAAM,UAAU,GAAG,EAAE,GAAG,UAAU,CAAA;AAEzC,MAAM,UAAU,eAAe,CAAE,GAAW;IAC1C,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAC/B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@libp2p/prometheus-metrics",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Collect libp2p metrics for scraping by Prometheus",
|
|
5
|
+
"author": "",
|
|
6
|
+
"license": "Apache-2.0 OR MIT",
|
|
7
|
+
"homepage": "https://github.com/libp2p/js-libp2p-prometheus-metrics#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/libp2p/js-libp2p-prometheus-metrics.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/libp2p/js-libp2p-prometheus-metrics/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=16.0.0",
|
|
17
|
+
"npm": ">=7.0.0"
|
|
18
|
+
},
|
|
19
|
+
"type": "module",
|
|
20
|
+
"types": "./dist/src/index.d.ts",
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"dist/src",
|
|
24
|
+
"!dist/test",
|
|
25
|
+
"!**/*.tsbuildinfo"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/src/index.d.ts",
|
|
30
|
+
"import": "./dist/src/index.js"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
"eslintConfig": {
|
|
34
|
+
"extends": "ipfs",
|
|
35
|
+
"parserOptions": {
|
|
36
|
+
"sourceType": "module"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"release": {
|
|
40
|
+
"branches": [
|
|
41
|
+
"main"
|
|
42
|
+
],
|
|
43
|
+
"plugins": [
|
|
44
|
+
[
|
|
45
|
+
"@semantic-release/commit-analyzer",
|
|
46
|
+
{
|
|
47
|
+
"preset": "conventionalcommits",
|
|
48
|
+
"releaseRules": [
|
|
49
|
+
{
|
|
50
|
+
"breaking": true,
|
|
51
|
+
"release": "major"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"revert": true,
|
|
55
|
+
"release": "patch"
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "feat",
|
|
59
|
+
"release": "minor"
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"type": "fix",
|
|
63
|
+
"release": "patch"
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"type": "docs",
|
|
67
|
+
"release": "patch"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"type": "test",
|
|
71
|
+
"release": "patch"
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"type": "deps",
|
|
75
|
+
"release": "patch"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"scope": "no-release",
|
|
79
|
+
"release": false
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
],
|
|
84
|
+
[
|
|
85
|
+
"@semantic-release/release-notes-generator",
|
|
86
|
+
{
|
|
87
|
+
"preset": "conventionalcommits",
|
|
88
|
+
"presetConfig": {
|
|
89
|
+
"types": [
|
|
90
|
+
{
|
|
91
|
+
"type": "feat",
|
|
92
|
+
"section": "Features"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
"type": "fix",
|
|
96
|
+
"section": "Bug Fixes"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"type": "chore",
|
|
100
|
+
"section": "Trivial Changes"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"type": "docs",
|
|
104
|
+
"section": "Documentation"
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
"type": "deps",
|
|
108
|
+
"section": "Dependencies"
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"type": "test",
|
|
112
|
+
"section": "Tests"
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"@semantic-release/changelog",
|
|
119
|
+
"@semantic-release/npm",
|
|
120
|
+
"@semantic-release/github",
|
|
121
|
+
"@semantic-release/git"
|
|
122
|
+
]
|
|
123
|
+
},
|
|
124
|
+
"scripts": {
|
|
125
|
+
"clean": "aegir clean",
|
|
126
|
+
"lint": "aegir lint",
|
|
127
|
+
"dep-check": "aegir dep-check",
|
|
128
|
+
"build": "aegir build",
|
|
129
|
+
"test": "aegir test -t node",
|
|
130
|
+
"test:node": "aegir test -t node --cov",
|
|
131
|
+
"test:electron-main": "aegir test -t electron-main --cov",
|
|
132
|
+
"release": "aegir release"
|
|
133
|
+
},
|
|
134
|
+
"dependencies": {
|
|
135
|
+
"@libp2p/interface-metrics": "^3.0.0",
|
|
136
|
+
"@libp2p/metrics": "^0.0.0",
|
|
137
|
+
"it-drain": "^2.0.0",
|
|
138
|
+
"it-pipe": "^2.0.4"
|
|
139
|
+
},
|
|
140
|
+
"peerDependencies": {
|
|
141
|
+
"prom-client": "^14.1.0"
|
|
142
|
+
},
|
|
143
|
+
"devDependencies": {
|
|
144
|
+
"@libp2p/interface-connection": "^3.0.2",
|
|
145
|
+
"@libp2p/interface-mocks": "^7.0.3",
|
|
146
|
+
"@libp2p/peer-id-factory": "^1.0.19",
|
|
147
|
+
"@multiformats/multiaddr": "^11.0.7",
|
|
148
|
+
"aegir": "^37.5.6",
|
|
149
|
+
"it-pair": "^2.0.3",
|
|
150
|
+
"it-stream-types": "^1.0.4",
|
|
151
|
+
"p-defer": "^4.0.0",
|
|
152
|
+
"prom-client": "^14.1.0",
|
|
153
|
+
"uint8arraylist": "^2.3.3"
|
|
154
|
+
}
|
|
155
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import type { CalculatedMetricOptions, CalculateMetric, Metric, MetricGroup, MetricOptions, Metrics } from '@libp2p/interface-metrics'
|
|
2
|
+
import type { Startable } from '@libp2p/interfaces/startable'
|
|
3
|
+
import { Gauge, CollectFunction, collectDefaultMetrics, DefaultMetricsCollectorConfiguration, register } from 'prom-client'
|
|
4
|
+
import { PrometheusMetric } from './metric.js'
|
|
5
|
+
import { PrometheusMetricGroup } from './metric-group.js'
|
|
6
|
+
import { DefaultMetrics, DefaultMetricsInit } from '@libp2p/metrics'
|
|
7
|
+
|
|
8
|
+
export interface PrometheusMetricsInit extends DefaultMetricsInit {
|
|
9
|
+
defaultMetrics?: DefaultMetricsCollectorConfiguration
|
|
10
|
+
preserveExistingMetrics?: boolean
|
|
11
|
+
collectDefaultMetrics?: boolean
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class PrometheusMetrics extends DefaultMetrics implements Metrics, Startable {
|
|
15
|
+
constructor (init?: Partial<PrometheusMetricsInit>) {
|
|
16
|
+
super(init)
|
|
17
|
+
|
|
18
|
+
if (init?.preserveExistingMetrics !== true) {
|
|
19
|
+
// all metrics in prometheus are global so it's necessary to remove
|
|
20
|
+
// existing metrics to make sure we don't error when setting up metrics
|
|
21
|
+
register.clear()
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (init?.preserveExistingMetrics !== false) {
|
|
25
|
+
// collect memory/CPU and node-specific default metrics
|
|
26
|
+
collectDefaultMetrics(init?.defaultMetrics)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
this.registerMetricGroup('libp2p_data_transfer_bytes', {
|
|
30
|
+
label: 'protocol',
|
|
31
|
+
calculate: () => {
|
|
32
|
+
const output: Record<string, number> = {}
|
|
33
|
+
|
|
34
|
+
const global = this.getGlobal().getSnapshot()
|
|
35
|
+
output['global sent'] = Number(global.dataSent)
|
|
36
|
+
output['global received'] = Number(global.dataReceived)
|
|
37
|
+
|
|
38
|
+
for (const protocol of this.getProtocols()) {
|
|
39
|
+
const stats = this.forProtocol(protocol)
|
|
40
|
+
|
|
41
|
+
if (stats == null) {
|
|
42
|
+
continue
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const snapshot = stats.getSnapshot()
|
|
46
|
+
output[`${protocol} sent`] = Number(snapshot.dataSent)
|
|
47
|
+
output[`${protocol} received`] = Number(snapshot.dataReceived)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return output
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
this.registerMetricGroup('nodejs_memory_usage_bytes', {
|
|
55
|
+
label: 'memory',
|
|
56
|
+
calculate: () => {
|
|
57
|
+
return {
|
|
58
|
+
...process.memoryUsage()
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
registerMetric (name: string, opts: CalculatedMetricOptions): void
|
|
65
|
+
registerMetric (name: string, opts?: MetricOptions): Metric
|
|
66
|
+
registerMetric (name: string, opts: any): any {
|
|
67
|
+
if (name == null ?? name.trim() === '') {
|
|
68
|
+
throw new Error('Metric name is required')
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (opts?.calculate != null) {
|
|
72
|
+
const calculate = opts.calculate
|
|
73
|
+
|
|
74
|
+
// calculated metric
|
|
75
|
+
const collect: CollectFunction<Gauge<any>> = async function () {
|
|
76
|
+
const value = await calculate()
|
|
77
|
+
|
|
78
|
+
this.set(value)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// prom-client metrics are global
|
|
82
|
+
new Gauge({ // eslint-disable-line no-new
|
|
83
|
+
name,
|
|
84
|
+
help: opts.help ?? name,
|
|
85
|
+
labelNames: [opts.label ?? name],
|
|
86
|
+
collect
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return new PrometheusMetric(name, opts ?? {})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
registerMetricGroup (name: string, opts: CalculatedMetricOptions<Record<string, number>>): void
|
|
96
|
+
registerMetricGroup (name: string, opts?: MetricOptions): MetricGroup
|
|
97
|
+
registerMetricGroup (name: string, opts: any): any {
|
|
98
|
+
if (name == null ?? name.trim() === '') {
|
|
99
|
+
throw new Error('Metric name is required')
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (opts?.calculate != null) {
|
|
103
|
+
// calculated metric
|
|
104
|
+
const calculate: CalculateMetric<Record<string, number>> = opts.calculate
|
|
105
|
+
const label = opts.label ?? name
|
|
106
|
+
|
|
107
|
+
// calculated metric
|
|
108
|
+
const collect: CollectFunction<Gauge<any>> = async function () {
|
|
109
|
+
const values = await calculate()
|
|
110
|
+
|
|
111
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
112
|
+
this.set({ [label]: key }, value)
|
|
113
|
+
})
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// prom-client metrics are global
|
|
117
|
+
new Gauge({ // eslint-disable-line no-new
|
|
118
|
+
name,
|
|
119
|
+
help: opts.help ?? name,
|
|
120
|
+
labelNames: [opts.label ?? name],
|
|
121
|
+
collect
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
return
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return new PrometheusMetricGroup(name, opts ?? {})
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function prometheusMetrics (init?: Partial<PrometheusMetricsInit>): () => Metrics {
|
|
132
|
+
return () => {
|
|
133
|
+
return new PrometheusMetrics(init)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { MetricOptions, MetricGroup, StopTimer } from '@libp2p/interface-metrics'
|
|
2
|
+
import { Gauge } from 'prom-client'
|
|
3
|
+
import { normaliseString } from './utils.js'
|
|
4
|
+
|
|
5
|
+
export class PrometheusMetricGroup implements MetricGroup {
|
|
6
|
+
private readonly gauge: Gauge
|
|
7
|
+
private readonly label: string
|
|
8
|
+
|
|
9
|
+
constructor (name: string, opts: MetricOptions) {
|
|
10
|
+
name = normaliseString(name)
|
|
11
|
+
const help = normaliseString(opts.help ?? name)
|
|
12
|
+
this.label = normaliseString(opts.label ?? name)
|
|
13
|
+
|
|
14
|
+
this.gauge = new Gauge({
|
|
15
|
+
name,
|
|
16
|
+
help,
|
|
17
|
+
labelNames: [this.label]
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
update (values: Record<string, number>): void {
|
|
22
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
23
|
+
this.gauge.set({ [this.label]: key }, value)
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
increment (values: Record<string, number | unknown>): void {
|
|
28
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
29
|
+
const inc = typeof value === 'number' ? value : 1
|
|
30
|
+
|
|
31
|
+
this.gauge.inc({ [this.label]: key }, inc)
|
|
32
|
+
})
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
decrement (values: Record<string, number | unknown>): void {
|
|
36
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
37
|
+
const dec = typeof value === 'number' ? value : 1
|
|
38
|
+
|
|
39
|
+
this.gauge.dec({ [this.label]: key }, dec)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
reset (): void {
|
|
44
|
+
this.gauge.reset()
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
timer (key: string): StopTimer {
|
|
48
|
+
return this.gauge.startTimer({
|
|
49
|
+
key: 0
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/metric.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Metric, MetricOptions, StopTimer } from '@libp2p/interface-metrics'
|
|
2
|
+
import { Gauge } from 'prom-client'
|
|
3
|
+
import { normaliseString } from './utils.js'
|
|
4
|
+
|
|
5
|
+
export class PrometheusMetric implements Metric {
|
|
6
|
+
private readonly gauge: Gauge
|
|
7
|
+
|
|
8
|
+
constructor (name: string, opts: MetricOptions) {
|
|
9
|
+
name = normaliseString(name)
|
|
10
|
+
const help = normaliseString(opts.help ?? name)
|
|
11
|
+
const label = opts.label != null ? normaliseString(opts.label) : undefined
|
|
12
|
+
|
|
13
|
+
this.gauge = new Gauge({
|
|
14
|
+
name,
|
|
15
|
+
help,
|
|
16
|
+
labelNames: label != null ? [label] : []
|
|
17
|
+
})
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
update (value: number): void {
|
|
21
|
+
this.gauge.set(value)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
increment (value = 1): void {
|
|
25
|
+
this.gauge.inc(value)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
decrement (value = 1): void {
|
|
29
|
+
this.gauge.dec(value)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
reset (): void {
|
|
33
|
+
this.gauge.reset()
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
timer (): StopTimer {
|
|
37
|
+
return this.gauge.startTimer()
|
|
38
|
+
}
|
|
39
|
+
}
|