@@ -42,17 +42,20 @@ function findWebSpan (startedSpans, spanId) {
42
42
}
43
43
44
44
class Profiler extends EventEmitter {
45
+ #compressionFn
46
+ #compressionOptions
47
+ #enabled = false
48
+ #endpointCounts = new Map ( )
49
+ #lastStart
50
+ #logger
45
51
#profileSeq = 0
52
+ #spanFinishListener
53
+ #timer
46
54
47
55
constructor ( ) {
48
56
super ( )
49
- this . _enabled = false
50
- this . _logger = undefined
51
57
this . _config = undefined
52
- this . _timer = undefined
53
- this . _lastStart = undefined
54
58
this . _timeoutInterval = undefined
55
- this . endpointCounts = new Map ( )
56
59
}
57
60
58
61
start ( options ) {
@@ -63,17 +66,21 @@ class Profiler extends EventEmitter {
63
66
} )
64
67
}
65
68
66
- _logError ( err ) {
67
- logError ( this . _logger , err )
69
+ get enabled ( ) {
70
+ return this . #enabled
71
+ }
72
+
73
+ #logError ( err ) {
74
+ logError ( this . #logger, err )
68
75
}
69
76
70
77
async _start ( options ) {
71
- if ( this . _enabled ) return true
78
+ if ( this . enabled ) return true
72
79
73
80
const config = this . _config = new Config ( options )
74
81
75
- this . _logger = config . logger
76
- this . _enabled = true
82
+ this . #logger = config . logger
83
+ this . #enabled = true
77
84
this . _setInterval ( )
78
85
79
86
// Log errors if the source map finder fails, but don't prevent the rest
@@ -85,7 +92,7 @@ class Profiler extends EventEmitter {
85
92
86
93
mapper = await maybeSourceMap ( config . sourceMap , SourceMapper , config . debugSourceMaps )
87
94
if ( config . sourceMap && config . debugSourceMaps ) {
88
- this . _logger . debug ( ( ) => {
95
+ this . #logger . debug ( ( ) => {
89
96
return mapper . infoMap . size === 0
90
97
? 'Found no source maps'
91
98
: `Found source maps for following files: [${ [ ...mapper . infoMap . keys ( ) ] . join ( ', ' ) } ]`
@@ -95,18 +102,18 @@ class Profiler extends EventEmitter {
95
102
const clevel = config . uploadCompression . level
96
103
switch ( config . uploadCompression . method ) {
97
104
case 'gzip' :
98
- this . _compressionFn = promisify ( zlib . gzip )
105
+ this . #compressionFn = promisify ( zlib . gzip )
99
106
if ( clevel !== undefined ) {
100
- this . _compressionOptions = {
107
+ this . #compressionOptions = {
101
108
level : clevel
102
109
}
103
110
}
104
111
break
105
112
case 'zstd' :
106
113
if ( typeof zlib . zstdCompress === 'function' ) {
107
- this . _compressionFn = promisify ( zlib . zstdCompress )
114
+ this . #compressionFn = promisify ( zlib . zstdCompress )
108
115
if ( clevel !== undefined ) {
109
- this . _compressionOptions = {
116
+ this . #compressionOptions = {
110
117
params : {
111
118
[ zlib . constants . ZSTD_c_compressionLevel ] : clevel
112
119
}
@@ -115,44 +122,44 @@ class Profiler extends EventEmitter {
115
122
} else {
116
123
const zstdCompress = require ( '@datadog/libdatadog' ) . load ( 'datadog-js-zstd' ) . zstd_compress
117
124
const level = clevel ?? 0 // 0 is zstd default compression level
118
- this . _compressionFn = ( buffer ) => Promise . resolve ( Buffer . from ( zstdCompress ( buffer , level ) ) )
125
+ this . #compressionFn = ( buffer ) => Promise . resolve ( Buffer . from ( zstdCompress ( buffer , level ) ) )
119
126
}
120
127
break
121
128
}
122
129
} catch ( err ) {
123
- this . _logError ( err )
130
+ this . #logError ( err )
124
131
}
125
132
126
133
try {
127
134
const start = new Date ( )
128
- const nearOOMCallback = this . _nearOOMExport . bind ( this )
135
+ const nearOOMCallback = this . #nearOOMExport . bind ( this )
129
136
for ( const profiler of config . profilers ) {
130
137
// TODO: move this out of Profiler when restoring sourcemap support
131
138
profiler . start ( {
132
139
mapper,
133
140
nearOOMCallback
134
141
} )
135
- this . _logger . debug ( `Started ${ profiler . type } profiler in ${ threadNamePrefix } thread` )
142
+ this . #logger . debug ( `Started ${ profiler . type } profiler in ${ threadNamePrefix } thread` )
136
143
}
137
144
138
145
if ( config . endpointCollectionEnabled ) {
139
- this . _spanFinishListener = this . _onSpanFinish . bind ( this )
140
- spanFinishedChannel . subscribe ( this . _spanFinishListener )
146
+ this . #spanFinishListener = this . #onSpanFinish . bind ( this )
147
+ spanFinishedChannel . subscribe ( this . #spanFinishListener )
141
148
}
142
149
143
150
this . _capture ( this . _timeoutInterval , start )
144
151
return true
145
152
} catch ( e ) {
146
- this . _logError ( e )
147
- this . _stop ( )
153
+ this . #logError ( e )
154
+ this . #stop ( )
148
155
return false
149
156
}
150
157
}
151
158
152
- _nearOOMExport ( profileType , encodedProfile ) {
153
- const start = this . _lastStart
159
+ #nearOOMExport ( profileType , encodedProfile ) {
160
+ const start = this . #lastStart
154
161
const end = new Date ( )
155
- this . _submit ( {
162
+ this . #submit ( {
156
163
[ profileType ] : encodedProfile
157
164
} , start , end , snapshotKinds . ON_OUT_OF_MEMORY )
158
165
}
@@ -162,45 +169,45 @@ class Profiler extends EventEmitter {
162
169
}
163
170
164
171
stop ( ) {
165
- if ( ! this . _enabled ) return
172
+ if ( ! this . enabled ) return
166
173
167
174
// collect and export current profiles
168
175
// once collect returns, profilers can be safely stopped
169
176
this . _collect ( snapshotKinds . ON_SHUTDOWN , false )
170
- this . _stop ( )
177
+ this . #stop ( )
171
178
}
172
179
173
- _stop ( ) {
174
- if ( ! this . _enabled ) return
180
+ #stop ( ) {
181
+ if ( ! this . enabled ) return
175
182
176
- this . _enabled = false
183
+ this . #enabled = false
177
184
178
- if ( this . _spanFinishListener !== undefined ) {
179
- spanFinishedChannel . unsubscribe ( this . _spanFinishListener )
180
- this . _spanFinishListener = undefined
185
+ if ( this . #spanFinishListener !== undefined ) {
186
+ spanFinishedChannel . unsubscribe ( this . #spanFinishListener )
187
+ this . #spanFinishListener = undefined
181
188
}
182
189
183
190
for ( const profiler of this . _config . profilers ) {
184
191
profiler . stop ( )
185
- this . _logger . debug ( `Stopped ${ profiler . type } profiler in ${ threadNamePrefix } thread` )
192
+ this . #logger . debug ( `Stopped ${ profiler . type } profiler in ${ threadNamePrefix } thread` )
186
193
}
187
194
188
- clearTimeout ( this . _timer )
189
- this . _timer = undefined
195
+ clearTimeout ( this . #timer )
196
+ this . #timer = undefined
190
197
}
191
198
192
199
_capture ( timeout , start ) {
193
- if ( ! this . _enabled ) return
194
- this . _lastStart = start
195
- if ( ! this . _timer || timeout !== this . _timeoutInterval ) {
196
- this . _timer = setTimeout ( ( ) => this . _collect ( snapshotKinds . PERIODIC ) , timeout )
197
- this . _timer . unref ( )
200
+ if ( ! this . enabled ) return
201
+ this . #lastStart = start
202
+ if ( ! this . #timer || timeout !== this . _timeoutInterval ) {
203
+ this . #timer = setTimeout ( ( ) => this . _collect ( snapshotKinds . PERIODIC ) , timeout )
204
+ this . #timer . unref ( )
198
205
} else {
199
- this . _timer . refresh ( )
206
+ this . #timer . refresh ( )
200
207
}
201
208
}
202
209
203
- _onSpanFinish ( span ) {
210
+ #onSpanFinish ( span ) {
204
211
const context = span . context ( )
205
212
const tags = context . _tags
206
213
if ( ! isWebServerSpan ( tags ) ) return
@@ -211,19 +218,19 @@ class Profiler extends EventEmitter {
211
218
// Make sure this is the outermost web span, just in case so we don't overcount
212
219
if ( findWebSpan ( getStartedSpans ( context ) , context . _parentId ) ) return
213
220
214
- let counter = this . endpointCounts . get ( endpointName )
221
+ let counter = this . # endpointCounts. get ( endpointName )
215
222
if ( counter === undefined ) {
216
223
counter = { count : 1 }
217
- this . endpointCounts . set ( endpointName , counter )
224
+ this . # endpointCounts. set ( endpointName , counter )
218
225
} else {
219
226
counter . count ++
220
227
}
221
228
}
222
229
223
230
async _collect ( snapshotKind , restart = true ) {
224
- if ( ! this . _enabled ) return
231
+ if ( ! this . enabled ) return
225
232
226
- const startDate = this . _lastStart
233
+ const startDate = this . #lastStart
227
234
const endDate = new Date ( )
228
235
const profiles = [ ]
229
236
const encodedProfiles = { }
@@ -238,7 +245,7 @@ class Profiler extends EventEmitter {
238
245
for ( const profiler of this . _config . profilers ) {
239
246
const profile = profiler . profile ( restart , startDate , endDate )
240
247
if ( ! restart ) {
241
- this . _logger . debug ( `Stopped ${ profiler . type } profiler in ${ threadNamePrefix } thread` )
248
+ this . #logger . debug ( `Stopped ${ profiler . type } profiler in ${ threadNamePrefix } thread` )
242
249
}
243
250
if ( ! profile ) continue
244
251
profiles . push ( { profiler, profile } )
@@ -255,11 +262,11 @@ class Profiler extends EventEmitter {
255
262
await Promise . all ( profiles . map ( async ( { profiler, profile } ) => {
256
263
try {
257
264
const encoded = await profiler . encode ( profile )
258
- const compressed = encoded instanceof Buffer && this . _compressionFn !== undefined
259
- ? await this . _compressionFn ( encoded , this . _compressionOptions )
265
+ const compressed = encoded instanceof Buffer && this . #compressionFn !== undefined
266
+ ? await this . #compressionFn ( encoded , this . #compressionOptions )
260
267
: encoded
261
268
encodedProfiles [ profiler . type ] = compressed
262
- this . _logger . debug ( ( ) => {
269
+ this . #logger . debug ( ( ) => {
263
270
const profileJson = JSON . stringify ( profile , ( key , value ) => {
264
271
return typeof value === 'bigint' ? value . toString ( ) : value
265
272
} )
@@ -269,38 +276,38 @@ class Profiler extends EventEmitter {
269
276
} catch ( err ) {
270
277
// If encoding one of the profile types fails, we should still try to
271
278
// encode and submit the other profile types.
272
- this . _logError ( err )
279
+ this . #logError ( err )
273
280
}
274
281
} ) )
275
282
276
283
if ( hasEncoded ) {
277
- await this . _submit ( encodedProfiles , startDate , endDate , snapshotKind )
284
+ await this . #submit ( encodedProfiles , startDate , endDate , snapshotKind )
278
285
profileSubmittedChannel . publish ( )
279
- this . _logger . debug ( 'Submitted profiles' )
286
+ this . #logger . debug ( 'Submitted profiles' )
280
287
}
281
288
} catch ( err ) {
282
- this . _logError ( err )
283
- this . _stop ( )
289
+ this . #logError ( err )
290
+ this . #stop ( )
284
291
}
285
292
}
286
293
287
- _submit ( profiles , start , end , snapshotKind ) {
294
+ #submit ( profiles , start , end , snapshotKind ) {
288
295
const { tags } = this . _config
289
296
290
297
// Flatten endpoint counts
291
298
const endpointCounts = { }
292
- for ( const [ endpoint , { count } ] of this . endpointCounts ) {
299
+ for ( const [ endpoint , { count } ] of this . # endpointCounts) {
293
300
endpointCounts [ endpoint ] = count
294
301
}
295
- this . endpointCounts . clear ( )
302
+ this . # endpointCounts. clear ( )
296
303
297
304
tags . snapshot = snapshotKind
298
305
tags . profile_seq = this . #profileSeq++
299
306
const exportSpec = { profiles, start, end, tags, endpointCounts }
300
307
const tasks = this . _config . exporters . map ( exporter =>
301
308
exporter . export ( exportSpec ) . catch ( err => {
302
- if ( this . _logger ) {
303
- this . _logger . warn ( err )
309
+ if ( this . #logger ) {
310
+ this . #logger . warn ( err )
304
311
}
305
312
} )
306
313
)
@@ -310,24 +317,32 @@ class Profiler extends EventEmitter {
310
317
}
311
318
312
319
class ServerlessProfiler extends Profiler {
320
+ #profiledIntervals = 0
321
+ #interval = 1 // seconds
322
+ #flushAfterIntervals
323
+
313
324
constructor ( ) {
314
325
super ( )
315
- this . _profiledIntervals = 0
316
- this . _interval = 1
317
- this . _flushAfterIntervals = undefined
326
+ this . #profiledIntervals = 0
327
+ this . #interval = 1
328
+ this . #flushAfterIntervals = undefined
329
+ }
330
+
331
+ get profiledIntervals ( ) {
332
+ return this . #profiledIntervals
318
333
}
319
334
320
335
_setInterval ( ) {
321
- this . _timeoutInterval = this . _interval * 1000
322
- this . _flushAfterIntervals = this . _config . flushInterval / 1000
336
+ this . _timeoutInterval = this . #interval * 1000
337
+ this . #flushAfterIntervals = this . _config . flushInterval / 1000
323
338
}
324
339
325
340
async _collect ( snapshotKind , restart = true ) {
326
- if ( this . _profiledIntervals >= this . _flushAfterIntervals || ! restart ) {
327
- this . _profiledIntervals = 0
341
+ if ( this . #profiledIntervals >= this . #flushAfterIntervals || ! restart ) {
342
+ this . #profiledIntervals = 0
328
343
await super . _collect ( snapshotKind , restart )
329
344
} else {
330
- this . _profiledIntervals += 1
345
+ this . #profiledIntervals += 1
331
346
this . _capture ( this . _timeoutInterval , new Date ( ) )
332
347
// Don't submit profile until 65 (flushAfterIntervals) intervals have elapsed
333
348
}
0 commit comments