@vtex/api 6.45.21 → 6.45.23

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,6 +7,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [6.45.23] - 2023-10-04
11
+
12
+ ### Fixed
13
+ - Fix metrics being restricted by tracing restrictions
14
+
15
+ ## [6.45.22] - 2023-09-20
16
+
17
+ ### Removed
18
+
19
+ - Remove reference of how to search for the app's errors on now-defunct Splunk.
20
+
21
+ ### Fixed
22
+
23
+ - Error tracing spans not logging the details.
24
+
10
25
  ## [6.45.21] - 2023-09-19
11
26
  ### Changed
12
27
  - Fix tracingMiddleware shouldTrace decision
@@ -1789,11 +1804,12 @@ instead
1789
1804
  - `HttpClient` now adds `'Accept-Encoding': 'gzip'` header by default.
1790
1805
 
1791
1806
 
1792
- [Unreleased]: https://github.com/vtex/node-vtex-api/compare/v6.45.21...HEAD
1807
+ [Unreleased]: https://github.com/vtex/node-vtex-api/compare/v6.45.22...HEAD
1793
1808
  [6.45.15]: https://github.com/vtex/node-vtex-api/compare/v6.45.14...v6.45.15
1794
1809
  [6.45.14]: https://github.com/vtex/node-vtex-api/compare/v6.45.13...v6.45.14
1795
1810
  [6.45.13]: https://github.com/vtex/node-vtex-api/compare/v6.45.12...v6.45.13
1796
1811
 
1812
+ [6.45.22]: https://github.com/vtex/node-vtex-api/compare/v6.45.21...v6.45.22
1797
1813
  [6.45.21]: https://github.com/vtex/node-vtex-api/compare/v6.45.21-beta.2...v6.45.21
1798
1814
  [6.45.21-beta.2]: https://github.com/vtex/node-vtex-api/compare/v6.45.21-beta.1...v6.45.21-beta.2
1799
1815
  [6.45.21-beta.1]: https://github.com/vtex/node-vtex-api/compare/v6.45.21-beta.0...v6.45.21-beta.1
@@ -25,11 +25,5 @@ export declare class Logger {
25
25
  warn: (warning: any) => void;
26
26
  error: (error: any) => void;
27
27
  log: (message: any, level: LogLevel) => void;
28
- /**
29
- * Logs splunk query so the developer can search for the errors in splunk.
30
- * This function runs only once in the lifetime of the Logger class so we
31
- * don't mess up with the developer's terminal
32
- */
33
- private logSplunkQuery;
34
28
  }
35
29
  export {};
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const constants_1 = require("../../constants");
4
4
  const error_1 = require("../../utils/error");
5
5
  const log_1 = require("../../utils/log");
6
- const console_1 = require("./console");
7
6
  const linked = !!process.env.VTEX_APP_LINK;
8
7
  const app = constants_1.APP.ID;
9
8
  const EMPTY_MESSAGE = 'Logger.log was called with null or undefined message';
@@ -45,19 +44,6 @@ class Logger {
45
44
  });
46
45
  }
47
46
  console.log(JSON.stringify(inflatedLog));
48
- // Warn the developer how to retrieve the error in splunk
49
- this.logSplunkQuery();
50
- };
51
- /**
52
- * Logs splunk query so the developer can search for the errors in splunk.
53
- * This function runs only once in the lifetime of the Logger class so we
54
- * don't mess up with the developer's terminal
55
- */
56
- this.logSplunkQuery = () => {
57
- if (linked) {
58
- const message = `Try this query at Splunk to retrieve error log: 'index=io_vtex_logs app="${app}" account=${this.account} workspace=${this.workspace} level=error OR level=warn'`;
59
- console_1.logOnceToDevConsole(message, LogLevel.Info);
60
- }
61
47
  };
62
48
  this.account = ctx.account;
63
49
  this.workspace = ctx.workspace;
@@ -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
- (_b = (_a = ctx.tracing) === null || _a === void 0 ? void 0 : _a.currentSpan) === null || _b === void 0 ? void 0 : _b.setOperationName(`${operationType}:${operationName}`);
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
  }
@@ -12,6 +12,11 @@ export declare const enum ErrorReportLogFields {
12
12
  */
13
13
  ERROR_KIND = "error.kind",
14
14
  ERROR_ID = "error.id",
15
+ ERROR_MESSAGE = "error.message",
16
+ ERROR_CODE = "error.code",
17
+ ERROR_STACK = "error.stack",
18
+ ERROR_METADATA_REPORT_COUNT = "error.metadata.reportCount",
19
+ ERROR_METADATA_METRICS_INSTANTIATION_TIME = "error.metadata.metrics.InstantiationTime",
15
20
  /**
16
21
  * VTEX's Infra errors adds error details to the response
17
22
  * The following log fields are supposed to hold these fields
@@ -34,7 +34,7 @@ class ErrorReport extends node_error_report_1.ErrorReportBase {
34
34
  * span is part of a **sampled** trace, then the error will be logged.
35
35
  */
36
36
  injectOnSpan(span, logger) {
37
- var _a;
37
+ var _a, _b, _c, _d;
38
38
  span === null || span === void 0 ? void 0 : span.setTag(__1.TracingTags.ERROR, 'true');
39
39
  const indexedLogs = {
40
40
  ["error.kind" /* ERROR_KIND */]: this.kind,
@@ -47,7 +47,15 @@ class ErrorReport extends node_error_report_1.ErrorReportBase {
47
47
  indexedLogs["error.server.request_id" /* ERROR_SERVER_REQUEST_ID */] = this.parsedInfo.response.data.requestId;
48
48
  }
49
49
  const serializableError = this.toObject();
50
- span === null || span === void 0 ? void 0 : span.log({ event: 'error', ...indexedLogs, error: serializableError });
50
+ span === null || span === void 0 ? void 0 : span.log({
51
+ event: 'error',
52
+ ...indexedLogs,
53
+ ["error.message" /* ERROR_MESSAGE */]: serializableError.message,
54
+ ["error.metadata.metrics.InstantiationTime" /* ERROR_METADATA_METRICS_INSTANTIATION_TIME */]: (_b = serializableError.metadata) === null || _b === void 0 ? void 0 : _b.reportCount,
55
+ ["error.metadata.reportCount" /* ERROR_METADATA_REPORT_COUNT */]: (_d = (_c = serializableError.metadata) === null || _c === void 0 ? void 0 : _c.metrics) === null || _d === void 0 ? void 0 : _d.instantiationTime,
56
+ ["error.stack" /* ERROR_STACK */]: serializableError.stack,
57
+ ["error.code" /* ERROR_CODE */]: serializableError.code,
58
+ });
51
59
  if (logger && this.shouldLogToSplunk(span)) {
52
60
  logger.error(serializableError);
53
61
  this.markErrorAsReported();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/api",
3
- "version": "6.45.21",
3
+ "version": "6.45.23",
4
4
  "description": "VTEX I/O API client",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",