@vtex/api 7.3.0-beta.4 → 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 +9 -1
- package/lib/HttpClient/HttpClient.js +2 -1
- package/lib/HttpClient/middlewares/metrics.js +6 -1
- package/lib/metrics/DiagnosticsMetrics.js +1 -1
- package/lib/service/metrics/metrics.d.ts +5 -4
- package/lib/service/metrics/metrics.js +7 -1
- package/lib/service/metrics/otelRequestMetricsMiddleware.js +12 -7
- package/lib/service/telemetry/client.js +1 -1
- package/lib/service/worker/runtime/graphql/schema/schemaDirectives/Metric.js +1 -0
- package/lib/service/worker/runtime/http/middlewares/requestStats.js +7 -3
- package/lib/service/worker/runtime/http/middlewares/timings.js +1 -0
- package/package.json +3 -3
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.
|
|
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 =
|
|
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
|
|
3
|
-
STATUS_CODE
|
|
4
|
-
REQUEST_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, { [
|
|
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
|
-
[
|
|
46
|
-
[
|
|
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
|
-
[
|
|
52
|
-
[
|
|
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
|
-
[
|
|
59
|
-
[
|
|
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
|
|
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
|
|
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,7 +53,7 @@
|
|
|
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.
|
|
56
|
+
"@vtex/diagnostics-nodejs": "0.1.8-io",
|
|
57
57
|
"@vtex/diagnostics-semconv": "^1.1.2",
|
|
58
58
|
"@vtex/node-error-report": "^0.0.3",
|
|
59
59
|
"@wry/equality": "^0.1.9",
|
|
@@ -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#
|
|
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",
|