@vtex/api 6.45.22 → 6.45.24
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 -0
- package/lib/HttpClient/HttpClient.d.ts +1 -0
- package/lib/HttpClient/HttpClient.js +3 -2
- package/lib/HttpClient/typings.d.ts +10 -0
- package/lib/service/metrics/requestMetricsMiddleware.d.ts +2 -0
- package/lib/service/metrics/requestMetricsMiddleware.js +44 -0
- package/lib/service/tracing/tracingMiddlewares.js +2 -23
- package/lib/service/worker/index.js +2 -0
- package/lib/service/worker/runtime/typings.d.ts +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [6.45.24] - 2023-10-05
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Allow disabling memoization for all requests of a client
|
|
14
|
+
## [6.45.23] - 2023-10-04
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
- Fix metrics being restricted by tracing restrictions
|
|
18
|
+
|
|
10
19
|
## [6.45.22] - 2023-09-20
|
|
11
20
|
|
|
12
21
|
### Removed
|
|
@@ -97,14 +97,15 @@ class HttpClient {
|
|
|
97
97
|
};
|
|
98
98
|
this.getConfig = (url, config = {}) => ({
|
|
99
99
|
cacheable: this.cacheableType,
|
|
100
|
-
memoizable:
|
|
100
|
+
memoizable: this.memoizable,
|
|
101
101
|
...config,
|
|
102
102
|
url,
|
|
103
103
|
});
|
|
104
|
-
const { baseURL, authToken, authType, memoryCache, diskCache, 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;
|
|
104
|
+
const { baseURL, authToken, authType, memoryCache, diskCache, memoizable = true, 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
105
|
this.name = name || baseURL || 'unknown';
|
|
106
106
|
this.logger = logger;
|
|
107
107
|
this.cacheableType = cacheableType;
|
|
108
|
+
this.memoizable = memoizable;
|
|
108
109
|
const limit = concurrency && concurrency > 0 && p_limit_1.default(concurrency) || undefined;
|
|
109
110
|
const headers = {
|
|
110
111
|
...defaultHeaders,
|
|
@@ -74,6 +74,16 @@ export interface InstanceOptions {
|
|
|
74
74
|
timeout?: number;
|
|
75
75
|
memoryCache?: CacheLayer<string, Cached>;
|
|
76
76
|
diskCache?: CacheLayer<string, Cached>;
|
|
77
|
+
/**
|
|
78
|
+
* Enables memoization, ephemeral within each request, for all requests of this client.
|
|
79
|
+
* Useful for services that makes recursive requests, like graphql resolvers, which
|
|
80
|
+
* might fetch the same endpoint more than once.
|
|
81
|
+
* If that's not the case for your service, disabling it might improve the CPU and
|
|
82
|
+
* memory usage.
|
|
83
|
+
*
|
|
84
|
+
* Default value: true
|
|
85
|
+
*/
|
|
86
|
+
memoizable?: boolean;
|
|
77
87
|
baseURL?: string;
|
|
78
88
|
retries?: number;
|
|
79
89
|
exponentialTimeoutCoefficient?: number;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import { ServiceContext } from '../worker/runtime/typings';
|
|
2
|
+
export declare const addRequestMetricsMiddleware: () => (ctx: ServiceContext<import("../..").IOClients, import("../worker/runtime/typings").RecorderState, import("../worker/runtime/typings").ParamsContext>, next: () => Promise<void>) => Promise<void>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const stream_1 = require("stream");
|
|
4
|
+
const utils_1 = require("../../utils");
|
|
5
|
+
const instruments_1 = require("../tracing/metrics/instruments");
|
|
6
|
+
exports.addRequestMetricsMiddleware = () => {
|
|
7
|
+
const concurrentRequests = instruments_1.createConcurrentRequestsInstrument();
|
|
8
|
+
const requestTimings = instruments_1.createRequestsTimingsInstrument();
|
|
9
|
+
const totalRequests = instruments_1.createTotalRequestsInstrument();
|
|
10
|
+
const responseSizes = instruments_1.createRequestsResponseSizesInstrument();
|
|
11
|
+
const abortedRequests = instruments_1.createTotalAbortedRequestsInstrument();
|
|
12
|
+
return async function addRequestMetrics(ctx, next) {
|
|
13
|
+
const start = process.hrtime();
|
|
14
|
+
concurrentRequests.inc(1);
|
|
15
|
+
ctx.req.once('aborted', () => abortedRequests.inc({ ["handler" /* REQUEST_HANDLER */]: ctx.requestHandlerName }, 1));
|
|
16
|
+
let responseClosed = false;
|
|
17
|
+
ctx.res.once('close', () => (responseClosed = true));
|
|
18
|
+
try {
|
|
19
|
+
await next();
|
|
20
|
+
}
|
|
21
|
+
finally {
|
|
22
|
+
const responseLength = ctx.response.length;
|
|
23
|
+
if (responseLength) {
|
|
24
|
+
responseSizes.observe({ ["handler" /* REQUEST_HANDLER */]: ctx.requestHandlerName }, responseLength);
|
|
25
|
+
}
|
|
26
|
+
totalRequests.inc({
|
|
27
|
+
["handler" /* REQUEST_HANDLER */]: ctx.requestHandlerName,
|
|
28
|
+
["status_code" /* STATUS_CODE */]: ctx.response.status,
|
|
29
|
+
}, 1);
|
|
30
|
+
const onResFinished = () => {
|
|
31
|
+
requestTimings.observe({
|
|
32
|
+
["handler" /* REQUEST_HANDLER */]: ctx.requestHandlerName,
|
|
33
|
+
}, utils_1.hrToMillisFloat(process.hrtime(start)));
|
|
34
|
+
concurrentRequests.dec(1);
|
|
35
|
+
};
|
|
36
|
+
if (responseClosed) {
|
|
37
|
+
onResFinished();
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
stream_1.finished(ctx.res, onResFinished);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -7,23 +7,14 @@ const tracing_1 = require("../../tracing");
|
|
|
7
7
|
const Tags_1 = require("../../tracing/Tags");
|
|
8
8
|
const utils_1 = require("../../tracing/utils");
|
|
9
9
|
const utils_2 = require("../../utils");
|
|
10
|
-
const instruments_1 = require("./metrics/instruments");
|
|
11
10
|
const PATHS_BLACKLISTED_FOR_TRACING = ['/_status', '/healthcheck'];
|
|
12
11
|
exports.addTracingMiddleware = (tracer) => {
|
|
13
|
-
const concurrentRequests = instruments_1.createConcurrentRequestsInstrument();
|
|
14
|
-
const requestTimings = instruments_1.createRequestsTimingsInstrument();
|
|
15
|
-
const totalRequests = instruments_1.createTotalRequestsInstrument();
|
|
16
|
-
const responseSizes = instruments_1.createRequestsResponseSizesInstrument();
|
|
17
|
-
const abortedRequests = instruments_1.createTotalAbortedRequestsInstrument();
|
|
18
12
|
return async function addTracing(ctx, next) {
|
|
19
13
|
var _a;
|
|
20
|
-
const start = process.hrtime();
|
|
21
|
-
concurrentRequests.inc(1);
|
|
22
14
|
const rootSpan = tracer.extract(opentracing_1.FORMAT_HTTP_HEADERS, ctx.request.headers);
|
|
23
15
|
ctx.tracing = { tracer, currentSpan: undefined };
|
|
24
16
|
if (!shouldTrace(ctx, rootSpan)) {
|
|
25
17
|
await next();
|
|
26
|
-
concurrentRequests.dec(1);
|
|
27
18
|
return;
|
|
28
19
|
}
|
|
29
20
|
const currentSpan = tracer.startSpan('unknown-operation', {
|
|
@@ -32,7 +23,6 @@ exports.addTracingMiddleware = (tracer) => {
|
|
|
32
23
|
});
|
|
33
24
|
const initialSamplingDecision = tracing_1.getTraceInfo(currentSpan).isSampled;
|
|
34
25
|
ctx.tracing = { currentSpan, tracer };
|
|
35
|
-
ctx.req.once('aborted', () => abortedRequests.inc({ ["handler" /* REQUEST_HANDLER */]: currentSpan.operationName }, 1));
|
|
36
26
|
let responseClosed = false;
|
|
37
27
|
ctx.res.once('close', () => (responseClosed = true));
|
|
38
28
|
try {
|
|
@@ -43,14 +33,6 @@ exports.addTracingMiddleware = (tracer) => {
|
|
|
43
33
|
throw err;
|
|
44
34
|
}
|
|
45
35
|
finally {
|
|
46
|
-
const responseLength = ctx.response.length;
|
|
47
|
-
if (responseLength) {
|
|
48
|
-
responseSizes.observe({ ["handler" /* REQUEST_HANDLER */]: currentSpan.operationName }, responseLength);
|
|
49
|
-
}
|
|
50
|
-
totalRequests.inc({
|
|
51
|
-
["handler" /* REQUEST_HANDLER */]: currentSpan.operationName,
|
|
52
|
-
["status_code" /* STATUS_CODE */]: ctx.response.status,
|
|
53
|
-
}, 1);
|
|
54
36
|
const traceInfo = tracing_1.getTraceInfo(currentSpan);
|
|
55
37
|
if (traceInfo === null || traceInfo === void 0 ? void 0 : traceInfo.isSampled) {
|
|
56
38
|
if (!initialSamplingDecision) {
|
|
@@ -70,10 +52,6 @@ exports.addTracingMiddleware = (tracer) => {
|
|
|
70
52
|
ctx.set(constants_1.TRACE_ID_HEADER, traceInfo.traceId);
|
|
71
53
|
}
|
|
72
54
|
const onResFinished = () => {
|
|
73
|
-
requestTimings.observe({
|
|
74
|
-
["handler" /* REQUEST_HANDLER */]: currentSpan.operationName,
|
|
75
|
-
}, utils_2.hrToMillisFloat(process.hrtime(start)));
|
|
76
|
-
concurrentRequests.dec(1);
|
|
77
55
|
currentSpan === null || currentSpan === void 0 ? void 0 : currentSpan.finish();
|
|
78
56
|
};
|
|
79
57
|
if (responseClosed) {
|
|
@@ -88,7 +66,8 @@ exports.addTracingMiddleware = (tracer) => {
|
|
|
88
66
|
exports.nameSpanOperationMiddleware = (operationType, operationName) => {
|
|
89
67
|
return function nameSpanOperation(ctx, next) {
|
|
90
68
|
var _a, _b;
|
|
91
|
-
|
|
69
|
+
ctx.requestHandlerName = `${operationType}:${operationName}`;
|
|
70
|
+
(_b = (_a = ctx.tracing) === null || _a === void 0 ? void 0 : _a.currentSpan) === null || _b === void 0 ? void 0 : _b.setOperationName(ctx.requestHandlerName);
|
|
92
71
|
return next();
|
|
93
72
|
};
|
|
94
73
|
};
|
|
@@ -13,6 +13,7 @@ const MetricsAccumulator_1 = require("../../metrics/MetricsAccumulator");
|
|
|
13
13
|
const loaders_1 = require("../loaders");
|
|
14
14
|
const console_1 = require("../logger/console");
|
|
15
15
|
const logger_1 = require("../logger/logger");
|
|
16
|
+
const requestMetricsMiddleware_1 = require("../metrics/requestMetricsMiddleware");
|
|
16
17
|
const TracerSingleton_1 = require("../tracing/TracerSingleton");
|
|
17
18
|
const tracingMiddlewares_1 = require("../tracing/tracingMiddlewares");
|
|
18
19
|
const listeners_1 = require("./listeners");
|
|
@@ -157,6 +158,7 @@ exports.startWorker = (serviceJSON) => {
|
|
|
157
158
|
.use(error_1.error)
|
|
158
159
|
.use(middlewares_1.prometheusLoggerMiddleware())
|
|
159
160
|
.use(tracingMiddlewares_1.addTracingMiddleware(tracer))
|
|
161
|
+
.use(requestMetricsMiddleware_1.addRequestMetricsMiddleware())
|
|
160
162
|
.use(middlewares_1.addMetricsLoggerMiddleware())
|
|
161
163
|
.use(rateLimit_1.concurrentRateLimiter((_a = serviceJSON === null || serviceJSON === void 0 ? void 0 : serviceJSON.rateLimitPerReplica) === null || _a === void 0 ? void 0 : _a.concurrent))
|
|
162
164
|
.use(koa_compress_1.default())
|
|
@@ -29,6 +29,7 @@ export interface Context<T extends IOClients> {
|
|
|
29
29
|
timings: Record<string, [number, number]>;
|
|
30
30
|
metrics: Record<string, [number, number]>;
|
|
31
31
|
previousTimerStart: [number, number];
|
|
32
|
+
requestHandlerName?: string;
|
|
32
33
|
serverTiming?: ServerTiming;
|
|
33
34
|
tracing?: TracingContext;
|
|
34
35
|
}
|