1
+
2
+ import { performance } from 'node:perf_hooks'
1
3
import { readFileSync } from 'fs'
2
4
import { load as ymlLoad } from 'js-yaml'
3
5
import promClient from 'prom-client'
4
- const PERCENTILES = [ 0.001 , 0.01 , 0. 1, 1 , 2.5 , 10 , 25 , 50 , 75 , 90 , 97.5 , 99 , 99.9 , 99.99 , 99.999 ]
6
+ const PERCENTILES = [ 0.1 , 1 , 10 , 25 , 50 , 75 , 90 , 97.5 , 99 ]
5
7
6
8
class Telemetry {
7
9
constructor ( { configFile, logger } ) {
@@ -25,40 +27,46 @@ class Telemetry {
25
27
// Setup
26
28
this . component = component
27
29
this . version = `${ version } -build.${ buildDate } `
30
+ this . metrics = new Map ( )
28
31
29
32
// Create metrics
30
33
for ( const [ category , metric ] of Object . entries ( metrics . count || { } ) ) {
31
- /* eslint-disable-next-line no-new */
32
- new promClient . Counter ( {
34
+ this . metrics . set ( category , new promClient . Counter ( {
33
35
name : category . replaceAll ( '-' , '_' ) ,
34
36
help : metric . description ,
35
37
registers : [ this . countRegistry , this . allRegistry ] // specify a non-default registry
36
- } )
38
+ } ) )
37
39
}
38
40
for ( const [ category , metric ] of Object . entries ( metrics . labelCount || { } ) ) {
39
- /* eslint-disable-next-line no-new */
40
- new promClient . Counter ( {
41
+ this . metrics . set ( category , new promClient . Counter ( {
41
42
name : category . replaceAll ( '-' , '_' ) ,
42
43
help : metric . description ,
43
44
labelNames : metric . labels ,
44
45
registers : [ this . labelCountRegistry , this . allRegistry ] // specify a non-default registry
45
- } )
46
+ } ) )
46
47
}
47
48
for ( const [ category , metric ] of Object . entries ( metrics . durations || { } ) ) {
48
- /* eslint-disable-next-line no-new */
49
- new promClient . Histogram ( {
49
+ this . metrics . set ( category , new promClient . Histogram ( {
50
50
name : category . replaceAll ( '-' , '_' ) ,
51
51
help : metric . description ,
52
52
buckets : PERCENTILES ,
53
53
registers : [ this . durationsRegistry , this . allRegistry ] // specify a non-default registry
54
- } )
54
+ } ) )
55
55
}
56
56
for ( const [ category , metric ] of Object . entries ( metrics . gauge || { } ) ) {
57
- /* eslint-disable-next-line no-new */
58
- new promClient . Gauge ( {
57
+ this . metrics . set ( category , new promClient . Gauge ( {
59
58
name : category . replaceAll ( '-' , '_' ) ,
60
59
help : metric . description ,
61
60
registers : [ this . gaugeRegistry , this . allRegistry ] // specify a non-default registry
61
+ } ) )
62
+ }
63
+
64
+ if ( metrics . process ?. elu ) {
65
+ this . collectEventLoopUtilization ( {
66
+ name : metrics . process . elu . name ,
67
+ description : metrics . process . elu . description ,
68
+ interval : metrics . process . elu . interval ,
69
+ registers : [ this . allRegistry ]
62
70
} )
63
71
}
64
72
} catch ( err ) {
@@ -67,6 +75,23 @@ class Telemetry {
67
75
}
68
76
}
69
77
78
+ collectEventLoopUtilization ( { name, description, interval, registers } ) {
79
+ const metric = new promClient . Gauge ( {
80
+ name : name . replaceAll ( '-' , '_' ) ,
81
+ help : description ,
82
+ registers
83
+ } )
84
+ this . metrics . set ( name , metric )
85
+
86
+ let elu1 = performance . eventLoopUtilization ( )
87
+ this . collectEluInterval = setInterval ( ( ) => {
88
+ const elu2 = performance . eventLoopUtilization ( )
89
+ const u = performance . eventLoopUtilization ( elu2 , elu1 )
90
+ metric . set ( u . utilization )
91
+ elu1 = elu2
92
+ } , interval ) . unref ( )
93
+ }
94
+
70
95
resetAll ( ) {
71
96
this . allRegistry . resetMetrics ( )
72
97
}
@@ -88,38 +113,54 @@ class Telemetry {
88
113
return this . allRegistry . metrics ( )
89
114
}
90
115
116
+ get ( name ) {
117
+ return this . metrics . get ( name )
118
+ }
119
+
120
+ getGaugeValue ( name ) {
121
+ const value = this . get ( name )
122
+ if ( ! value ) { return }
123
+ return value . hashMap [ '' ] . value
124
+ }
125
+
126
+ getHistogramValue ( name ) {
127
+ const value = this . get ( name )
128
+ if ( ! value ) { return }
129
+ return value . hashMap && value . hashMap [ '' ] ?. sum
130
+ }
131
+
91
132
increaseCount ( category , amount = 1 ) {
92
- const metric = this . countRegistry . getSingleMetric ( category . replaceAll ( '-' , '_' ) )
133
+ const metric = this . metrics . get ( category )
93
134
if ( ! metric ) throw new Error ( `Metric ${ category } not found` )
94
135
return metric . inc ( amount )
95
136
}
96
137
97
138
increaseLabelCount ( category , labels = [ ] , amount = 1 ) {
98
- const metric = this . labelCountRegistry . getSingleMetric ( category . replaceAll ( '-' , '_' ) )
139
+ const metric = this . metrics . get ( category )
99
140
if ( ! metric ) throw new Error ( `Metric ${ category } not found` )
100
141
return metric . labels ( ...labels ) . inc ( amount )
101
142
}
102
143
103
144
increaseGauge ( category , amount = 1 ) {
104
- const metric = this . gaugeRegistry . getSingleMetric ( category . replaceAll ( '-' , '_' ) )
145
+ const metric = this . metrics . get ( category )
105
146
if ( ! metric ) throw new Error ( `Metric ${ category } not found` )
106
147
return metric . inc ( amount )
107
148
}
108
149
109
150
decreaseGauge ( category , amount = 1 ) {
110
- const metric = this . gaugeRegistry . getSingleMetric ( category . replaceAll ( '-' , '_' ) )
151
+ const metric = this . metrics . get ( category )
111
152
if ( ! metric ) throw new Error ( `Metric ${ category } not found` )
112
153
return metric . inc ( - 1 * amount )
113
154
}
114
155
115
156
setGauge ( category , value ) {
116
- const metric = this . gaugeRegistry . getSingleMetric ( category . replaceAll ( '-' , '_' ) )
157
+ const metric = this . metrics . get ( category )
117
158
if ( ! metric ) throw new Error ( `Metric ${ category } not found` )
118
159
return metric . set ( value )
119
160
}
120
161
121
162
async trackDuration ( category , promise ) {
122
- const metric = this . durationsRegistry . getSingleMetric ( category . replaceAll ( '-' , '_' ) )
163
+ const metric = this . metrics . get ( category )
123
164
if ( ! metric ) throw new Error ( `Metric ${ category } not found` )
124
165
125
166
const end = metric . startTimer ( )
0 commit comments