@aidra/pmx-io 0.0.0-stage → 9.13.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.
Files changed (67) hide show
  1. package/README.md +69 -2
  2. package/bin/pmx-io-node.js +143 -0
  3. package/index.d.ts +381 -0
  4. package/index.js +27 -0
  5. package/index.mjs +47 -0
  6. package/lib/actions.js +120 -0
  7. package/lib/activate.js +402 -0
  8. package/lib/application.js +106 -0
  9. package/lib/bun.js +155 -0
  10. package/lib/config.js +67 -0
  11. package/lib/constants.js +17 -0
  12. package/lib/debug.js +48 -0
  13. package/lib/esm-hooks.mjs +111 -0
  14. package/lib/exit.js +79 -0
  15. package/lib/features/metrics.js +409 -0
  16. package/lib/features/notify.js +358 -0
  17. package/lib/features/profiling.js +208 -0
  18. package/lib/hooks.js +151 -0
  19. package/lib/inbound.js +174 -0
  20. package/lib/integrations.js +372 -0
  21. package/lib/itg/amqplib.js +169 -0
  22. package/lib/itg/bullmq.js +141 -0
  23. package/lib/itg/common.js +657 -0
  24. package/lib/itg/dbcomment.js +114 -0
  25. package/lib/itg/index.js +103 -0
  26. package/lib/itg/ioredis.js +212 -0
  27. package/lib/itg/kafkajs.js +205 -0
  28. package/lib/itg/mongodb.js +322 -0
  29. package/lib/itg/mysql2.js +205 -0
  30. package/lib/itg/nats.js +531 -0
  31. package/lib/itg/noderedis.js +236 -0
  32. package/lib/itg/pg.js +253 -0
  33. package/lib/itg/pgqueue.js +305 -0
  34. package/lib/itg/postgres.js +252 -0
  35. package/lib/itg/redis-common.js +265 -0
  36. package/lib/itg/sql.js +302 -0
  37. package/lib/metrics/service.js +286 -0
  38. package/lib/metrics/types.js +342 -0
  39. package/lib/modules.js +260 -0
  40. package/lib/node-options.js +62 -0
  41. package/lib/otel/bridge.js +797 -0
  42. package/lib/otel/env.js +114 -0
  43. package/lib/outbound.js +362 -0
  44. package/lib/pmx.js +757 -0
  45. package/lib/relay/hub.js +279 -0
  46. package/lib/relay/transport.js +253 -0
  47. package/lib/standalone/activate.js +307 -0
  48. package/lib/standalone/capture.js +55 -0
  49. package/lib/standalone/container.js +909 -0
  50. package/lib/standalone/transport.js +1023 -0
  51. package/lib/tracing/context.js +90 -0
  52. package/lib/tracing/control.js +124 -0
  53. package/lib/tracing/exporter.js +115 -0
  54. package/lib/tracing/index.js +242 -0
  55. package/lib/tracing/logs.js +176 -0
  56. package/lib/tracing/options.js +105 -0
  57. package/lib/tracing/paths.js +34 -0
  58. package/lib/tracing/tracer.js +850 -0
  59. package/lib/tracing/w3c.js +415 -0
  60. package/lib/transport/ipc.js +97 -0
  61. package/lib/transport/ws.js +511 -0
  62. package/lib/util.js +109 -0
  63. package/package.json +48 -4
  64. package/preload.cjs +26 -0
  65. package/preload.mjs +25 -0
  66. package/standalone.cjs +16 -0
  67. package/standalone.mjs +17 -0
@@ -0,0 +1,286 @@
1
+ // Copyright (c) 2026 Mike Warriner. All rights reserved. Proprietary — see LICENSE.
2
+ 'use strict'
3
+
4
+ // Metric registry and the 990 ms `axm:monitor` push (80 A.3.6).
5
+
6
+ const { Gauge, Counter, Meter, Histogram } = require('./types')
7
+ const { METRIC_PUSH_INTERVAL } = require('../constants')
8
+
9
+ const RELAY_INTERVAL = 1000
10
+ const { round2 } = require('../util')
11
+ const debug = require('../debug')('axm:services:metrics')
12
+
13
+ function normalizeOpts (opts) {
14
+ if (typeof opts === 'string') return { name: opts }
15
+ if (opts === null || typeof opts !== 'object') return { name: opts }
16
+ return opts
17
+ }
18
+
19
+ function isReportable (v) {
20
+ if (typeof v === 'string' || typeof v === 'boolean') return true
21
+ return typeof v === 'number' && Number.isFinite(v)
22
+ }
23
+
24
+ class MetricService {
25
+ constructor (transport) {
26
+ this._transport = transport
27
+ this._metrics = new Map()
28
+ this._instruments = new Map() // relay key → { key, kind, impl, opts } (80 Part G.5)
29
+ this._relay = null
30
+ this._timer = null
31
+ }
32
+
33
+ start () {
34
+ if (this._timer) return
35
+ this._timer = setInterval(() => (this._relay ? this.flushContributions() : this.push()), this._relay ? RELAY_INTERVAL : METRIC_PUSH_INTERVAL)
36
+ if (this._timer.unref) this._timer.unref()
37
+ }
38
+
39
+ /**
40
+ * Relay mode (80 NIO-263, NIO-291, NIO-293): instead of `axm:monitor`, contributions of the
41
+ * relay-capable instruments are sent every 1000 ms with `send(list)`.
42
+ */
43
+ setRelay (send) {
44
+ this._relay = send
45
+ for (const i of this._instruments.values()) if (i.impl) i.impl._track = true
46
+ if (this._timer) {
47
+ clearInterval(this._timer)
48
+ this._timer = null
49
+ this.start()
50
+ }
51
+ }
52
+
53
+ /** Declare a relay-capable instrument (built-in key, or a custom metric's name). */
54
+ instrument (key, kind, impl, opts) {
55
+ if (typeof key !== 'string') return
56
+ if (this._relay && impl) impl._track = true
57
+ this._instruments.set(key, { key, kind, impl, opts: opts || {} })
58
+ }
59
+
60
+ contributions () {
61
+ const out = []
62
+ for (const i of this._instruments.values()) {
63
+ let c
64
+ try {
65
+ c = i.kind === 'gauge' && typeof i.impl === 'function' ? i.impl() : i.impl._drain()
66
+ } catch (_) {
67
+ c = undefined
68
+ }
69
+ if (c === undefined || c === null || (typeof c === 'number' && !Number.isFinite(c))) continue
70
+ out.push({ k: i.key, t: i.kind, o: i.opts, c })
71
+ }
72
+ return out
73
+ }
74
+
75
+ flushContributions () {
76
+ if (!this._relay) return
77
+ const c = this.contributions()
78
+ if (c.length) {
79
+ try {
80
+ this._relay(c)
81
+ } catch (_) {}
82
+ }
83
+ }
84
+
85
+ /** Root side: apply one relay contribution `{k, t, o, c}`. */
86
+ applyContribution (item) {
87
+ if (!item || typeof item.k !== 'string') return
88
+ let i = this._instruments.get(item.k)
89
+ if (!i) {
90
+ if (item.k.startsWith('internal/')) return
91
+ const o = Object.assign({}, item.o && typeof item.o === 'object' ? item.o : {}, { name: item.k })
92
+ switch (item.t) {
93
+ case 'counter': this.counter(o); break
94
+ case 'meter': this.meter(o); break
95
+ case 'histogram': this.histogram(o); break
96
+ case 'gauge': this.gauge(o); break
97
+ default: return
98
+ }
99
+ i = this._instruments.get(item.k)
100
+ if (!i) return
101
+ }
102
+ if (!i.impl || typeof i.impl._apply !== 'function') return
103
+ try {
104
+ i.impl._apply(item.c)
105
+ } catch (_) {}
106
+ }
107
+
108
+ /**
109
+ * Register (or replace) a metric.
110
+ * @param {{name: string, id?: string, unit?: string, historic?: boolean, handler: Function, implementation?: any}} def
111
+ */
112
+ register (def) {
113
+ if (typeof def.name !== 'string') {
114
+ console.error('Invalid metric name declared: ' + def.name)
115
+ return false
116
+ }
117
+ if (def.id !== undefined && typeof def.id !== 'string') {
118
+ console.error('Invalid metric type declared: ' + def.id)
119
+ return false
120
+ }
121
+ if (typeof def.handler !== 'function') {
122
+ console.error('Invalid metric handler declared for ' + def.name)
123
+ return false
124
+ }
125
+ const old = this._metrics.get(def.name)
126
+ if (old && old.implementation && typeof old.implementation._stop === 'function' && old.implementation !== def.implementation) {
127
+ old.implementation._stop()
128
+ }
129
+ this._metrics.set(def.name, {
130
+ name: def.name,
131
+ id: def.id,
132
+ unit: def.unit,
133
+ historic: def.historic === undefined ? true : Boolean(def.historic),
134
+ handler: def.handler,
135
+ implementation: def.implementation
136
+ })
137
+ return true
138
+ }
139
+
140
+ unregister (name) {
141
+ const m = this._metrics.get(name)
142
+ if (!m) return
143
+ if (m.implementation && typeof m.implementation._stop === 'function') m.implementation._stop()
144
+ this._metrics.delete(name)
145
+ }
146
+
147
+ has (name) {
148
+ return this._metrics.has(name)
149
+ }
150
+
151
+ /** Evaluate every metric into the `axm:monitor` payload shape. */
152
+ collect () {
153
+ const data = {}
154
+ for (const m of this._metrics.values()) {
155
+ let value
156
+ try {
157
+ value = m.handler()
158
+ } catch (err) {
159
+ debug('metric %s handler threw: %s', m.name, err && err.message)
160
+ continue
161
+ }
162
+ if (!isReportable(value)) continue
163
+ const entry = { value }
164
+ if (m.unit !== undefined && m.unit !== null) entry.unit = m.unit
165
+ if (m.id !== undefined && m.id !== null) entry.type = m.id
166
+ entry.historic = m.historic
167
+ data[m.name] = entry
168
+ }
169
+ return data
170
+ }
171
+
172
+ push () {
173
+ this._transport.send('axm:monitor', this.collect())
174
+ }
175
+
176
+ // ---- creators (80 A.3.1 – A.3.5) ----
177
+
178
+ _common (opts) {
179
+ return { name: opts.name, id: opts.id, unit: opts.unit, historic: opts.historic }
180
+ }
181
+
182
+ _relayOpts (opts) {
183
+ const o = {}
184
+ for (const k of ['name', 'unit', 'id', 'historic', 'measurement', 'samples', 'timeframe']) if (opts[k] !== undefined) o[k] = opts[k]
185
+ return o
186
+ }
187
+
188
+ gauge (opts) {
189
+ opts = normalizeOpts(opts)
190
+ if (typeof opts.value === 'function') {
191
+ const fn = opts.value
192
+ if (this.register(Object.assign(this._common(opts), { handler: fn }))) this.instrument(opts.name, 'gauge', fn, this._relayOpts(opts))
193
+ return undefined
194
+ }
195
+ const g = new Gauge()
196
+ const ok = this.register(Object.assign(this._common(opts), {
197
+ implementation: g,
198
+ handler: () => (g.isUsed() ? g.val() : undefined)
199
+ }))
200
+ if (ok) this.instrument(opts.name, 'gauge', g, this._relayOpts(opts))
201
+ return ok ? g : undefined
202
+ }
203
+
204
+ counter (opts) {
205
+ opts = normalizeOpts(opts)
206
+ const c = new Counter(opts)
207
+ const ok = this.register(Object.assign(this._common(opts), {
208
+ implementation: c,
209
+ handler: () => (c.isUsed() ? c.val() : undefined)
210
+ }))
211
+ if (ok) this.instrument(opts.name, 'counter', c, this._relayOpts(opts))
212
+ return ok ? c : undefined
213
+ }
214
+
215
+ meter (opts) {
216
+ opts = normalizeOpts(opts)
217
+ if (typeof opts.name !== 'string') {
218
+ console.error('Invalid metric name declared: ' + opts.name)
219
+ return undefined
220
+ }
221
+ const m = new Meter(opts)
222
+ this.register(Object.assign(this._common(opts), {
223
+ implementation: m,
224
+ handler: () => (m.isUsed() ? m.val() : undefined)
225
+ }))
226
+ this.instrument(opts.name, 'meter', m, this._relayOpts(opts))
227
+ return m
228
+ }
229
+
230
+ histogram (opts) {
231
+ opts = normalizeOpts(opts)
232
+ const h = new Histogram(opts)
233
+ const ok = this.register(Object.assign(this._common(opts), {
234
+ implementation: h,
235
+ handler: () => {
236
+ if (!h.isUsed()) return undefined
237
+ const v = h.val()
238
+ return typeof v === 'number' ? round2(v) : v
239
+ }
240
+ }))
241
+ if (ok) this.instrument(opts.name, 'histogram', h, this._relayOpts(opts))
242
+ return ok ? h : undefined
243
+ }
244
+
245
+ metrics (list) {
246
+ if (list === null || list === undefined) {
247
+ console.error('Received empty metric to create')
248
+ console.trace()
249
+ return []
250
+ }
251
+ const arr = Array.isArray(list) ? list : [list]
252
+ return arr.map((def) => {
253
+ if (!def || typeof def.name !== 'string') {
254
+ console.error('Trying to create a metrics without a name')
255
+ console.trace()
256
+ return {}
257
+ }
258
+ switch (def.type) {
259
+ case 'counter': return this.counter(def)
260
+ case 'histogram': return this.histogram(def)
261
+ case 'meter': return this.meter(def)
262
+ case 'gauge':
263
+ case 'metric':
264
+ case undefined:
265
+ case null:
266
+ return this.gauge(def)
267
+ default:
268
+ console.error('Invalid metric type ' + def.type + ' for metric ' + def.name)
269
+ console.trace()
270
+ return {}
271
+ }
272
+ })
273
+ }
274
+
275
+ destroy () {
276
+ if (this._timer) clearInterval(this._timer)
277
+ this._timer = null
278
+ for (const m of this._metrics.values()) {
279
+ if (m.implementation && typeof m.implementation._stop === 'function') m.implementation._stop()
280
+ }
281
+ this._metrics.clear()
282
+ this._instruments.clear()
283
+ }
284
+ }
285
+
286
+ module.exports = { MetricService, normalizeOpts }
@@ -0,0 +1,342 @@
1
+ // Copyright (c) 2026 Mike Warriner. All rights reserved. Proprietary — see LICENSE.
2
+ 'use strict'
3
+
4
+ // Metric implementations (80 A.3): Gauge, Counter, Meter (EWMA), Histogram with an
5
+ // exponentially decaying reservoir (forward-decay priority sampling).
6
+
7
+ const { round2 } = require('../util')
8
+
9
+ const RESERVOIR_SIZE = 1028
10
+ const RESERVOIR_ALPHA = 0.015 // per second
11
+ const RESCALE_INTERVAL_MS = 60 * 60 * 1000
12
+
13
+ class Gauge {
14
+ constructor (value) {
15
+ this._value = value === undefined ? 0 : value
16
+ this._used = false
17
+ }
18
+
19
+ set (value) {
20
+ this._value = value
21
+ this._used = true
22
+ }
23
+
24
+ val () {
25
+ return this._value
26
+ }
27
+
28
+ isUsed () {
29
+ return this._used
30
+ }
31
+
32
+ /** Relay contribution (80 Part G.5): the last value. */
33
+ _drain () {
34
+ return this._used ? this._value : undefined
35
+ }
36
+
37
+ _apply (c) {
38
+ this.set(c)
39
+ }
40
+ }
41
+
42
+ class Counter {
43
+ constructor (opts) {
44
+ opts = opts || {}
45
+ this._count = typeof opts.count === 'number' ? opts.count : 0
46
+ this._used = false
47
+ }
48
+
49
+ inc (n) {
50
+ this._count += n || 1
51
+ this._used = true
52
+ }
53
+
54
+ dec (n) {
55
+ this._count -= n || 1
56
+ this._used = true
57
+ }
58
+
59
+ reset (count) {
60
+ this._count = count || 0
61
+ }
62
+
63
+ /** Relay contribution: the net change since the previous drain. */
64
+ _drain () {
65
+ const base = this._relayBase || 0
66
+ this._relayBase = this._count
67
+ const d = this._count - base
68
+ return d !== 0 ? d : undefined
69
+ }
70
+
71
+ _apply (c) {
72
+ if (typeof c === 'number' && Number.isFinite(c)) {
73
+ this._count += c
74
+ this._used = true
75
+ }
76
+ }
77
+
78
+ val () {
79
+ return this._count
80
+ }
81
+
82
+ isUsed () {
83
+ return this._used
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Exponentially weighted moving average rate (80 A.3.3).
89
+ * rate is in events per millisecond; val() = events per `samples` seconds.
90
+ */
91
+ class Meter {
92
+ constructor (opts) {
93
+ opts = opts || {}
94
+ this._samples = Number(opts.samples || opts.seconds || 1)
95
+ this._timeframe = Number(opts.timeframe || 60)
96
+ this._tickInterval = Number(opts.tickInterval || 5000)
97
+ this._alpha = 1 - Math.exp(-this._tickInterval / (this._timeframe * 1000))
98
+ this._pending = 0
99
+ this._rate = 0
100
+ this._used = false
101
+ this._timer = setInterval(() => this._tick(), this._tickInterval)
102
+ if (this._timer.unref) this._timer.unref()
103
+ }
104
+
105
+ _tick () {
106
+ const instant = this._pending / this._tickInterval
107
+ this._pending = 0
108
+ this._rate += this._alpha * (instant - this._rate)
109
+ }
110
+
111
+ mark (n) {
112
+ this._pending += n || 1
113
+ this._used = true
114
+ if (this._track) this._relayMarks = (this._relayMarks || 0) + (n || 1)
115
+ }
116
+
117
+ /** Relay contribution: the number of marks since the previous drain. */
118
+ _drain () {
119
+ const m = this._relayMarks || 0
120
+ this._relayMarks = 0
121
+ return m > 0 ? m : undefined
122
+ }
123
+
124
+ _apply (c) {
125
+ if (typeof c === 'number' && c > 0) this.mark(c)
126
+ }
127
+
128
+ /** Unrounded rate in events per `samples` seconds. */
129
+ rawVal () {
130
+ return this._rate * this._samples * 1000
131
+ }
132
+
133
+ val () {
134
+ return round2(this.rawVal())
135
+ }
136
+
137
+ isUsed () {
138
+ return this._used
139
+ }
140
+
141
+ _stop () {
142
+ clearInterval(this._timer)
143
+ }
144
+ }
145
+
146
+ class ExponentiallyDecayingReservoir {
147
+ constructor (size, alpha) {
148
+ this._size = size || RESERVOIR_SIZE
149
+ this._alpha = alpha || RESERVOIR_ALPHA
150
+ this.clear()
151
+ }
152
+
153
+ clear () {
154
+ this._samples = [] // { priority, value }
155
+ this._landmark = Date.now()
156
+ this._nextRescale = this._landmark + RESCALE_INTERVAL_MS
157
+ }
158
+
159
+ _rescale (now) {
160
+ const factor = Math.exp(-this._alpha * (now - this._landmark) / 1000)
161
+ for (const s of this._samples) s.priority *= factor
162
+ this._landmark = now
163
+ this._nextRescale = now + RESCALE_INTERVAL_MS
164
+ }
165
+
166
+ update (value, now) {
167
+ now = now === undefined ? Date.now() : now
168
+ if (now >= this._nextRescale) this._rescale(now)
169
+ const weight = Math.exp(this._alpha * (now - this._landmark) / 1000)
170
+ const u = 1 - Math.random() // (0, 1]
171
+ const priority = weight / u
172
+ if (this._samples.length < this._size) {
173
+ this._samples.push({ priority, value })
174
+ return
175
+ }
176
+ let minIdx = 0
177
+ for (let i = 1; i < this._samples.length; i++) {
178
+ if (this._samples[i].priority < this._samples[minIdx].priority) minIdx = i
179
+ }
180
+ if (priority > this._samples[minIdx].priority) {
181
+ this._samples[minIdx] = { priority, value }
182
+ }
183
+ }
184
+
185
+ size () {
186
+ return this._samples.length
187
+ }
188
+
189
+ sortedValues () {
190
+ return this._samples.map((s) => s.value).sort((a, b) => a - b)
191
+ }
192
+ }
193
+
194
+ /** Percentile rule of 80 A.3.4 over ascending values. */
195
+ function percentile (sorted, p) {
196
+ const n = sorted.length
197
+ if (n === 0) return null
198
+ const pos = p * (n + 1)
199
+ if (pos < 1) return sorted[0]
200
+ if (pos >= n) return sorted[n - 1]
201
+ const lower = sorted[Math.floor(pos) - 1]
202
+ const upper = sorted[Math.ceil(pos) - 1]
203
+ return lower + (pos - Math.floor(pos)) * (upper - lower)
204
+ }
205
+
206
+ const MEASUREMENTS = ['min', 'max', 'sum', 'count', 'variance', 'mean', 'stddev', 'median', 'p75', 'p95', 'p99', 'p999', 'ema']
207
+
208
+ class Histogram {
209
+ constructor (opts) {
210
+ opts = opts || {}
211
+ this._measurement = MEASUREMENTS.includes(opts.measurement) ? opts.measurement : 'mean'
212
+ this._reservoir = new ExponentiallyDecayingReservoir()
213
+ this._min = null
214
+ this._max = null
215
+ this._sum = 0
216
+ this._count = 0
217
+ this._mean = 0 // Welford running mean
218
+ this._m2 = 0
219
+ this._ema = 0
220
+ this._used = false
221
+ }
222
+
223
+ update (value) {
224
+ value = Number(value)
225
+ if (Number.isNaN(value)) return
226
+ this._used = true
227
+ this._count++
228
+ this._sum += value
229
+ if (this._min === null || value < this._min) this._min = value
230
+ if (this._max === null || value > this._max) this._max = value
231
+ const delta = value - this._mean
232
+ this._mean += delta / this._count
233
+ this._m2 += delta * (value - this._mean)
234
+ const alpha = 2 / (1 + this._count)
235
+ this._ema = this._count === 1 ? value : this._ema + alpha * (value - this._ema)
236
+ this._reservoir.update(value)
237
+ if (this._track) {
238
+ if (!this._relayValues) this._relayValues = []
239
+ if (this._relayValues.length < 2000) this._relayValues.push(value)
240
+ }
241
+ }
242
+
243
+ /** Relay contribution: the values recorded since the previous drain (at most 2 000). */
244
+ _drain () {
245
+ const v = this._relayValues
246
+ this._relayValues = null
247
+ return v && v.length ? v : undefined
248
+ }
249
+
250
+ _apply (c) {
251
+ if (!Array.isArray(c)) return
252
+ for (const v of c.slice(0, 2000)) this.update(v)
253
+ }
254
+
255
+ getMin () { return this._min }
256
+ getMax () { return this._max }
257
+ getSum () { return this._sum }
258
+ getCount () { return this._count }
259
+ getEma () { return this._ema }
260
+ getMean () { return this._count === 0 ? 0 : this._sum / this._count }
261
+ getVariance () { return this._count <= 1 ? null : this._m2 / (this._count - 1) }
262
+
263
+ percentiles (fractions) {
264
+ const sorted = this._reservoir.sortedValues()
265
+ const out = {}
266
+ for (const p of fractions || []) out[p] = percentile(sorted, p)
267
+ return out
268
+ }
269
+
270
+ fullResults () {
271
+ const pc = this.percentiles([0.5, 0.75, 0.95, 0.99, 0.999])
272
+ return {
273
+ min: this._min,
274
+ max: this._max,
275
+ sum: this._sum,
276
+ variance: this.getVariance(),
277
+ mean: this.getMean(),
278
+ count: this._count,
279
+ median: pc[0.5],
280
+ p75: pc[0.75],
281
+ p95: pc[0.95],
282
+ p99: pc[0.99],
283
+ p999: pc[0.999],
284
+ ema: this._ema
285
+ }
286
+ }
287
+
288
+ _compute (measurement) {
289
+ switch (measurement) {
290
+ case 'min': return this._min
291
+ case 'max': return this._max
292
+ case 'sum': return this._sum
293
+ case 'count': return this._count
294
+ case 'variance': return this.getVariance()
295
+ case 'mean': return this.getMean()
296
+ case 'stddev': {
297
+ const v = this.getVariance()
298
+ return v === null ? null : Math.sqrt(v)
299
+ }
300
+ case 'ema': return this._ema
301
+ case 'median': return this.percentiles([0.5])[0.5]
302
+ case 'p75': return this.percentiles([0.75])[0.75]
303
+ case 'p95': return this.percentiles([0.95])[0.95]
304
+ case 'p99': return this.percentiles([0.99])[0.99]
305
+ case 'p999': return this.percentiles([0.999])[0.999]
306
+ default: return this.getMean()
307
+ }
308
+ }
309
+
310
+ val () {
311
+ return this._compute(this._measurement)
312
+ }
313
+
314
+ isUsed () {
315
+ return this._used
316
+ }
317
+ }
318
+
319
+ const MetricType = Object.freeze({
320
+ meter: 'meter',
321
+ histogram: 'histogram',
322
+ counter: 'counter',
323
+ gauge: 'gauge',
324
+ metric: 'metric'
325
+ })
326
+
327
+ const MetricMeasurements = Object.freeze(MEASUREMENTS.reduce((acc, m) => {
328
+ acc[m] = m
329
+ return acc
330
+ }, {}))
331
+
332
+ module.exports = {
333
+ Gauge,
334
+ Counter,
335
+ Meter,
336
+ Histogram,
337
+ ExponentiallyDecayingReservoir,
338
+ percentile,
339
+ MetricType,
340
+ MetricMeasurements,
341
+ MEASUREMENTS
342
+ }