@platformatic/wattpm-pprof-capture 3.21.0 → 3.23.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 +1 -49
- package/lib/source-mapper-wrapper.js +65 -0
- package/package.json +3 -3
- package/test/source-mapper-wrapper.test.js +43 -0
package/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { time, heap, SourceMapper } from '@datadog/pprof'
|
|
|
2
2
|
import { performance } from 'node:perf_hooks'
|
|
3
3
|
import { workerData } from 'node:worker_threads'
|
|
4
4
|
import { NoProfileAvailableError, NotEnoughELUError, ProfilingAlreadyStartedError, ProfilingNotStartedError } from './lib/errors.js'
|
|
5
|
+
import { SourceMapperWrapper } from './lib/source-mapper-wrapper.js'
|
|
5
6
|
|
|
6
7
|
const kITC = Symbol.for('plt.runtime.itc')
|
|
7
8
|
|
|
@@ -9,55 +10,6 @@ const kITC = Symbol.for('plt.runtime.itc')
|
|
|
9
10
|
let sourceMapper = null
|
|
10
11
|
let sourceMapperInitialized = false
|
|
11
12
|
|
|
12
|
-
/**
|
|
13
|
-
* Wrapper around SourceMapper that fixes Windows path normalization issues.
|
|
14
|
-
*
|
|
15
|
-
* On Windows, V8 profiler returns paths like `file:///D:/path/to/file.js`.
|
|
16
|
-
* The @datadog/pprof library removes `file://` leaving `/D:/path/to/file.js`,
|
|
17
|
-
* but SourceMapper stores paths as `D:\path\to\file.js`.
|
|
18
|
-
*
|
|
19
|
-
* This wrapper normalizes Windows paths to match the internal format.
|
|
20
|
-
*/
|
|
21
|
-
class SourceMapperWrapper {
|
|
22
|
-
constructor (innerMapper) {
|
|
23
|
-
this.innerMapper = innerMapper
|
|
24
|
-
this.debug = innerMapper.debug
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Normalize Windows-style paths from V8 profiler to match SourceMapper format.
|
|
29
|
-
* Handles paths like `/D:/path/to/file.js` -> `D:\path\to\file.js`
|
|
30
|
-
*/
|
|
31
|
-
normalizePath (filePath) {
|
|
32
|
-
if (process.platform !== 'win32') {
|
|
33
|
-
return filePath
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Handle paths like /D:/path/to/file -> D:\path\to\file
|
|
37
|
-
// This happens because pprof removes 'file://' from 'file:///D:/path/to/file'
|
|
38
|
-
if (filePath.startsWith('/') && filePath.length > 2 && filePath[2] === ':') {
|
|
39
|
-
// Remove leading slash and convert forward slashes to backslashes
|
|
40
|
-
return filePath.slice(1).replace(/\//g, '\\')
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Also convert any forward slashes to backslashes on Windows
|
|
44
|
-
return filePath.replace(/\//g, '\\')
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
hasMappingInfo (inputPath) {
|
|
48
|
-
const normalized = this.normalizePath(inputPath)
|
|
49
|
-
return this.innerMapper.hasMappingInfo(normalized)
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
mappingInfo (location) {
|
|
53
|
-
const normalized = {
|
|
54
|
-
...location,
|
|
55
|
-
file: this.normalizePath(location.file)
|
|
56
|
-
}
|
|
57
|
-
return this.innerMapper.mappingInfo(normalized)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
13
|
// Track ELU globally (shared across all profiler types)
|
|
62
14
|
let lastELU = null
|
|
63
15
|
let previousELU = performance.eventLoopUtilization()
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrapper around SourceMapper that fixes Windows path normalization issues.
|
|
3
|
+
*
|
|
4
|
+
* On Windows, V8 profiler returns paths like `file:///D:/path/to/file.js`.
|
|
5
|
+
* The @datadog/pprof library removes `file://` leaving `/D:/path/to/file.js`,
|
|
6
|
+
* but SourceMapper stores paths as `D:\path\to\file.js`.
|
|
7
|
+
*
|
|
8
|
+
* This wrapper normalizes Windows paths to match the internal format.
|
|
9
|
+
*/
|
|
10
|
+
export class SourceMapperWrapper {
|
|
11
|
+
constructor (innerMapper) {
|
|
12
|
+
this.innerMapper = innerMapper
|
|
13
|
+
this.debug = innerMapper.debug
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Normalize Windows-style paths from V8 profiler to match SourceMapper format.
|
|
18
|
+
* Handles paths like `/D:/path/to/file.js` -> `D:\path\to\file.js`
|
|
19
|
+
*/
|
|
20
|
+
normalizePath (filePath) {
|
|
21
|
+
if (process.platform !== 'win32') {
|
|
22
|
+
return filePath
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Handle paths like /D:/path/to/file -> D:\path\to\file
|
|
26
|
+
// This happens because pprof removes 'file://' from 'file:///D:/path/to/file'
|
|
27
|
+
if (filePath.startsWith('/') && filePath.length > 2 && filePath[2] === ':') {
|
|
28
|
+
// Remove leading slash and convert forward slashes to backslashes
|
|
29
|
+
return filePath.slice(1).replace(/\//g, '\\')
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Also convert any forward slashes to backslashes on Windows
|
|
33
|
+
return filePath.replace(/\//g, '\\')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
hasMappingInfo (inputPath) {
|
|
37
|
+
const normalized = this.normalizePath(inputPath)
|
|
38
|
+
return this.innerMapper.hasMappingInfo(normalized)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
mappingInfo (location) {
|
|
42
|
+
const normalized = {
|
|
43
|
+
...location,
|
|
44
|
+
file: this.normalizePath(location.file)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const protocols = ['webpack:']
|
|
48
|
+
const mappedInfo = this.innerMapper.mappingInfo(normalized)
|
|
49
|
+
// The @datadog/pprof SourceMapper uses path.resolve() which treats webpack: URLs
|
|
50
|
+
// as relative paths, creating malformed paths like:
|
|
51
|
+
// /path/to/.next/server/app/api/heavy/webpack:/next/src/app/api/heavy/route.js
|
|
52
|
+
// We need to extract just the webpack: URL part
|
|
53
|
+
|
|
54
|
+
for (const protocol of protocols) {
|
|
55
|
+
if (!mappedInfo.file) continue
|
|
56
|
+
|
|
57
|
+
const webpackIndex = mappedInfo.file.indexOf(protocol)
|
|
58
|
+
if (webpackIndex > 0) {
|
|
59
|
+
// Extract just the webpack: URL
|
|
60
|
+
mappedInfo.file = mappedInfo.file.substring(webpackIndex)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return mappedInfo
|
|
64
|
+
}
|
|
65
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/wattpm-pprof-capture",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.23.0",
|
|
4
4
|
"description": "pprof profiling capture for wattpm",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"neostandard": "^0.12.0",
|
|
27
27
|
"pprof-format": "^2.1.0",
|
|
28
28
|
"typescript": "^5.0.0",
|
|
29
|
-
"@platformatic/foundation": "3.
|
|
30
|
-
"@platformatic/service": "3.
|
|
29
|
+
"@platformatic/foundation": "3.23.0",
|
|
30
|
+
"@platformatic/service": "3.23.0"
|
|
31
31
|
},
|
|
32
32
|
"engines": {
|
|
33
33
|
"node": ">=22.19.0"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import { deepStrictEqual } from 'node:assert'
|
|
3
|
+
import { SourceMapperWrapper } from '../lib/source-mapper-wrapper.js'
|
|
4
|
+
|
|
5
|
+
class MockSourceMapper {
|
|
6
|
+
constructor (mapper) {
|
|
7
|
+
this.mapper = mapper
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
mappingInfo (location) {
|
|
11
|
+
return this.mapper(location)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
test('should correctly map webpack paths', async () => {
|
|
16
|
+
const appPath = '/Users/ivan-tymoshenko/projects/platformatic/leads-demo/web/next'
|
|
17
|
+
const info = {
|
|
18
|
+
file: `${appPath}/.next/server/app/api/heavy/route.js`,
|
|
19
|
+
line: 1,
|
|
20
|
+
column: 42,
|
|
21
|
+
name: 'a'
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const mapper = () => {
|
|
25
|
+
return {
|
|
26
|
+
file: `${appPath}/.next/server/app/api/heavy/webpack:/next/src/app/api/heavy/route.js`,
|
|
27
|
+
name: 'fibonacci',
|
|
28
|
+
line: 6,
|
|
29
|
+
column: 12
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const innerMapper = new MockSourceMapper(mapper)
|
|
34
|
+
const sourceMapper = new SourceMapperWrapper(innerMapper)
|
|
35
|
+
|
|
36
|
+
const mappedInfo = sourceMapper.mappingInfo(info)
|
|
37
|
+
deepStrictEqual(mappedInfo, {
|
|
38
|
+
file: 'webpack:/next/src/app/api/heavy/route.js',
|
|
39
|
+
name: 'fibonacci',
|
|
40
|
+
line: 6,
|
|
41
|
+
column: 12
|
|
42
|
+
})
|
|
43
|
+
})
|