wattpm 3.41.0 → 3.42.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/README.md +4 -3
- package/index.js +4 -0
- package/lib/commands/help.js +2 -1
- package/lib/commands/snapshot.js +99 -0
- package/package.json +5 -5
- package/schema.json +1 -1
package/README.md
CHANGED
|
@@ -19,18 +19,19 @@ Watt supports the stacks you love most, including [Next.js](https://nextjs.org/)
|
|
|
19
19
|
|
|
20
20
|
```bash
|
|
21
21
|
# Create a new application
|
|
22
|
-
npx wattpm@latest
|
|
22
|
+
npx wattpm@latest create
|
|
23
23
|
|
|
24
24
|
# Or install manually:
|
|
25
25
|
npm install wattpm
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Follow our [Quick Start Guide](https://docs.platformatic.dev/docs/getting-started/quick-start)
|
|
29
|
-
|
|
29
|
+
to get up and running with Watt.
|
|
30
30
|
|
|
31
31
|
## Documentation
|
|
32
32
|
|
|
33
|
-
- [
|
|
33
|
+
- [Quick Start](https://docs.platformatic.dev/docs/getting-started/quick-start)
|
|
34
|
+
- [Running Your Project in Watt](https://docs.platformatic.dev/docs/getting-started/port-your-app)
|
|
34
35
|
- [Reference](https://docs.platformatic.dev/docs/reference/wattpm/overview)
|
|
35
36
|
- [Guides](https://docs.platformatic.dev/docs/guides/build-modular-monolith)
|
|
36
37
|
|
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { applicationsCommand, configCommand, envCommand, psCommand } from './lib
|
|
|
14
14
|
import { metricsCommand } from './lib/commands/metrics.js'
|
|
15
15
|
import { pprofCommand } from './lib/commands/pprof.js'
|
|
16
16
|
import { replCommand } from './lib/commands/repl.js'
|
|
17
|
+
import { heapSnapshotCommand } from './lib/commands/snapshot.js'
|
|
17
18
|
import { version } from './lib/schema.js'
|
|
18
19
|
|
|
19
20
|
export * from './lib/schema.js'
|
|
@@ -116,6 +117,9 @@ export async function main () {
|
|
|
116
117
|
case 'pprof':
|
|
117
118
|
command = pprofCommand
|
|
118
119
|
break
|
|
120
|
+
case 'heap-snapshot':
|
|
121
|
+
command = heapSnapshotCommand
|
|
122
|
+
break
|
|
119
123
|
case 'repl':
|
|
120
124
|
command = replCommand
|
|
121
125
|
break
|
package/lib/commands/help.js
CHANGED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { RuntimeApiClient, getMatchingRuntime } from '@platformatic/control'
|
|
2
|
+
import { ensureLoggableError, logFatalError, parseArgs } from '@platformatic/foundation'
|
|
3
|
+
import { bold } from 'colorette'
|
|
4
|
+
import { createWriteStream } from 'node:fs'
|
|
5
|
+
import { resolve } from 'node:path'
|
|
6
|
+
import { pipeline } from 'node:stream/promises'
|
|
7
|
+
|
|
8
|
+
export async function heapSnapshotCommand (logger, args) {
|
|
9
|
+
const client = new RuntimeApiClient({ logger, socket: this.socket })
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const { positionals, values } = parseArgs(
|
|
13
|
+
args,
|
|
14
|
+
{
|
|
15
|
+
dir: { type: 'string', short: 'd' }
|
|
16
|
+
},
|
|
17
|
+
false
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
const [runtime, remainingPositionals] = await getMatchingRuntime(client, positionals)
|
|
21
|
+
const { applications: runtimeApplications } = await client.getRuntimeApplications(runtime.pid)
|
|
22
|
+
|
|
23
|
+
const applicationId = remainingPositionals[0]
|
|
24
|
+
const timestamp = new Date().toISOString().replace(/:/g, '-').replace(/\./g, '-')
|
|
25
|
+
const outputDir = values.dir || process.cwd()
|
|
26
|
+
|
|
27
|
+
if (applicationId) {
|
|
28
|
+
const application = runtimeApplications.find(s => s.id === applicationId)
|
|
29
|
+
if (!application) {
|
|
30
|
+
return logFatalError(logger, `Application not found: ${applicationId}`)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
logger.info(`Taking heap snapshot for application ${bold(applicationId)}...`)
|
|
34
|
+
const body = await client.takeApplicationHeapSnapshot(runtime.pid, applicationId)
|
|
35
|
+
const filename = `heap-${applicationId}-${timestamp}.heapsnapshot`
|
|
36
|
+
const filepath = resolve(outputDir, filename)
|
|
37
|
+
await pipeline(body, createWriteStream(filepath))
|
|
38
|
+
logger.info(`Heap snapshot saved to ${bold(filepath)}`)
|
|
39
|
+
} else {
|
|
40
|
+
for (const application of runtimeApplications) {
|
|
41
|
+
try {
|
|
42
|
+
logger.info(`Taking heap snapshot for application ${bold(application.id)}...`)
|
|
43
|
+
const body = await client.takeApplicationHeapSnapshot(runtime.pid, application.id)
|
|
44
|
+
const filename = `heap-${application.id}-${timestamp}.heapsnapshot`
|
|
45
|
+
const filepath = resolve(outputDir, filename)
|
|
46
|
+
await pipeline(body, createWriteStream(filepath))
|
|
47
|
+
logger.info(`Heap snapshot saved to ${bold(filepath)}`)
|
|
48
|
+
} catch (error) {
|
|
49
|
+
logger.warn(`Failed to take heap snapshot for application ${application.id}: ${error.message}`)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (error.code === 'PLT_CTR_RUNTIME_NOT_FOUND') {
|
|
55
|
+
return logFatalError(logger, 'Cannot find a matching runtime.')
|
|
56
|
+
} else if (error.message && error.message.includes('Application not found')) {
|
|
57
|
+
return logFatalError(logger, error.message)
|
|
58
|
+
} else {
|
|
59
|
+
return logFatalError(
|
|
60
|
+
logger,
|
|
61
|
+
{ error: ensureLoggableError(error) },
|
|
62
|
+
`Cannot take heap snapshot: ${error.message}`
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
} finally {
|
|
66
|
+
await client.close()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export const help = {
|
|
71
|
+
'heap-snapshot': {
|
|
72
|
+
usage: 'heap-snapshot [id] [application] [options]',
|
|
73
|
+
description: 'Take a heap snapshot of a running application',
|
|
74
|
+
options: [
|
|
75
|
+
{
|
|
76
|
+
name: '--dir, -d',
|
|
77
|
+
description: 'Directory to save the heap snapshot to (default: current working directory)'
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
args: [
|
|
81
|
+
{
|
|
82
|
+
name: 'id',
|
|
83
|
+
description:
|
|
84
|
+
'The process ID or the name of the application (it can be omitted only if there is a single application running)'
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
name: 'application',
|
|
88
|
+
description: 'The application ID to snapshot (if omitted, snapshots all applications)'
|
|
89
|
+
}
|
|
90
|
+
],
|
|
91
|
+
footer:
|
|
92
|
+
'Takes a V8 heap snapshot of a running application and saves it as a .heapsnapshot file.\n' +
|
|
93
|
+
'The resulting file can be loaded in Chrome DevTools (Memory tab) for analysis.\n\n' +
|
|
94
|
+
'Examples:\n' +
|
|
95
|
+
' wattpm heap-snapshot my-app # Take heap snapshot of my-app\n' +
|
|
96
|
+
' wattpm heap-snapshot --dir=/tmp/snapshots my-app # Save to specific directory\n' +
|
|
97
|
+
' wattpm heap-snapshot # Snapshot all applications'
|
|
98
|
+
}
|
|
99
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wattpm",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.42.0",
|
|
4
4
|
"description": "The Node.js Application Server",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -30,9 +30,9 @@
|
|
|
30
30
|
"pino-pretty": "^13.0.0",
|
|
31
31
|
"split2": "^4.2.0",
|
|
32
32
|
"table": "^6.8.2",
|
|
33
|
-
"@platformatic/
|
|
34
|
-
"@platformatic/
|
|
35
|
-
"@platformatic/
|
|
33
|
+
"@platformatic/control": "3.42.0",
|
|
34
|
+
"@platformatic/foundation": "3.42.0",
|
|
35
|
+
"@platformatic/runtime": "3.42.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"cleaner-spec-reporter": "^0.5.0",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"neostandard": "^0.12.0",
|
|
45
45
|
"typescript": "^5.5.4",
|
|
46
46
|
"undici": "^7.0.0",
|
|
47
|
-
"@platformatic/node": "3.
|
|
47
|
+
"@platformatic/node": "3.42.0"
|
|
48
48
|
},
|
|
49
49
|
"engines": {
|
|
50
50
|
"node": ">=22.19.0"
|
package/schema.json
CHANGED