@platformatic/metrics 2.74.3 → 3.0.0-alpha.2
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/eslint.config.js +2 -2
- package/index.js +85 -51
- package/package.json +5 -2
- package/test/helper.js +34 -39
- package/test/index.test.js +3 -5
package/eslint.config.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
import neostandard from 'neostandard'
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default neostandard()
|
package/index.js
CHANGED
|
@@ -1,59 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
import collectHttpMetrics from '@platformatic/http-metrics'
|
|
2
|
+
import os from 'node:os'
|
|
3
|
+
import { performance } from 'node:perf_hooks'
|
|
4
|
+
import client from 'prom-client'
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
const { eventLoopUtilization } = require('node:perf_hooks').performance
|
|
5
|
-
const client = require('prom-client')
|
|
6
|
-
const collectHttpMetrics = require('@platformatic/http-metrics')
|
|
6
|
+
export * as client from 'prom-client'
|
|
7
7
|
|
|
8
|
+
const { eventLoopUtilization } = performance
|
|
8
9
|
const { Registry, Gauge, Counter, collectDefaultMetrics } = client
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
if (!registry) {
|
|
12
|
-
registry = new Registry()
|
|
13
|
-
}
|
|
11
|
+
export const kMetricsGroups = Symbol('plt.metrics.MetricsGroups')
|
|
14
12
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
registry.setDefaultLabels(labels)
|
|
13
|
+
export function registerMetricsGroup (registry, group) {
|
|
14
|
+
registry[kMetricsGroups] ??= new Set()
|
|
15
|
+
registry[kMetricsGroups].add(group)
|
|
16
|
+
}
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
await collectThreadCpuMetrics(registry)
|
|
25
|
-
}
|
|
18
|
+
export function hasMetricsGroup (registry, group) {
|
|
19
|
+
return registry[kMetricsGroups]?.has(group)
|
|
20
|
+
}
|
|
26
21
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown'
|
|
32
|
-
return { telemetry_id: telemetryId }
|
|
33
|
-
},
|
|
34
|
-
histogram: {
|
|
35
|
-
name: 'http_request_all_duration_seconds',
|
|
36
|
-
help: 'request duration in seconds summary for all requests',
|
|
37
|
-
collect: function () {
|
|
38
|
-
process.nextTick(() => this.reset())
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
summary: {
|
|
42
|
-
name: 'http_request_all_summary_seconds',
|
|
43
|
-
help: 'request duration in seconds histogram for all requests',
|
|
44
|
-
collect: function () {
|
|
45
|
-
process.nextTick(() => this.reset())
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
}
|
|
22
|
+
// Use this method when dealing with metrics registration in async functions.
|
|
23
|
+
// This will ensure that the group is registered only once.
|
|
24
|
+
export function ensureMetricsGroup (registry, group) {
|
|
25
|
+
registry[kMetricsGroups] ??= new Set()
|
|
50
26
|
|
|
51
|
-
|
|
52
|
-
|
|
27
|
+
if (registry[kMetricsGroups]?.has(group)) {
|
|
28
|
+
return true
|
|
53
29
|
}
|
|
30
|
+
|
|
31
|
+
registry[kMetricsGroups].add(group)
|
|
32
|
+
return false
|
|
54
33
|
}
|
|
55
34
|
|
|
56
|
-
async function collectThreadCpuMetrics (registry) {
|
|
35
|
+
export async function collectThreadCpuMetrics (registry) {
|
|
36
|
+
if (ensureMetricsGroup(registry, 'threadCpuUsage')) {
|
|
37
|
+
return
|
|
38
|
+
}
|
|
39
|
+
|
|
57
40
|
let threadCpuUsage
|
|
58
41
|
|
|
59
42
|
try {
|
|
@@ -117,7 +100,11 @@ async function collectThreadCpuMetrics (registry) {
|
|
|
117
100
|
registry.registerMetric(threadCpuPercentUsageGaugeMetric)
|
|
118
101
|
}
|
|
119
102
|
|
|
120
|
-
function collectEluMetric (
|
|
103
|
+
export function collectEluMetric (registry) {
|
|
104
|
+
if (ensureMetricsGroup(registry, 'elu')) {
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
121
108
|
let startELU = eventLoopUtilization()
|
|
122
109
|
const eluMetric = new Gauge({
|
|
123
110
|
name: 'nodejs_eventloop_utilization',
|
|
@@ -128,9 +115,9 @@ function collectEluMetric (register) {
|
|
|
128
115
|
eluMetric.set(result)
|
|
129
116
|
startELU = endELU
|
|
130
117
|
},
|
|
131
|
-
registers: [
|
|
118
|
+
registers: [registry]
|
|
132
119
|
})
|
|
133
|
-
|
|
120
|
+
registry.registerMetric(eluMetric)
|
|
134
121
|
|
|
135
122
|
let previousIdleTime = 0
|
|
136
123
|
let previousTotalTime = 0
|
|
@@ -161,9 +148,56 @@ function collectEluMetric (register) {
|
|
|
161
148
|
previousIdleTime = idleTime
|
|
162
149
|
previousTotalTime = totalTime
|
|
163
150
|
},
|
|
164
|
-
registers: [
|
|
151
|
+
registers: [registry]
|
|
165
152
|
})
|
|
166
|
-
|
|
153
|
+
registry.registerMetric(cpuMetric)
|
|
167
154
|
}
|
|
168
155
|
|
|
169
|
-
|
|
156
|
+
export async function collectMetrics (serviceId, workerId, metricsConfig = {}, registry = undefined) {
|
|
157
|
+
if (!registry) {
|
|
158
|
+
registry = new Registry()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const labels = { ...metricsConfig.labels, serviceId }
|
|
162
|
+
if (workerId >= 0) {
|
|
163
|
+
labels.workerId = workerId
|
|
164
|
+
}
|
|
165
|
+
registry.setDefaultLabels(labels)
|
|
166
|
+
|
|
167
|
+
if (metricsConfig.defaultMetrics) {
|
|
168
|
+
if (!ensureMetricsGroup(registry, 'default')) {
|
|
169
|
+
collectDefaultMetrics({ register: registry })
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
collectEluMetric(registry)
|
|
173
|
+
await collectThreadCpuMetrics(registry)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (metricsConfig.httpMetrics && !ensureMetricsGroup(registry, 'http')) {
|
|
177
|
+
collectHttpMetrics(registry, {
|
|
178
|
+
customLabels: ['telemetry_id'],
|
|
179
|
+
getCustomLabels: req => {
|
|
180
|
+
const telemetryId = req.headers?.['x-plt-telemetry-id'] ?? 'unknown'
|
|
181
|
+
return { telemetry_id: telemetryId }
|
|
182
|
+
},
|
|
183
|
+
histogram: {
|
|
184
|
+
name: 'http_request_all_duration_seconds',
|
|
185
|
+
help: 'request duration in seconds summary for all requests',
|
|
186
|
+
collect: function () {
|
|
187
|
+
process.nextTick(() => this.reset())
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
summary: {
|
|
191
|
+
name: 'http_request_all_summary_seconds',
|
|
192
|
+
help: 'request duration in seconds histogram for all requests',
|
|
193
|
+
collect: function () {
|
|
194
|
+
process.nextTick(() => this.reset())
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
registry
|
|
202
|
+
}
|
|
203
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/metrics",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-alpha.2",
|
|
4
4
|
"description": "Platformatic Stackable Metrics",
|
|
5
5
|
"main": "index.js",
|
|
6
|
-
"type": "
|
|
6
|
+
"type": "module",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "git+https://github.com/platformatic/platformatic.git"
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
"eslint": "9",
|
|
27
27
|
"neostandard": "^0.12.0"
|
|
28
28
|
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=22.18.0"
|
|
31
|
+
},
|
|
29
32
|
"scripts": {
|
|
30
33
|
"test": "npm run lint && borp",
|
|
31
34
|
"lint": "eslint"
|
package/test/helper.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import { ok } from 'node:assert'
|
|
2
2
|
|
|
3
|
-
const expectedMetrics = [
|
|
3
|
+
export const expectedMetrics = [
|
|
4
4
|
{
|
|
5
5
|
name: 'nodejs_active_handles',
|
|
6
6
|
type: 'gauge'
|
|
@@ -127,47 +127,42 @@ const expectedMetrics = [
|
|
|
127
127
|
}
|
|
128
128
|
]
|
|
129
129
|
|
|
130
|
-
function assertMetric (metrics, metric) {
|
|
131
|
-
assert.ok(metrics.includes(`# HELP ${metric.name} `), `Metric ${metric.name} not found`)
|
|
132
|
-
assert.ok(metrics.includes(`# TYPE ${metric.name} ${metric.type}`), `Metric ${metric.name} type ${metric.type} not found`)
|
|
133
|
-
|
|
134
|
-
if (metric.type === 'summary') {
|
|
135
|
-
assertSummary(metrics, metric)
|
|
136
|
-
} else if (metric.type === 'histogram') {
|
|
137
|
-
assertHistogram(metrics, metric)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
130
|
function assertSummary (metrics, metric) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
131
|
+
ok(metrics.includes(`${metric.name}{quantile="0.01"`))
|
|
132
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.01"'))
|
|
133
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.05"'))
|
|
134
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.5"'))
|
|
135
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.9"'))
|
|
136
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.95"'))
|
|
137
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.99"'))
|
|
138
|
+
ok(metrics.includes('http_request_all_summary_seconds{quantile="0.999"'))
|
|
139
|
+
ok(metrics.includes('http_request_all_summary_seconds_sum{'))
|
|
140
|
+
ok(metrics.includes('http_request_all_summary_seconds_count{'))
|
|
152
141
|
}
|
|
153
142
|
|
|
154
143
|
function assertHistogram (metrics, metric) {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
144
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.005"'))
|
|
145
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.01"'))
|
|
146
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.025"'))
|
|
147
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.05"'))
|
|
148
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.1"'))
|
|
149
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.25"'))
|
|
150
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="0.5"'))
|
|
151
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="1"'))
|
|
152
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="2.5"'))
|
|
153
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="5"'))
|
|
154
|
+
ok(metrics.includes('http_request_all_duration_seconds_bucket{le="10"'))
|
|
155
|
+
ok(metrics.includes('http_request_all_duration_seconds_sum{'))
|
|
156
|
+
ok(metrics.includes('http_request_all_duration_seconds_count{'))
|
|
168
157
|
}
|
|
169
158
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
159
|
+
export function assertMetric (metrics, metric) {
|
|
160
|
+
ok(metrics.includes(`# HELP ${metric.name} `), `Metric ${metric.name} not found`)
|
|
161
|
+
ok(metrics.includes(`# TYPE ${metric.name} ${metric.type}`), `Metric ${metric.name} type ${metric.type} not found`)
|
|
162
|
+
|
|
163
|
+
if (metric.type === 'summary') {
|
|
164
|
+
assertSummary(metrics, metric)
|
|
165
|
+
} else if (metric.type === 'histogram') {
|
|
166
|
+
assertHistogram(metrics, metric)
|
|
167
|
+
}
|
|
173
168
|
}
|
package/test/index.test.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const { test } = require('node:test')
|
|
5
|
-
const { collectMetrics, client } = require('..')
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { test } from 'node:test'
|
|
3
|
+
import { client, collectMetrics } from '../index.js'
|
|
6
4
|
|
|
7
5
|
const nextTick = () => new Promise(resolve => process.nextTick(resolve))
|
|
8
6
|
|