@vtex/api 7.3.0-beta.5 → 7.3.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/CHANGELOG.md CHANGED
@@ -7,7 +7,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- ## [7.2.8-beta.0] - 2025-12-05
10
+ ## [7.2.9-beta.1] - 2025-12-12
11
+ ### Changed
12
+ - Increase maximum attributes limit for diagnostics metrics
13
+
14
+ ## [7.2.9-beta.0] - 2025-12-11
15
+ ### Fix
16
+ - Add account attribute to diagnostics metrics for improved observability
17
+
18
+ ## [7.2.8-beta.4] - 2025-12-08
11
19
  ### Changed
12
20
  - New deploy pipeline. No functional changes in the code
13
21
 
@@ -102,7 +102,7 @@ class HttpClient {
102
102
  ...config,
103
103
  url,
104
104
  });
105
- const { baseURL, authToken, authType, memoryCache, diskCache, memoizable = true, asyncSetCache, locale, name, metrics, product, serverTiming, recorder, userAgent, timeout = DEFAULT_TIMEOUT_MS, segmentToken, sessionToken, retries, concurrency, headers: defaultHeaders, host, params, operationId, tenant, binding, verbose, cancellation, exponentialTimeoutCoefficient, initialBackoffDelay, exponentialBackoffCoefficient, httpsAgent, tracer, logger, cacheableType = cache_1.CacheType.Memory, } = opts;
105
+ const { account, baseURL, authToken, authType, memoryCache, diskCache, memoizable = true, asyncSetCache, locale, name, metrics, product, serverTiming, recorder, userAgent, timeout = DEFAULT_TIMEOUT_MS, segmentToken, sessionToken, retries, concurrency, headers: defaultHeaders, host, params, operationId, tenant, binding, verbose, cancellation, exponentialTimeoutCoefficient, initialBackoffDelay, exponentialBackoffCoefficient, httpsAgent, tracer, logger, cacheableType = cache_1.CacheType.Memory, } = opts;
106
106
  this.name = name || baseURL || 'unknown';
107
107
  this.logger = logger;
108
108
  this.cacheableType = cacheableType;
@@ -112,6 +112,7 @@ class HttpClient {
112
112
  ...defaultHeaders,
113
113
  'Accept-Encoding': 'gzip',
114
114
  'User-Agent': userAgent,
115
+ ...account ? { [constants_1.HeaderKeys.ACCOUNT]: account } : null,
115
116
  ...host ? { [constants_1.HeaderKeys.FORWARDED_HOST]: host } : null,
116
117
  ...tenant ? { [constants_1.HeaderKeys.TENANT]: (0, tenant_1.formatTenantHeaderValue)(tenant) } : null,
117
118
  ...binding ? { [constants_1.HeaderKeys.BINDING]: (0, binding_1.formatBindingHeaderValue)(binding) } : null,
@@ -1,11 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.metricsMiddleware = void 0;
4
+ const constants_1 = require("../../constants");
4
5
  const RequestCancelledError_1 = require("../../errors/RequestCancelledError");
5
6
  const requestStats_1 = require("../../service/worker/runtime/http/middlewares/requestStats");
6
7
  const utils_1 = require("../../utils");
7
8
  const retry_1 = require("../../utils/retry");
8
9
  const status_1 = require("../../utils/status");
10
+ const DEFAULT_ACCOUNT = 'unknown';
9
11
  const metricsMiddleware = ({ metrics, serverTiming, name }) => {
10
12
  const serverTimingStart = process.hrtime();
11
13
  const serverTimingLabel = (0, utils_1.shrinkTimings)((0, utils_1.formatTimingName)({
@@ -14,7 +16,7 @@ const metricsMiddleware = ({ metrics, serverTiming, name }) => {
14
16
  target: name || 'unknown',
15
17
  }));
16
18
  return async (ctx, next) => {
17
- var _a;
19
+ var _a, _b;
18
20
  const start = process.hrtime();
19
21
  let status = 'unknown';
20
22
  let errorCode;
@@ -90,7 +92,10 @@ const metricsMiddleware = ({ metrics, serverTiming, name }) => {
90
92
  if (global.diagnosticsMetrics) {
91
93
  const elapsed = process.hrtime(start);
92
94
  const rawStatusCode = ((_a = ctx.response) === null || _a === void 0 ? void 0 : _a.status) || errorStatus;
95
+ // Extract account from request headers, fallback to default
96
+ const account = ((_b = ctx.config.headers) === null || _b === void 0 ? void 0 : _b[constants_1.HeaderKeys.ACCOUNT]) || DEFAULT_ACCOUNT;
93
97
  const baseAttributes = {
98
+ [constants_1.AttributeKeys.VTEX_ACCOUNT_NAME]: account,
94
99
  component: 'http-client',
95
100
  client_metric: ctx.config.metric,
96
101
  status_code: rawStatusCode,
@@ -7,7 +7,7 @@ const constants_1 = require("../constants");
7
7
  * Maximum number of attributes allowed per metric to control cardinality.
8
8
  * This limit applies to external usage (VTEX IO Apps) to prevent unbounded metric dimensions.
9
9
  */
10
- const MAX_ATTRIBUTES = 5;
10
+ const MAX_ATTRIBUTES = 7;
11
11
  /**
12
12
  * Converts an hrtime tuple [seconds, nanoseconds] to milliseconds.
13
13
  */
@@ -1,8 +1,9 @@
1
1
  import { Types } from '@vtex/diagnostics-nodejs';
2
- export declare const enum RequestsMetricLabels {
3
- STATUS_CODE = "status_code",
4
- REQUEST_HANDLER = "handler"
5
- }
2
+ export declare const RequestsMetricLabels: {
3
+ readonly STATUS_CODE: "status_code";
4
+ readonly REQUEST_HANDLER: "handler";
5
+ readonly ACCOUNT_NAME: "vtex.account.name";
6
+ };
6
7
  export interface OtelRequestInstruments {
7
8
  concurrentRequests: Types.Gauge;
8
9
  requestTimings: Types.Histogram;
@@ -1,7 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getOtelInstruments = void 0;
3
+ exports.getOtelInstruments = exports.RequestsMetricLabels = void 0;
4
4
  const client_1 = require("./client");
5
+ const constants_1 = require("../../constants");
6
+ exports.RequestsMetricLabels = {
7
+ STATUS_CODE: 'status_code',
8
+ REQUEST_HANDLER: 'handler',
9
+ ACCOUNT_NAME: constants_1.AttributeKeys.VTEX_ACCOUNT_NAME,
10
+ };
5
11
  const createOtelConcurrentRequestsInstrument = async () => {
6
12
  const metricsClient = await (0, client_1.getMetricClient)();
7
13
  return metricsClient.createGauge('io_http_requests_current', {
@@ -21,6 +21,7 @@ const addOtelRequestMetricsMiddleware = () => {
21
21
  }
22
22
  };
23
23
  return async function addOtelRequestMetrics(ctx, next) {
24
+ var _a, _b;
24
25
  instruments = instruments ? instruments : await tryGetInstruments(ctx);
25
26
  if (!instruments) {
26
27
  await next();
@@ -30,7 +31,7 @@ const addOtelRequestMetricsMiddleware = () => {
30
31
  instruments.concurrentRequests.add(1);
31
32
  ctx.req.once('aborted', () => {
32
33
  if (instruments) {
33
- instruments.abortedRequests.add(1, { ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName });
34
+ instruments.abortedRequests.add(1, { [metrics_1.RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName });
34
35
  }
35
36
  });
36
37
  let responseClosed = false;
@@ -42,21 +43,25 @@ const addOtelRequestMetricsMiddleware = () => {
42
43
  const responseLength = ctx.response.length;
43
44
  if (responseLength && instruments) {
44
45
  instruments.responseSizes.record(responseLength, {
45
- ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName,
46
- ["status_code" /* RequestsMetricLabels.STATUS_CODE */]: ctx.response.status,
46
+ [metrics_1.RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName,
47
+ [metrics_1.RequestsMetricLabels.STATUS_CODE]: ctx.response.status,
48
+ [metrics_1.RequestsMetricLabels.ACCOUNT_NAME]: ((_a = ctx.vtex) === null || _a === void 0 ? void 0 : _a.account) || 'unknown',
47
49
  });
48
50
  }
49
51
  if (instruments) {
50
52
  instruments.totalRequests.add(1, {
51
- ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName,
52
- ["status_code" /* RequestsMetricLabels.STATUS_CODE */]: ctx.response.status,
53
+ [metrics_1.RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName,
54
+ [metrics_1.RequestsMetricLabels.STATUS_CODE]: ctx.response.status,
55
+ [metrics_1.RequestsMetricLabels.ACCOUNT_NAME]: ((_b = ctx.vtex) === null || _b === void 0 ? void 0 : _b.account) || 'unknown',
53
56
  });
54
57
  }
55
58
  const onResFinished = () => {
59
+ var _a;
56
60
  if (instruments) {
57
61
  instruments.requestTimings.record((0, utils_1.hrToMillisFloat)(process.hrtime(start)), {
58
- ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName,
59
- ["status_code" /* RequestsMetricLabels.STATUS_CODE */]: ctx.response.status,
62
+ [metrics_1.RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName,
63
+ [metrics_1.RequestsMetricLabels.STATUS_CODE]: ctx.response.status,
64
+ [metrics_1.RequestsMetricLabels.ACCOUNT_NAME]: ((_a = ctx.vtex) === null || _a === void 0 ? void 0 : _a.account) || 'unknown',
60
65
  });
61
66
  instruments.concurrentRequests.subtract(1);
62
67
  }
@@ -45,7 +45,7 @@ class TelemetryClientSingleton {
45
45
  'vendor': constants_1.APP.VENDOR,
46
46
  'version': constants_1.APP.VERSION || '',
47
47
  [constants_1.AttributeKeys.VTEX_IO_WORKSPACE_NAME]: constants_1.WORKSPACE,
48
- [constants_1.AttributeKeys.VTEX_IO_WORKSPACE_TYPE]: constants_1.PRODUCTION.toString(),
48
+ [constants_1.AttributeKeys.VTEX_IO_WORKSPACE_TYPE]: constants_1.PRODUCTION ? 'production' : 'development',
49
49
  },
50
50
  });
51
51
  const [tracesClient, metricsClient, logsClient] = await Promise.all([
@@ -31,6 +31,7 @@ class Metric extends graphql_tools_1.SchemaDirectiveVisitor {
31
31
  // New diagnostics metrics with stable names and attributes
32
32
  if (global.diagnosticsMetrics) {
33
33
  const attributes = {
34
+ [__1.AttributeKeys.VTEX_ACCOUNT_NAME]: ctx.vtex.account,
34
35
  component: 'graphql',
35
36
  field_name: name,
36
37
  status,
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.trackIncomingRequestStats = exports.incomingRequestStats = exports.cancelMessage = void 0;
4
+ const constants_1 = require("../../../../../constants");
4
5
  exports.cancelMessage = 'Request cancelled';
5
6
  class IncomingRequestStats {
6
7
  constructor() {
@@ -25,9 +26,10 @@ exports.incomingRequestStats = new IncomingRequestStats();
25
26
  const requestClosed = (ctx) => () => {
26
27
  exports.incomingRequestStats.closed++;
27
28
  // Report to diagnostics metrics (cumulative counter)
28
- const { status: statusCode, vtex: { route: { id, type } } } = ctx;
29
+ const { status: statusCode, vtex: { account, route: { id, type } } } = ctx;
29
30
  if (global.diagnosticsMetrics) {
30
31
  global.diagnosticsMetrics.incrementCounter('http_server_requests_closed_total', 1, {
32
+ [constants_1.AttributeKeys.VTEX_ACCOUNT_NAME]: account,
31
33
  route_id: id,
32
34
  route_type: type,
33
35
  status_code: statusCode,
@@ -40,9 +42,10 @@ const requestClosed = (ctx) => () => {
40
42
  const requestAborted = (ctx) => () => {
41
43
  exports.incomingRequestStats.aborted++;
42
44
  // Report to diagnostics metrics (cumulative counter)
43
- const { status: statusCode, vtex: { route: { id, type } } } = ctx;
45
+ const { status: statusCode, vtex: { account, route: { id, type } } } = ctx;
44
46
  if (global.diagnosticsMetrics) {
45
47
  global.diagnosticsMetrics.incrementCounter('http_server_requests_aborted_total', 1, {
48
+ [constants_1.AttributeKeys.VTEX_ACCOUNT_NAME]: account,
46
49
  route_id: id,
47
50
  route_type: type,
48
51
  status_code: statusCode,
@@ -61,9 +64,10 @@ async function trackIncomingRequestStats(ctx, next) {
61
64
  ctx.req.on('aborted', requestAborted(ctx));
62
65
  exports.incomingRequestStats.total++;
63
66
  // Report total requests to diagnostics metrics (cumulative counter)
64
- const { status: statusCode, vtex: { route: { id, type } } } = ctx;
67
+ const { status: statusCode, vtex: { account, route: { id, type } } } = ctx;
65
68
  if (global.diagnosticsMetrics) {
66
69
  global.diagnosticsMetrics.incrementCounter('http_server_requests_total', 1, {
70
+ [constants_1.AttributeKeys.VTEX_ACCOUNT_NAME]: account,
67
71
  route_id: id,
68
72
  route_type: type,
69
73
  status_code: statusCode,
@@ -46,6 +46,7 @@ async function timings(ctx, next) {
46
46
  // New diagnostics metrics with stable names and attributes
47
47
  if (global.diagnosticsMetrics) {
48
48
  const attributes = {
49
+ [constants_1.AttributeKeys.VTEX_ACCOUNT_NAME]: vtex.account,
49
50
  component: 'http-handler',
50
51
  route_id: id,
51
52
  route_type: type,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/api",
3
- "version": "7.3.0-beta.5",
3
+ "version": "7.3.0",
4
4
  "description": "VTEX I/O API client",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
@@ -53,8 +53,8 @@
53
53
  "@opentelemetry/instrumentation-koa": "0.47.1",
54
54
  "@types/koa": "^2.11.0",
55
55
  "@types/koa-compose": "^3.2.3",
56
- "@vtex/diagnostics-nodejs": "0.1.0-io-beta.26",
57
- "@vtex/diagnostics-semconv": "1.1.2",
56
+ "@vtex/diagnostics-nodejs": "0.1.8-io",
57
+ "@vtex/diagnostics-semconv": "^1.1.2",
58
58
  "@vtex/node-error-report": "^0.0.3",
59
59
  "@wry/equality": "^0.1.9",
60
60
  "agentkeepalive": "^4.0.2",
@@ -88,7 +88,7 @@
88
88
  "ramda": "^0.26.0",
89
89
  "rwlock": "^5.0.0",
90
90
  "semver": "^5.5.1",
91
- "stats-lite": "vtex/node-stats-lite#dist",
91
+ "stats-lite": "vtex/node-stats-lite#v2.2.1",
92
92
  "tar-fs": "^2.0.0",
93
93
  "tokenbucket": "^0.3.2",
94
94
  "uuid": "^3.3.3",