@platformatic/wattpm-pprof-capture 3.54.0 → 3.56.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/index.js +43 -22
- package/lib/node-modules-sourcemaps.js +2 -1
- package/package.json +5 -4
package/index.js
CHANGED
|
@@ -1,10 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { heap, SourceMapper, time } from '@datadog/pprof'
|
|
2
|
+
import { getITC, getLogger } from '@platformatic/globals'
|
|
2
3
|
import { performance } from 'node:perf_hooks'
|
|
3
4
|
import { workerData } from 'node:worker_threads'
|
|
4
5
|
import { NoProfileAvailableError, NotEnoughELUError, ProfilingAlreadyStartedError, ProfilingNotStartedError } from './lib/errors.js'
|
|
5
6
|
import { SourceMapperWrapper } from './lib/source-mapper-wrapper.js'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// @datadog/pprof >= 5.14.2 introduced a regression in the legacy time profiler
|
|
9
|
+
// `stop()`: it now clears the internal source mapper (via handleStopNoRestart)
|
|
10
|
+
// *before* serializing the profile, so transpiled frames (e.g. TypeScript) are
|
|
11
|
+
// no longer mapped back to their original `.ts` sources. The `stopV2()` entry
|
|
12
|
+
// point serializes the profile while the source mapper is still set — the
|
|
13
|
+
// behaviour `stop()` had in earlier versions. It is not re-exported on the
|
|
14
|
+
// public `time` facade, so resolve it from the internal module when available
|
|
15
|
+
// and fall back to the public `stop()` otherwise (e.g. older versions).
|
|
16
|
+
let stopTimeProfilerV2 = null
|
|
17
|
+
try {
|
|
18
|
+
;({ stopV2: stopTimeProfilerV2 } = await import('@datadog/pprof/out/src/time-profiler.js'))
|
|
19
|
+
} catch {
|
|
20
|
+
// Internal module path not available; fall back to the public stop().
|
|
21
|
+
}
|
|
8
22
|
|
|
9
23
|
// SourceMapper for resolving transpiled code locations back to original source
|
|
10
24
|
let sourceMapper = null
|
|
@@ -55,14 +69,15 @@ const profilingState = {
|
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
// Keep trying until ITC is available. This is needed because preloads run
|
|
58
|
-
// before the app thread initialization, so
|
|
59
|
-
// and ITC don't exist yet.
|
|
72
|
+
// before the app thread initialization, so messaging and ITC don't exist yet.
|
|
60
73
|
const registerInterval = setInterval(() => {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
const itc = getITC({ throwOnMissing: false })
|
|
75
|
+
|
|
76
|
+
if (itc) {
|
|
77
|
+
itc.handle('getLastProfile', getLastProfile)
|
|
78
|
+
itc.handle('startProfiling', startProfiling)
|
|
79
|
+
itc.handle('stopProfiling', stopProfiling)
|
|
80
|
+
itc.handle('getProfilingState', getProfilingState)
|
|
66
81
|
clearInterval(registerInterval)
|
|
67
82
|
}
|
|
68
83
|
}, 10)
|
|
@@ -159,9 +174,11 @@ function stopProfiler (type, state) {
|
|
|
159
174
|
state.latestProfile = (state.sourceMapsEnabled && sourceMapper) ? profiler.profile(undefined, sourceMapper) : profiler.profile()
|
|
160
175
|
profiler.stop()
|
|
161
176
|
} else {
|
|
162
|
-
// CPU time profiler returns the profile when stopping
|
|
163
|
-
// sourceMapper was already passed to start(), so it's applied automatically
|
|
164
|
-
|
|
177
|
+
// CPU time profiler returns the profile when stopping.
|
|
178
|
+
// sourceMapper was already passed to start(), so it's applied automatically.
|
|
179
|
+
// Use stopV2() when available so the source mapper is honoured during
|
|
180
|
+
// serialization (see the note next to stopTimeProfilerV2 above).
|
|
181
|
+
state.latestProfile = stopTimeProfilerV2 ? stopTimeProfilerV2() : profiler.stop()
|
|
165
182
|
}
|
|
166
183
|
}
|
|
167
184
|
|
|
@@ -211,18 +228,19 @@ function startIfOverThreshold (type, state, wasRunning = state.profilerStarted)
|
|
|
211
228
|
// Was not running: only start if ELU rises above start threshold
|
|
212
229
|
: isAboveThreshold(state)
|
|
213
230
|
|
|
231
|
+
const logger = getLogger({ throwOnMissing: false })
|
|
214
232
|
if (shouldRun) {
|
|
215
233
|
// ELU is high enough, start/restart profiling
|
|
216
|
-
if (!wasRunning && !state.profilerStarted &&
|
|
217
|
-
|
|
234
|
+
if (!wasRunning && !state.profilerStarted && logger) {
|
|
235
|
+
logger.debug(
|
|
218
236
|
{ type, eluThreshold: state.eluThreshold, currentELU },
|
|
219
237
|
'Starting profiler due to ELU threshold exceeded'
|
|
220
238
|
)
|
|
221
239
|
}
|
|
222
240
|
startProfiler(type, state, state.options)
|
|
223
|
-
} else if (!shouldRun && wasRunning &&
|
|
241
|
+
} else if (!shouldRun && wasRunning && state.eluThreshold != null && logger) {
|
|
224
242
|
// Log when deciding not to restart after stopping (only in rotation context)
|
|
225
|
-
|
|
243
|
+
logger.debug(
|
|
226
244
|
{ type, eluThreshold: state.eluThreshold, currentELU },
|
|
227
245
|
'Pausing profiler due to ELU below threshold'
|
|
228
246
|
)
|
|
@@ -240,8 +258,9 @@ async function initializeSourceMapper (options = {}) {
|
|
|
240
258
|
// Get the application directory from workerData
|
|
241
259
|
const appPath = workerData?.applicationConfig?.path
|
|
242
260
|
if (!appPath) {
|
|
243
|
-
|
|
244
|
-
|
|
261
|
+
const logger = getLogger({ throwOnMissing: false })
|
|
262
|
+
if (logger) {
|
|
263
|
+
logger.debug('No application path available for sourcemap resolution')
|
|
245
264
|
}
|
|
246
265
|
return
|
|
247
266
|
}
|
|
@@ -267,16 +286,18 @@ async function initializeSourceMapper (options = {}) {
|
|
|
267
286
|
// Wrap the SourceMapper to fix Windows path normalization
|
|
268
287
|
sourceMapper = new SourceMapperWrapper(innerMapper)
|
|
269
288
|
|
|
270
|
-
|
|
289
|
+
const logger = getLogger({ throwOnMissing: false })
|
|
290
|
+
if (logger) {
|
|
271
291
|
const hasMappings = sourceMapper && typeof sourceMapper.hasMappingInfo === 'function'
|
|
272
|
-
|
|
292
|
+
logger.info(
|
|
273
293
|
{ appPath, hasSourceMapper: !!sourceMapper, hasMappingInfo: hasMappings },
|
|
274
294
|
'SourceMapper initialized for profiling'
|
|
275
295
|
)
|
|
276
296
|
}
|
|
277
297
|
} catch (err) {
|
|
278
|
-
|
|
279
|
-
|
|
298
|
+
const logger = getLogger({ throwOnMissing: false })
|
|
299
|
+
if (logger) {
|
|
300
|
+
logger.warn(
|
|
280
301
|
{ err: err.message, stack: err.stack },
|
|
281
302
|
'Failed to initialize SourceMapper'
|
|
282
303
|
)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getLogger } from '@platformatic/globals'
|
|
1
2
|
import { promises as fs } from 'node:fs'
|
|
2
3
|
import path from 'node:path'
|
|
3
4
|
import { createRequire } from 'node:module'
|
|
@@ -184,7 +185,7 @@ function resolveModulePath (appPath, moduleName) {
|
|
|
184
185
|
*/
|
|
185
186
|
export async function loadNodeModulesSourceMaps (appPath, moduleNames, debug = false) {
|
|
186
187
|
const entries = new Map()
|
|
187
|
-
const logger =
|
|
188
|
+
const logger = getLogger({ throwOnMissing: false })
|
|
188
189
|
|
|
189
190
|
if (debug && logger) {
|
|
190
191
|
logger.debug({ appPath, moduleNames }, 'Loading source maps from node_modules')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/wattpm-pprof-capture",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.56.0",
|
|
4
4
|
"description": "pprof profiling capture for wattpm",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@datadog/pprof": "^5.3.0",
|
|
19
19
|
"@fastify/error": "^4.0.0",
|
|
20
|
-
"undici": "^7.
|
|
20
|
+
"undici": "^7.27.2",
|
|
21
|
+
"@platformatic/globals": "3.56.0"
|
|
21
22
|
},
|
|
22
23
|
"devDependencies": {
|
|
23
24
|
"@types/node": "^22.0.0",
|
|
@@ -26,8 +27,8 @@
|
|
|
26
27
|
"neostandard": "^0.12.0",
|
|
27
28
|
"pprof-format": "^2.1.0",
|
|
28
29
|
"typescript": "^5.0.0",
|
|
29
|
-
"@platformatic/service": "3.
|
|
30
|
-
"@platformatic/foundation": "3.
|
|
30
|
+
"@platformatic/service": "3.56.0",
|
|
31
|
+
"@platformatic/foundation": "3.56.0"
|
|
31
32
|
},
|
|
32
33
|
"engines": {
|
|
33
34
|
"node": ">=22.19.0"
|