@platformatic/watt-extra 0.1.8 → 1.0.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.
@@ -41,7 +41,7 @@ jobs:
41
41
  version: 10
42
42
 
43
43
  - name: Use Node.js ${{ matrix.node-version }}
44
- uses: actions/setup-node@v4
44
+ uses: actions/setup-node@v5
45
45
  with:
46
46
  node-version: ${{ matrix.node-version }}
47
47
  # https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#use-private-packages
package/lib/watt.js CHANGED
@@ -201,6 +201,7 @@ class Watt {
201
201
  applicationId: this.#instanceConfig?.applicationId,
202
202
  instanceId: this.#instanceId,
203
203
  },
204
+ applicationLabel: this.#instanceConfig?.applicationMetricsLabel ?? 'serviceId'
204
205
  }
205
206
 
206
207
  if (this.#env.PLT_DISABLE_FLAMEGRAPHS !== true) {
@@ -251,11 +252,11 @@ class Watt {
251
252
  }
252
253
 
253
254
  #getTrafficInterceptorConfig () {
254
- if (!this.#instanceConfig?.iccServices?.trafficante?.url) {
255
+ if (!this.#instanceConfig?.iccServices?.trafficInspector?.url) {
255
256
  return
256
257
  }
257
- const { origin: trafficanteOrigin, pathname: trafficantePath } = new URL(
258
- this.#instanceConfig.iccServices.trafficante.url
258
+ const { origin: trafficInspectorOrigin, pathname: trafficInspectorPath } = new URL(
259
+ this.#instanceConfig.iccServices.trafficInspector.url
259
260
  )
260
261
  return {
261
262
  module: require.resolve(
@@ -271,9 +272,9 @@ class Watt {
271
272
  },
272
273
  maxResponseSize: 5 * 1024 * 1024, // 5MB
273
274
  trafficInspectorOptions: {
274
- url: trafficanteOrigin,
275
- pathSendBody: join(trafficantePath, '/requests'),
276
- pathSendMeta: join(trafficantePath, '/requests/hash'),
275
+ url: trafficInspectorOrigin,
276
+ pathSendBody: join(trafficInspectorPath, '/requests'),
277
+ pathSendMeta: join(trafficInspectorPath, '/requests/hash'),
277
278
  },
278
279
  matchingDomains: [this.#env.PLT_APP_INTERNAL_SUB_DOMAIN],
279
280
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/watt-extra",
3
- "version": "0.1.8",
3
+ "version": "1.0.0",
4
4
  "description": "The Platformatic runtime manager",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -13,25 +13,25 @@
13
13
  },
14
14
  "devDependencies": {
15
15
  "@fastify/websocket": "^11.1.0",
16
- "@platformatic/composer": "^3.0.5",
17
- "@platformatic/next": "^3.0.5",
18
- "@platformatic/node": "^3.0.5",
19
- "@platformatic/service": "^3.0.5",
16
+ "@platformatic/composer": "^3.3.0",
17
+ "@platformatic/next": "^3.3.0",
18
+ "@platformatic/node": "^3.3.0",
19
+ "@platformatic/service": "^3.3.0",
20
20
  "borp": "^0.20.0",
21
21
  "eslint": "9",
22
22
  "fastify": "^5.4.0",
23
23
  "fastify-plugin": "^5.0.1",
24
24
  "neostandard": "^0.12.0",
25
25
  "next": "^15.3.4",
26
- "platformatic": "^3.0.5",
26
+ "platformatic": "^3.3.0",
27
27
  "pprof-format": "^2.1.0",
28
28
  "why-is-node-running": "^2.3.0"
29
29
  },
30
30
  "dependencies": {
31
31
  "@datadog/pprof": "^5.9.0",
32
32
  "@fastify/error": "^4.2.0",
33
- "@platformatic/runtime": "^3.0.5",
34
- "@platformatic/wattpm-pprof-capture": "^3.0.5",
33
+ "@platformatic/runtime": "^3.3.0",
34
+ "@platformatic/wattpm-pprof-capture": "^3.3.0",
35
35
  "avvio": "^9.1.0",
36
36
  "chalk": "^4.1.2",
37
37
  "commist": "^3.2.0",
@@ -60,7 +60,7 @@ async function compliancy (app, _opts) {
60
60
  const { compliant, report } = JSON.parse(res.body)
61
61
 
62
62
  if (!compliant) {
63
- app.log.error(report, 'Compliancy check failed')
63
+ app.log.warn(report, 'Compliancy check failed')
64
64
  }
65
65
  }
66
66
  }
@@ -128,7 +128,7 @@ test('should spawn an app with auto caching', async (t) => {
128
128
  assert.strictEqual(headers['x-foo-bar'], undefined)
129
129
  assert.strictEqual(headers['x-custom-cache-tags'], undefined)
130
130
 
131
- // Wait for interceptor to send data to the Trafficante
131
+ // Wait for interceptor to send data to the Traffic Inspector
132
132
  await sleep(1000)
133
133
 
134
134
  assert.strictEqual(savedRequestHashes.length, 1)
package/test/helper.js CHANGED
@@ -34,6 +34,7 @@ async function startICC (t, opts = {}) {
34
34
  let {
35
35
  applicationId,
36
36
  applicationName,
37
+ applicationMetricsLabel,
37
38
  iccServices,
38
39
  iccConfig = {},
39
40
  enableOpenTelemetry = false,
@@ -46,8 +47,8 @@ async function startICC (t, opts = {}) {
46
47
  riskEngine: {
47
48
  url: 'http://127.0.0.1:3000/risk-service'
48
49
  },
49
- trafficante: {
50
- url: 'http://127.0.0.1:3000/trafficante'
50
+ trafficInspector: {
51
+ url: 'http://127.0.0.1:3000/traffic-inspector'
51
52
  },
52
53
  compliance: {
53
54
  url: 'http://127.0.0.1:3000/compliance'
@@ -108,6 +109,7 @@ async function startICC (t, opts = {}) {
108
109
  return controlPlaneResponse || {
109
110
  applicationId,
110
111
  applicationName,
112
+ applicationMetricsLabel,
111
113
  iccServices,
112
114
  config: iccConfig,
113
115
  enableOpenTelemetry,
@@ -143,7 +145,7 @@ async function startICC (t, opts = {}) {
143
145
  })
144
146
  }, { prefix: '/compliance' })
145
147
 
146
- // Trafficante
148
+ // Traffic Inspector
147
149
  await icc.register(async (icc) => {
148
150
  icc.post('/requests/hash', async (req) => {
149
151
  const { taxonomyId, applicationId } = JSON.parse(req.headers['x-labels'])
@@ -159,7 +161,7 @@ async function startICC (t, opts = {}) {
159
161
 
160
162
  opts.saveRequest?.({ taxonomyId, applicationId, request, response })
161
163
  })
162
- }, { prefix: '/trafficante' })
164
+ }, { prefix: '/traffic-inspector' })
163
165
 
164
166
  // Risk Service
165
167
  await icc.register(async (icc) => {
package/test/init.test.js CHANGED
@@ -63,7 +63,7 @@ test('init plugin with optional PLT_APP_NAME - uses ICC response', async (t) =>
63
63
  applicationName, // ICC returns the application name
64
64
  iccServices: {
65
65
  riskEngine: { url: 'http://127.0.0.1:3000/risk-service' },
66
- trafficante: { url: 'http://127.0.0.1:3000/trafficante' },
66
+ trafficInspector: { url: 'http://127.0.0.1:3000/traffic-inspector' },
67
67
  compliance: { url: 'http://127.0.0.1:3000/compliance' },
68
68
  cron: { url: 'http://127.0.0.1:3000/cron' },
69
69
  scaler: { url: 'http://127.0.0.1:3000/scaler' }
@@ -166,7 +166,7 @@ test('init plugin sends correct request structure when PLT_APP_NAME provided', a
166
166
  applicationName,
167
167
  iccServices: {
168
168
  riskEngine: { url: 'http://127.0.0.1:3000/risk-service' },
169
- trafficante: { url: 'http://127.0.0.1:3000/trafficante' },
169
+ trafficInspector: { url: 'http://127.0.0.1:3000/traffic-inspector' },
170
170
  compliance: { url: 'http://127.0.0.1:3000/compliance' },
171
171
  cron: { url: 'http://127.0.0.1:3000/cron' },
172
172
  scaler: { url: 'http://127.0.0.1:3000/scaler' }
@@ -212,7 +212,7 @@ test('init plugin sends request without applicationName when not provided', asyn
212
212
  applicationName, // ICC provides the name
213
213
  iccServices: {
214
214
  riskEngine: { url: 'http://127.0.0.1:3000/risk-service' },
215
- trafficante: { url: 'http://127.0.0.1:3000/trafficante' },
215
+ trafficInspector: { url: 'http://127.0.0.1:3000/traffic-inspector' },
216
216
  compliance: { url: 'http://127.0.0.1:3000/compliance' },
217
217
  cron: { url: 'http://127.0.0.1:3000/cron' },
218
218
  scaler: { url: 'http://127.0.0.1:3000/scaler' }
@@ -0,0 +1,107 @@
1
+ import assert from 'node:assert'
2
+ import { test } from 'node:test'
3
+ import { randomUUID } from 'node:crypto'
4
+ import { request } from 'undici'
5
+ import { join, dirname } from 'node:path'
6
+ import { fileURLToPath } from 'node:url'
7
+ import { setUpEnvironment, startICC } from './helper.js'
8
+ import { start } from '../index.js'
9
+
10
+ const __filename = fileURLToPath(import.meta.url)
11
+ const __dirname = dirname(__filename)
12
+
13
+ test('should generate metrics with a correct labels', async (t) => {
14
+ const applicationName = 'test-app'
15
+ const applicationId = randomUUID()
16
+ const applicationPath = join(__dirname, 'fixtures', 'service-1')
17
+
18
+ const icc = await startICC(t, {
19
+ applicationId,
20
+ applicationName
21
+ })
22
+
23
+ process.env.PLT_TEST_APP_1_URL = 'http://test-app-1:3042'
24
+ t.after(() => {
25
+ delete process.env.PLT_TEST_APP_1_URL
26
+ })
27
+
28
+ setUpEnvironment({
29
+ PLT_APP_NAME: applicationName,
30
+ PLT_APP_DIR: applicationPath,
31
+ PLT_ICC_URL: 'http://127.0.0.1:3000',
32
+ })
33
+
34
+ const app = await start()
35
+
36
+ t.after(async () => {
37
+ await app.close()
38
+ await icc.close()
39
+ })
40
+
41
+ const { statusCode, body } = await request('http://127.0.0.1:9090/metrics', {
42
+ headers: {
43
+ accept: 'application/json',
44
+ }
45
+ })
46
+ assert.strictEqual(statusCode, 200)
47
+
48
+ const metrics = await body.json()
49
+
50
+ {
51
+ const eluMetrics = metrics.find((metric) => metric.name === 'nodejs_eventloop_utilization')
52
+ assert.ok(eluMetrics)
53
+
54
+ const labels = eluMetrics.values[0].labels
55
+ assert.strictEqual(labels.applicationId, applicationId)
56
+ assert.strictEqual(labels.serviceId, 'main')
57
+ }
58
+ })
59
+
60
+ test('should generate metrics with a custom metrics label', async (t) => {
61
+ const applicationName = 'test-app'
62
+ const applicationId = randomUUID()
63
+ const applicationPath = join(__dirname, 'fixtures', 'service-1')
64
+ const applicationMetricsLabel = 'customLabel'
65
+
66
+ const icc = await startICC(t, {
67
+ applicationId,
68
+ applicationName,
69
+ applicationMetricsLabel
70
+ })
71
+
72
+ process.env.PLT_TEST_APP_1_URL = 'http://test-app-1:3042'
73
+ t.after(() => {
74
+ delete process.env.PLT_TEST_APP_1_URL
75
+ })
76
+
77
+ setUpEnvironment({
78
+ PLT_APP_NAME: applicationName,
79
+ PLT_APP_DIR: applicationPath,
80
+ PLT_ICC_URL: 'http://127.0.0.1:3000',
81
+ })
82
+
83
+ const app = await start()
84
+
85
+ t.after(async () => {
86
+ await app.close()
87
+ await icc.close()
88
+ })
89
+
90
+ const { statusCode, body } = await request('http://127.0.0.1:9090/metrics', {
91
+ headers: {
92
+ accept: 'application/json',
93
+ }
94
+ })
95
+ assert.strictEqual(statusCode, 200)
96
+
97
+ const metrics = await body.json()
98
+
99
+ {
100
+ const eluMetrics = metrics.find((metric) => metric.name === 'nodejs_eventloop_utilization')
101
+ assert.ok(eluMetrics)
102
+
103
+ const labels = eluMetrics.values[0].labels
104
+ assert.strictEqual(labels.applicationId, applicationId)
105
+ assert.strictEqual(labels[applicationMetricsLabel], 'main')
106
+ }
107
+ })
@@ -80,6 +80,7 @@ test('should spawn a service app settings labels for metrics', async (t) => {
80
80
  instanceId: app.instanceId,
81
81
  applicationId,
82
82
  },
83
+ applicationLabel: 'serviceId'
83
84
  }
84
85
  assert.deepStrictEqual(metrics, expectedMetrics)
85
86
  })