wattpm 3.7.1 → 3.9.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.
@@ -5,7 +5,15 @@ import { writeFile } from 'node:fs/promises'
5
5
 
6
6
  export async function pprofStartCommand (logger, args) {
7
7
  try {
8
- const { positionals } = parseArgs(args, {}, false)
8
+ const { positionals, values } = parseArgs(args, {
9
+ type: { type: 'string', short: 't', default: 'cpu' }
10
+ }, false)
11
+
12
+ // Validate profile type
13
+ const type = values.type
14
+ if (type !== 'cpu' && type !== 'heap') {
15
+ return logFatalError(logger, `Invalid profile type: ${type}. Must be 'cpu' or 'heap'.`)
16
+ }
9
17
 
10
18
  const client = new RuntimeApiClient()
11
19
  const [runtime, remainingPositionals] = await getMatchingRuntime(client, positionals)
@@ -14,6 +22,8 @@ export async function pprofStartCommand (logger, args) {
14
22
  // Get application ID from positional arguments or use all applications
15
23
  const applicationId = remainingPositionals[0]
16
24
 
25
+ const options = { intervalMicros: 1000, type }
26
+
17
27
  if (applicationId) {
18
28
  // Start profiling for specific application
19
29
  const application = runtimeApplications.find(s => s.id === applicationId)
@@ -22,14 +32,14 @@ export async function pprofStartCommand (logger, args) {
22
32
  return logFatalError(logger, `Application not found: ${applicationId}`)
23
33
  }
24
34
 
25
- await client.startApplicationProfiling(runtime.pid, applicationId, { intervalMicros: 1000 })
26
- logger.info(`Profiling started for application ${bold(applicationId)}`)
35
+ await client.startApplicationProfiling(runtime.pid, applicationId, options)
36
+ logger.info(`${type.toUpperCase()} profiling started for application ${bold(applicationId)}`)
27
37
  } else {
28
38
  // Start profiling for all applications
29
39
  for (const application of runtimeApplications) {
30
40
  try {
31
- await client.startApplicationProfiling(runtime.pid, application.id, { intervalMicros: 1000 })
32
- logger.info(`Profiling started for application ${bold(application.id)}`)
41
+ await client.startApplicationProfiling(runtime.pid, application.id, options)
42
+ logger.info(`${type.toUpperCase()} profiling started for application ${bold(application.id)}`)
33
43
  } catch (error) {
34
44
  logger.warn(`Failed to start profiling for application ${application.id}: ${error.message}`)
35
45
  }
@@ -50,7 +60,15 @@ export async function pprofStartCommand (logger, args) {
50
60
 
51
61
  export async function pprofStopCommand (logger, args) {
52
62
  try {
53
- const { positionals } = parseArgs(args, {}, false)
63
+ const { positionals, values } = parseArgs(args, {
64
+ type: { type: 'string', short: 't', default: 'cpu' }
65
+ }, false)
66
+
67
+ // Validate profile type
68
+ const type = values.type
69
+ if (type !== 'cpu' && type !== 'heap') {
70
+ return logFatalError(logger, `Invalid profile type: ${type}. Must be 'cpu' or 'heap'.`)
71
+ }
54
72
 
55
73
  const client = new RuntimeApiClient()
56
74
  const [runtime, remainingPositionals] = await getMatchingRuntime(client, positionals)
@@ -60,6 +78,8 @@ export async function pprofStopCommand (logger, args) {
60
78
  const applicationId = remainingPositionals[0]
61
79
  const timestamp = new Date().toISOString().replace(/:/g, '-').replace(/\./g, '-')
62
80
 
81
+ const options = { type }
82
+
63
83
  if (applicationId) {
64
84
  // Stop profiling for specific application
65
85
  const application = runtimeApplications.find(s => s.id === applicationId)
@@ -68,18 +88,18 @@ export async function pprofStopCommand (logger, args) {
68
88
  return logFatalError(logger, `Application not found: ${applicationId}`)
69
89
  }
70
90
 
71
- const profileData = await client.stopApplicationProfiling(runtime.pid, applicationId)
72
- const filename = `pprof-${applicationId}-${timestamp}.pb`
91
+ const profileData = await client.stopApplicationProfiling(runtime.pid, applicationId, options)
92
+ const filename = `pprof-${type}-${applicationId}-${timestamp}.pb`
73
93
  await writeFile(filename, Buffer.from(profileData))
74
- logger.info(`Profiling stopped for application ${bold(applicationId)}, profile saved to ${bold(filename)}`)
94
+ logger.info(`${type.toUpperCase()} profiling stopped for application ${bold(applicationId)}, profile saved to ${bold(filename)}`)
75
95
  } else {
76
96
  // Stop profiling for all applications
77
97
  for (const application of runtimeApplications) {
78
98
  try {
79
- const profileData = await client.stopApplicationProfiling(runtime.pid, application.id)
80
- const filename = `pprof-${application.id}-${timestamp}.pb`
99
+ const profileData = await client.stopApplicationProfiling(runtime.pid, application.id, options)
100
+ const filename = `pprof-${type}-${application.id}-${timestamp}.pb`
81
101
  await writeFile(filename, Buffer.from(profileData))
82
- logger.info(`Profiling stopped for application ${bold(application.id)}, profile saved to ${bold(filename)}`)
102
+ logger.info(`${type.toUpperCase()} profiling stopped for application ${bold(application.id)}, profile saved to ${bold(filename)}`)
83
103
  } catch (error) {
84
104
  logger.warn(`Failed to stop profiling for application ${application.id}: ${error.message}`)
85
105
  }
@@ -113,9 +133,14 @@ export async function pprofCommand (logger, args) {
113
133
 
114
134
  export const help = {
115
135
  pprof: {
116
- usage: 'pprof <start|stop> [id] [application]',
117
- description: 'Profile CPU usage of running application',
118
- options: [],
136
+ usage: 'pprof <start|stop> [id] [application] [options]',
137
+ description: 'Profile CPU or heap usage of running application',
138
+ options: [
139
+ {
140
+ name: '--type, -t',
141
+ description: 'Profile type: "cpu" for CPU wall time (default) or "heap" for heap memory'
142
+ }
143
+ ],
119
144
  args: [
120
145
  {
121
146
  name: 'command',
@@ -126,17 +151,17 @@ export const help = {
126
151
  description:
127
152
  'The process ID or the name of the application (it can be omitted only if there is a single application running)'
128
153
  },
129
- {
130
- name: 'id',
131
- description:
132
- 'The process ID or the name of the application (it can be omitted only if there is a single application running)'
133
- },
134
154
  {
135
155
  name: 'application',
136
156
  description: 'The application ID to profile (if omitted, profiles all applications)'
137
157
  }
138
158
  ],
139
159
  footer:
140
- 'Use "pprof start [application]" to start profiling and "pprof stop [application]" to stop and save profile data.'
160
+ 'Use "pprof start [application]" to start profiling and "pprof stop [application]" to stop and save profile data.\n' +
161
+ 'Examples:\n' +
162
+ ' wattpm pprof start --type=cpu my-app # Start CPU profiling\n' +
163
+ ' wattpm pprof start --type=heap my-app # Start heap profiling\n' +
164
+ ' wattpm pprof stop --type=cpu my-app # Stop CPU profiling\n' +
165
+ ' wattpm pprof stop --type=heap my-app # Stop heap profiling'
141
166
  }
142
167
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wattpm",
3
- "version": "3.7.1",
3
+ "version": "3.9.0",
4
4
  "description": "The Node.js Application Server",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -29,9 +29,9 @@
29
29
  "pino-pretty": "^13.0.0",
30
30
  "split2": "^4.2.0",
31
31
  "table": "^6.8.2",
32
- "@platformatic/foundation": "3.7.1",
33
- "@platformatic/runtime": "3.7.1",
34
- "@platformatic/control": "3.7.1"
32
+ "@platformatic/foundation": "3.9.0",
33
+ "@platformatic/runtime": "3.9.0",
34
+ "@platformatic/control": "3.9.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "cleaner-spec-reporter": "^0.5.0",
@@ -42,7 +42,7 @@
42
42
  "neostandard": "^0.12.0",
43
43
  "typescript": "^5.5.4",
44
44
  "undici": "^7.0.0",
45
- "@platformatic/node": "3.7.1"
45
+ "@platformatic/node": "3.9.0"
46
46
  },
47
47
  "engines": {
48
48
  "node": ">=22.19.0"
package/schema.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$id": "https://schemas.platformatic.dev/wattpm/3.7.1.json",
2
+ "$id": "https://schemas.platformatic.dev/wattpm/3.9.0.json",
3
3
  "$schema": "http://json-schema.org/draft-07/schema#",
4
4
  "title": "Platformatic Runtime Config",
5
5
  "type": "object",
@@ -923,8 +923,7 @@
923
923
  {
924
924
  "type": "string"
925
925
  }
926
- ],
927
- "default": 1
926
+ ]
928
927
  },
929
928
  "workersRestartDelay": {
930
929
  "anyOf": [
@@ -1828,6 +1827,72 @@
1828
1827
  ],
1829
1828
  "additionalProperties": false
1830
1829
  },
1830
+ "verticalScaler": {
1831
+ "type": "object",
1832
+ "properties": {
1833
+ "enabled": {
1834
+ "type": "boolean",
1835
+ "default": true
1836
+ },
1837
+ "maxTotalWorkers": {
1838
+ "type": "number",
1839
+ "minimum": 1
1840
+ },
1841
+ "minWorkers": {
1842
+ "type": "number",
1843
+ "minimum": 1
1844
+ },
1845
+ "maxWorkers": {
1846
+ "type": "number",
1847
+ "minimum": 1
1848
+ },
1849
+ "scaleUpELU": {
1850
+ "type": "number",
1851
+ "minimum": 0,
1852
+ "maximum": 1
1853
+ },
1854
+ "scaleDownELU": {
1855
+ "type": "number",
1856
+ "minimum": 0,
1857
+ "maximum": 1
1858
+ },
1859
+ "minELUDiff": {
1860
+ "type": "number",
1861
+ "minimum": 0,
1862
+ "maximum": 1
1863
+ },
1864
+ "timeWindowSec": {
1865
+ "type": "number",
1866
+ "minimum": 0
1867
+ },
1868
+ "cooldownSec": {
1869
+ "type": "number",
1870
+ "minimum": 0
1871
+ },
1872
+ "scaleIntervalSec": {
1873
+ "type": "number",
1874
+ "minimum": 0
1875
+ },
1876
+ "applications": {
1877
+ "type": "object",
1878
+ "additionalProperties": {
1879
+ "type": "object",
1880
+ "properties": {
1881
+ "minWorkers": {
1882
+ "type": "number",
1883
+ "minimum": 1
1884
+ },
1885
+ "maxWorkers": {
1886
+ "type": "number",
1887
+ "minimum": 1
1888
+ }
1889
+ },
1890
+ "additionalProperties": false
1891
+ }
1892
+ }
1893
+ },
1894
+ "additionalProperties": false
1895
+ },
1831
1896
  "inspectorOptions": {
1832
1897
  "type": "object",
1833
1898
  "properties": {