@vtex/api 6.51.3 → 6.53.0-beta.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.
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getClusterResourceAttributes = void 0;
4
+ const constants_1 = require("../../constants");
5
+ const normalizeAttribute = (value) => {
6
+ const normalized = value === null || value === void 0 ? void 0 : value.trim();
7
+ return normalized || undefined;
8
+ };
9
+ const getClusterResourceAttributes = (clusterId, clusterRole) => {
10
+ const attributes = {};
11
+ const normalizedClusterId = normalizeAttribute(clusterId);
12
+ const normalizedClusterRole = normalizeAttribute(clusterRole);
13
+ if (normalizedClusterId) {
14
+ attributes[constants_1.AttributeKeys.VTEX_IO_CLUSTER_ID] = normalizedClusterId;
15
+ }
16
+ if (normalizedClusterRole) {
17
+ attributes[constants_1.AttributeKeys.VTEX_IO_CLUSTER_ROLE] = normalizedClusterRole;
18
+ }
19
+ return attributes;
20
+ };
21
+ exports.getClusterResourceAttributes = getClusterResourceAttributes;
@@ -1,6 +1,7 @@
1
1
  import Koa from 'koa';
2
2
  import { MetricsAccumulator } from '../../metrics/MetricsAccumulator';
3
3
  import { ServiceJSON } from './runtime/typings';
4
+ export declare const onMessage: (service: ServiceJSON) => (message: any) => void;
4
5
  export declare const startWorker: (serviceJSON: ServiceJSON) => Koa<Koa.DefaultState, Koa.DefaultContext>;
5
6
  declare global {
6
7
  namespace NodeJS {
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.startWorker = void 0;
6
+ exports.startWorker = exports.onMessage = void 0;
7
7
  const http_1 = require("http");
8
8
  const koa_1 = __importDefault(require("koa"));
9
9
  const koa_compress_1 = __importDefault(require("koa-compress"));
@@ -14,6 +14,7 @@ const MetricsAccumulator_1 = require("../../metrics/MetricsAccumulator");
14
14
  const loaders_1 = require("../loaders");
15
15
  const console_1 = require("../logger/console");
16
16
  const loggerTypes_1 = require("../logger/loggerTypes");
17
+ const clusterMetricsAggregator_1 = require("../metrics/clusterMetricsAggregator");
17
18
  const requestMetricsMiddleware_1 = require("../metrics/requestMetricsMiddleware");
18
19
  const TracerSingleton_1 = require("../tracing/TracerSingleton");
19
20
  const tracingMiddlewares_1 = require("../tracing/tracingMiddlewares");
@@ -54,7 +55,12 @@ const onMessage = (service) => (message) => {
54
55
  else if ((0, statusTrack_1.isStatusTrack)(message)) {
55
56
  (0, statusTrack_1.trackStatus)();
56
57
  }
57
- else {
58
+ else if ((0, clusterMetricsAggregator_1.isAggMetricsResponse)(message)) {
59
+ (0, clusterMetricsAggregator_1.handleMasterMetricsResponse)(message);
60
+ }
61
+ else if (!(0, clusterMetricsAggregator_1.isPromClientMessage)(message)) {
62
+ // prom-client's own cluster messages are handled by its worker listener;
63
+ // anything else that reaches here is genuinely unexpected.
58
64
  listeners_1.logger.warn({
59
65
  content: message,
60
66
  message: 'Master sent message',
@@ -62,6 +68,7 @@ const onMessage = (service) => (message) => {
62
68
  });
63
69
  }
64
70
  };
71
+ exports.onMessage = onMessage;
65
72
  const createAppHttpHandlers = ({ config: { routes, clients } }, serviceJSON, globalLimiter) => {
66
73
  if (routes && clients) {
67
74
  return Object.keys(routes).reduce((acc, routeId) => {
@@ -153,11 +160,16 @@ const startWorker = (serviceJSON) => {
153
160
  var _a, _b;
154
161
  (0, listeners_1.addProcessListeners)();
155
162
  const tracer = TracerSingleton_1.TracerSingleton.getTracer();
163
+ // In multi-worker mode install prom-client's worker-side cluster responder so
164
+ // the master can collect this worker's registry for the aggregated /metrics.
165
+ if (serviceJSON.workers > 1) {
166
+ (0, clusterMetricsAggregator_1.ensureWorkerAggregatorRegistry)();
167
+ }
156
168
  const app = new koa_1.default();
157
169
  app.proxy = true;
158
170
  app
159
171
  .use(error_1.error)
160
- .use((0, middlewares_1.prometheusLoggerMiddleware)())
172
+ .use((0, middlewares_1.prometheusLoggerMiddleware)(serviceJSON.workers))
161
173
  .use((0, tracingMiddlewares_1.addTracingMiddleware)(tracer))
162
174
  .use((0, requestMetricsMiddleware_1.addRequestMetricsMiddleware)())
163
175
  .use((0, middlewares_1.addMetricsLoggerMiddleware)())
@@ -190,7 +202,7 @@ const startWorker = (serviceJSON) => {
190
202
  const privateHandlersRouter = routerFromPrivateHttpHandlers(httpHandlers.pvt);
191
203
  app.use(privateHandlersRouter.routes());
192
204
  }
193
- process.on('message', onMessage(serviceJSON));
205
+ process.on('message', (0, exports.onMessage)(serviceJSON));
194
206
  return app;
195
207
  };
196
208
  exports.startWorker = startWorker;
@@ -1,4 +1,4 @@
1
1
  import { ServiceContext } from '../typings';
2
2
  export declare function recorderMiddleware(ctx: ServiceContext, next: () => Promise<void>): Promise<void>;
3
3
  export declare const addMetricsLoggerMiddleware: () => (ctx: ServiceContext, next: () => Promise<void>) => Promise<void>;
4
- export declare const prometheusLoggerMiddleware: () => (ctx: ServiceContext, next: () => Promise<void>) => Promise<void>;
4
+ export declare const prometheusLoggerMiddleware: (workers?: number) => (ctx: ServiceContext, next: () => Promise<void>) => Promise<void>;
@@ -4,6 +4,7 @@ exports.prometheusLoggerMiddleware = exports.addMetricsLoggerMiddleware = export
4
4
  const prom_client_1 = require("prom-client");
5
5
  const constants_1 = require("../../../../constants");
6
6
  const metricsLogger_1 = require("../../../logger/metricsLogger");
7
+ const clusterMetricsAggregator_1 = require("../../../metrics/clusterMetricsAggregator");
7
8
  const EventLoopLagMeasurer_1 = require("../../../tracing/metrics/measurers/EventLoopLagMeasurer");
8
9
  const recorder_1 = require("../utils/recorder");
9
10
  async function recorderMiddleware(ctx, next) {
@@ -22,10 +23,14 @@ const addMetricsLoggerMiddleware = () => {
22
23
  };
23
24
  };
24
25
  exports.addMetricsLoggerMiddleware = addMetricsLoggerMiddleware;
25
- const prometheusLoggerMiddleware = () => {
26
+ const prometheusLoggerMiddleware = (workers = 1) => {
26
27
  (0, prom_client_1.collectDefaultMetrics)();
27
28
  const eventLoopLagMeasurer = new EventLoopLagMeasurer_1.EventLoopLagMeasurer();
28
29
  eventLoopLagMeasurer.start();
30
+ // In multi-worker mode each worker holds only its own registry, so /metrics
31
+ // must serve the cluster-wide aggregate requested from the master over IPC.
32
+ // In single-worker mode (LINKED / workers:1) the local registry is complete.
33
+ const isMultiWorker = workers > 1;
29
34
  return async (ctx, next) => {
30
35
  if (ctx.request.path !== '/metrics') {
31
36
  return next();
@@ -36,7 +41,7 @@ const prometheusLoggerMiddleware = () => {
36
41
  }
37
42
  await eventLoopLagMeasurer.updateInstrumentsAndReset();
38
43
  ctx.set('Content-Type', prom_client_1.register.contentType);
39
- ctx.body = await prom_client_1.register.metrics();
44
+ ctx.body = isMultiWorker ? await (0, clusterMetricsAggregator_1.requestAggregatedMetrics)() : await prom_client_1.register.metrics();
40
45
  ctx.status = 200;
41
46
  };
42
47
  };
@@ -14,7 +14,10 @@ const isStatusTrackBroadcast = (message) => message === BROADCAST_STATUS_TRACK;
14
14
  exports.isStatusTrackBroadcast = isStatusTrackBroadcast;
15
15
  const statusTrackHandler = async (ctx) => {
16
16
  var _a, _b, _c;
17
- (_b = (_a = ctx.tracing) === null || _a === void 0 ? void 0 : _a.currentSpan) === null || _b === void 0 ? void 0 : _b.setOperationName('builtin:status-track');
17
+ // Parity with the other builtin handlers: name the request so its samples don't
18
+ // land in the catch-all `handler="undefined"` bucket.
19
+ ctx.requestHandlerName = 'builtin:status-track';
20
+ (_b = (_a = ctx.tracing) === null || _a === void 0 ? void 0 : _a.currentSpan) === null || _b === void 0 ? void 0 : _b.setOperationName(ctx.requestHandlerName);
18
21
  if (!constants_1.LINKED) {
19
22
  (_c = process.send) === null || _c === void 0 ? void 0 : _c.call(process, BROADCAST_STATUS_TRACK);
20
23
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/api",
3
- "version": "6.51.3",
3
+ "version": "6.53.0-beta.0",
4
4
  "description": "VTEX I/O API client",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -47,9 +47,14 @@
47
47
  },
48
48
  "license": "MIT",
49
49
  "dependencies": {
50
+ "@opentelemetry/api": "^1.9.0",
51
+ "@opentelemetry/host-metrics": "0.35.5",
52
+ "@opentelemetry/instrumentation": "0.57.2",
53
+ "@opentelemetry/instrumentation-koa": "0.47.1",
50
54
  "@types/koa": "^2.11.0",
51
55
  "@types/koa-compose": "^3.2.3",
52
- "@vtex/diagnostics-nodejs": "0.1.0-beta.10",
56
+ "@vtex/diagnostics-nodejs": "0.1.8-io",
57
+ "@vtex/diagnostics-semconv": "5.5.2",
53
58
  "@vtex/node-error-report": "^0.0.3",
54
59
  "@wry/equality": "^0.1.9",
55
60
  "agentkeepalive": "^4.0.2",