@vtex/api 7.1.0 → 7.2.1-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.
@@ -58,3 +58,6 @@ export declare const PRODUCTION: boolean;
58
58
  export declare const INSPECT_DEBUGGER_PORT = 5858;
59
59
  export declare const cancellableMethods: Set<string>;
60
60
  export declare const LOG_CLIENT_INIT_TIMEOUT_MS = 5000;
61
+ export declare const OTEL_EXPORTER_OTLP_ENDPOINT: string;
62
+ export declare const DK_APP_ID: string;
63
+ export declare const DIAGNOSTICS_TELEMETRY_ENABLED: boolean;
package/lib/constants.js CHANGED
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LOG_CLIENT_INIT_TIMEOUT_MS = exports.cancellableMethods = exports.INSPECT_DEBUGGER_PORT = exports.PRODUCTION = exports.WORKSPACE = exports.ACCOUNT = exports.NODE_ENV = exports.APP = exports.PUBLIC_ENDPOINT = exports.REGION = exports.LINKED = exports.MAX_WORKERS = exports.HTTP_SERVER_PORT = exports.MAX_AGE = exports.UP_SIGNAL = exports.BODY_HASH = exports.PROVIDER_HEADER = exports.TRACE_ID_HEADER = exports.COLOSSUS_PARAMS_HEADER = exports.COLOSSUS_ROUTE_ID_HEADER = exports.COLOSSUS_ROUTE_DECLARER_HEADER = exports.EVENT_HANDLER_ID_HEADER = exports.EVENT_SUBJECT_HEADER = exports.EVENT_SENDER_HEADER = exports.EVENT_KEY_HEADER = exports.WORKSPACE_HEADER = exports.WORKSPACE_IS_PRODUCTION_HEADER = exports.PLATFORM_HEADER = exports.OPERATION_ID_HEADER = exports.ROUTER_CACHE_HEADER = exports.REQUEST_ID_HEADER = exports.CREDENTIAL_HEADER = exports.ACCOUNT_HEADER = exports.ETAG_HEADER = exports.META_HEADER_BUCKET = exports.META_HEADER = exports.BINDING_HEADER = exports.TENANT_HEADER = exports.FORWARDED_HOST_HEADER = exports.LOCALE_HEADER = exports.PRODUCT_HEADER = exports.SESSION_HEADER = exports.SEGMENT_HEADER = exports.CACHE_CONTROL_HEADER = exports.PID = exports.IS_IO = exports.DEFAULT_WORKSPACE = exports.NODE_VTEX_API_VERSION = void 0;
3
+ exports.DK_APP_ID = exports.OTEL_EXPORTER_OTLP_ENDPOINT = exports.LOG_CLIENT_INIT_TIMEOUT_MS = exports.cancellableMethods = exports.INSPECT_DEBUGGER_PORT = exports.PRODUCTION = exports.WORKSPACE = exports.ACCOUNT = exports.NODE_ENV = exports.APP = exports.PUBLIC_ENDPOINT = exports.REGION = exports.LINKED = exports.MAX_WORKERS = exports.HTTP_SERVER_PORT = exports.MAX_AGE = exports.UP_SIGNAL = exports.BODY_HASH = exports.PROVIDER_HEADER = exports.TRACE_ID_HEADER = exports.COLOSSUS_PARAMS_HEADER = exports.COLOSSUS_ROUTE_ID_HEADER = exports.COLOSSUS_ROUTE_DECLARER_HEADER = exports.EVENT_HANDLER_ID_HEADER = exports.EVENT_SUBJECT_HEADER = exports.EVENT_SENDER_HEADER = exports.EVENT_KEY_HEADER = exports.WORKSPACE_HEADER = exports.WORKSPACE_IS_PRODUCTION_HEADER = exports.PLATFORM_HEADER = exports.OPERATION_ID_HEADER = exports.ROUTER_CACHE_HEADER = exports.REQUEST_ID_HEADER = exports.CREDENTIAL_HEADER = exports.ACCOUNT_HEADER = exports.ETAG_HEADER = exports.META_HEADER_BUCKET = exports.META_HEADER = exports.BINDING_HEADER = exports.TENANT_HEADER = exports.FORWARDED_HOST_HEADER = exports.LOCALE_HEADER = exports.PRODUCT_HEADER = exports.SESSION_HEADER = exports.SEGMENT_HEADER = exports.CACHE_CONTROL_HEADER = exports.PID = exports.IS_IO = exports.DEFAULT_WORKSPACE = exports.NODE_VTEX_API_VERSION = void 0;
4
+ exports.DIAGNOSTICS_TELEMETRY_ENABLED = void 0;
4
5
  const app_1 = require("./utils/app");
5
6
  // tslint:disable-next-line
6
7
  const pkg = require('../package.json');
@@ -65,3 +66,6 @@ exports.PRODUCTION = process.env.VTEX_PRODUCTION === 'true';
65
66
  exports.INSPECT_DEBUGGER_PORT = 5858;
66
67
  exports.cancellableMethods = new Set(['GET', 'OPTIONS', 'HEAD']);
67
68
  exports.LOG_CLIENT_INIT_TIMEOUT_MS = 5000;
69
+ exports.OTEL_EXPORTER_OTLP_ENDPOINT = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;
70
+ exports.DK_APP_ID = process.env.NODE_VTEX_API_DK_APP_ID || "apps-team";
71
+ exports.DIAGNOSTICS_TELEMETRY_ENABLED = process.env.VTEX_DIAGNOSTICS_TELEMETRY_ENABLED === 'true';
@@ -1,2 +1,2 @@
1
- export declare const startApp: () => void;
1
+ export declare const startApp: () => Promise<void>;
2
2
  export { appPath } from './loaders';
@@ -1,25 +1,51 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
27
  };
5
28
  Object.defineProperty(exports, "__esModule", { value: true });
6
29
  exports.appPath = exports.startApp = void 0;
30
+ const telemetry_1 = require("./telemetry");
7
31
  const cluster_1 = __importDefault(require("cluster"));
8
32
  const constants_1 = require("../constants");
9
33
  const loaders_1 = require("./loaders");
10
34
  const logger_1 = require("./logger");
11
- const master_1 = require("./master");
12
- const worker_1 = require("./worker");
13
- const startApp = () => {
35
+ const startApp = async () => {
36
+ await (0, telemetry_1.initializeTelemetry)();
14
37
  const serviceJSON = (0, loaders_1.getServiceJSON)();
15
38
  try {
16
39
  // if it is a master process then call setting up worker process
17
40
  if (cluster_1.default.isMaster) {
18
- (0, master_1.startMaster)(serviceJSON);
41
+ const { startMaster } = await Promise.resolve().then(() => __importStar(require('./master')));
42
+ startMaster(serviceJSON);
19
43
  }
20
44
  else {
21
45
  // to setup server configurations and share port address for incoming requests
22
- (0, worker_1.startWorker)(serviceJSON).listen(constants_1.HTTP_SERVER_PORT);
46
+ const { startWorker } = await Promise.resolve().then(() => __importStar(require('./worker')));
47
+ const app = await startWorker(serviceJSON);
48
+ app.listen(constants_1.HTTP_SERVER_PORT);
23
49
  }
24
50
  }
25
51
  catch (err) {
@@ -77,7 +77,7 @@ class Logger {
77
77
  traceId: ctx.tracer.traceId,
78
78
  };
79
79
  }
80
- // this.initLogClient();
80
+ this.initLogClient();
81
81
  }
82
82
  initLogClient() {
83
83
  if (this.clientInitPromise) {
@@ -0,0 +1,2 @@
1
+ import { Types } from "@vtex/diagnostics-nodejs";
2
+ export declare const getMetricClient: () => Promise<Types.MetricClient>;
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getMetricClient = void 0;
4
+ const telemetry_1 = require("../telemetry");
5
+ class MetricClientSingleton {
6
+ constructor() { }
7
+ static getInstance() {
8
+ if (!MetricClientSingleton.instance) {
9
+ MetricClientSingleton.instance = new MetricClientSingleton();
10
+ }
11
+ return MetricClientSingleton.instance;
12
+ }
13
+ async getClient() {
14
+ if (this.client) {
15
+ return this.client;
16
+ }
17
+ if (this.initPromise) {
18
+ return this.initPromise;
19
+ }
20
+ this.initPromise = this.initializeClient();
21
+ return this.initPromise;
22
+ }
23
+ async initializeClient() {
24
+ try {
25
+ const { metricsClient } = await (0, telemetry_1.initializeTelemetry)();
26
+ this.client = metricsClient;
27
+ this.initPromise = undefined;
28
+ return metricsClient;
29
+ }
30
+ catch (error) {
31
+ console.error('Failed to initialize metrics client:', error);
32
+ this.initPromise = undefined;
33
+ throw error;
34
+ }
35
+ }
36
+ }
37
+ const getMetricClient = () => MetricClientSingleton.getInstance().getClient();
38
+ exports.getMetricClient = getMetricClient;
@@ -0,0 +1,14 @@
1
+ import { InstrumentationBase, InstrumentationConfig } from "@opentelemetry/instrumentation";
2
+ import { MeterProvider } from '@opentelemetry/api';
3
+ interface HostMetricsInstrumentationConfig extends InstrumentationConfig {
4
+ name?: string;
5
+ meterProvider?: MeterProvider;
6
+ }
7
+ export declare class HostMetricsInstrumentation extends InstrumentationBase<HostMetricsInstrumentationConfig> {
8
+ private hostMetrics?;
9
+ constructor(config?: HostMetricsInstrumentationConfig);
10
+ init(): void;
11
+ enable(): void;
12
+ disable(): void;
13
+ }
14
+ export {};
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HostMetricsInstrumentation = void 0;
4
+ const instrumentation_1 = require("@opentelemetry/instrumentation");
5
+ const host_metrics_1 = require("@opentelemetry/host-metrics");
6
+ class HostMetricsInstrumentation extends instrumentation_1.InstrumentationBase {
7
+ constructor(config = {}) {
8
+ const instrumentation_name = config.name || 'host-metrics-instrumentation';
9
+ const instrumentation_version = '1.0.0';
10
+ super(instrumentation_name, instrumentation_version, config);
11
+ }
12
+ init() { }
13
+ enable() {
14
+ if (!this._config.meterProvider) {
15
+ throw new Error('MeterProvider is required for HostMetricsInstrumentation');
16
+ }
17
+ this.hostMetrics = new host_metrics_1.HostMetrics({
18
+ meterProvider: this._config.meterProvider,
19
+ name: this._config.name || 'host-metrics',
20
+ });
21
+ this.hostMetrics.start();
22
+ console.debug('HostMetricsInstrumentation enabled');
23
+ }
24
+ disable() {
25
+ if (this.hostMetrics) {
26
+ this.hostMetrics = undefined;
27
+ console.debug('HostMetricsInstrumentation disabled');
28
+ }
29
+ }
30
+ }
31
+ exports.HostMetricsInstrumentation = HostMetricsInstrumentation;
@@ -0,0 +1,13 @@
1
+ import { Types } from '@vtex/diagnostics-nodejs';
2
+ export declare const enum RequestsMetricLabels {
3
+ STATUS_CODE = "status_code",
4
+ REQUEST_HANDLER = "handler"
5
+ }
6
+ export interface OtelRequestInstruments {
7
+ concurrentRequests: Types.Gauge;
8
+ requestTimings: Types.Histogram;
9
+ totalRequests: Types.Counter;
10
+ responseSizes: Types.Histogram;
11
+ abortedRequests: Types.Counter;
12
+ }
13
+ export declare const getOtelInstruments: () => Promise<OtelRequestInstruments>;
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOtelInstruments = void 0;
4
+ const client_1 = require("./client");
5
+ const createOtelConcurrentRequestsInstrument = async () => {
6
+ const metricsClient = await (0, client_1.getMetricClient)();
7
+ return metricsClient.createGauge('io_http_requests_current', {
8
+ description: 'The current number of requests in course.',
9
+ unit: '1'
10
+ });
11
+ };
12
+ const createOtelRequestsTimingsInstrument = async () => {
13
+ const metricsClient = await (0, client_1.getMetricClient)();
14
+ return metricsClient.createHistogram('runtime_http_requests_duration_milliseconds', {
15
+ description: 'The incoming http requests total duration.',
16
+ unit: 'ms'
17
+ });
18
+ };
19
+ const createOtelTotalRequestsInstrument = async () => {
20
+ const metricsClient = await (0, client_1.getMetricClient)();
21
+ return metricsClient.createCounter('runtime_http_requests_total', {
22
+ description: 'The total number of HTTP requests.',
23
+ unit: '1'
24
+ });
25
+ };
26
+ const createOtelRequestsResponseSizesInstrument = async () => {
27
+ const metricsClient = await (0, client_1.getMetricClient)();
28
+ return metricsClient.createHistogram('runtime_http_response_size_bytes', {
29
+ description: 'The outgoing response sizes (only applicable when the response isn\'t a stream).',
30
+ unit: 'bytes'
31
+ });
32
+ };
33
+ const createOtelTotalAbortedRequestsInstrument = async () => {
34
+ const metricsClient = await (0, client_1.getMetricClient)();
35
+ return metricsClient.createCounter('runtime_http_aborted_requests_total', {
36
+ description: 'The total number of HTTP requests aborted.',
37
+ unit: '1'
38
+ });
39
+ };
40
+ class OtelInstrumentsSingleton {
41
+ constructor() { }
42
+ static getInstance() {
43
+ if (!OtelInstrumentsSingleton.instance) {
44
+ OtelInstrumentsSingleton.instance = new OtelInstrumentsSingleton();
45
+ }
46
+ return OtelInstrumentsSingleton.instance;
47
+ }
48
+ async getInstruments() {
49
+ if (this.instruments) {
50
+ return this.instruments;
51
+ }
52
+ if (this.initializingPromise) {
53
+ return this.initializingPromise;
54
+ }
55
+ this.initializingPromise = this.initializeInstruments();
56
+ try {
57
+ this.instruments = await this.initializingPromise;
58
+ return this.instruments;
59
+ }
60
+ catch (error) {
61
+ console.error('Failed to initialize OTel instruments:', error);
62
+ this.initializingPromise = undefined;
63
+ throw error;
64
+ }
65
+ finally {
66
+ this.initializingPromise = undefined;
67
+ }
68
+ }
69
+ async initializeInstruments() {
70
+ const [concurrentRequests, requestTimings, totalRequests, responseSizes, abortedRequests] = await Promise.all([
71
+ createOtelConcurrentRequestsInstrument(),
72
+ createOtelRequestsTimingsInstrument(),
73
+ createOtelTotalRequestsInstrument(),
74
+ createOtelRequestsResponseSizesInstrument(),
75
+ createOtelTotalAbortedRequestsInstrument()
76
+ ]);
77
+ return {
78
+ concurrentRequests,
79
+ requestTimings,
80
+ totalRequests,
81
+ responseSizes,
82
+ abortedRequests
83
+ };
84
+ }
85
+ }
86
+ const getOtelInstruments = () => OtelInstrumentsSingleton.getInstance().getInstruments();
87
+ exports.getOtelInstruments = getOtelInstruments;
@@ -0,0 +1,2 @@
1
+ import { ServiceContext } from '../worker/runtime/typings';
2
+ export declare const addOtelRequestMetricsMiddleware: () => (ctx: ServiceContext, next: () => Promise<void>) => Promise<void>;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addOtelRequestMetricsMiddleware = void 0;
4
+ const stream_1 = require("stream");
5
+ const utils_1 = require("../../utils");
6
+ const metrics_1 = require("./metrics");
7
+ const INSTRUMENTS_INITIALIZATION_TIMEOUT = 500;
8
+ const addOtelRequestMetricsMiddleware = () => {
9
+ let instruments;
10
+ const tryGetInstruments = async (ctx) => {
11
+ try {
12
+ return await Promise.race([
13
+ (0, metrics_1.getOtelInstruments)(),
14
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout waiting for OpenTelemetry instruments initialization')), INSTRUMENTS_INITIALIZATION_TIMEOUT))
15
+ ]);
16
+ }
17
+ catch (error) {
18
+ const errorMessage = error instanceof Error ? error.message : String(error);
19
+ console.warn(`OpenTelemetry instruments not ready for request ${ctx.requestHandlerName}: ${errorMessage}`);
20
+ return undefined;
21
+ }
22
+ };
23
+ return async function addOtelRequestMetrics(ctx, next) {
24
+ instruments = instruments ? instruments : await tryGetInstruments(ctx);
25
+ if (!instruments) {
26
+ await next();
27
+ return;
28
+ }
29
+ const start = process.hrtime();
30
+ instruments.concurrentRequests.add(1);
31
+ ctx.req.once('aborted', () => {
32
+ if (instruments) {
33
+ instruments.abortedRequests.add(1, { ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName });
34
+ }
35
+ });
36
+ let responseClosed = false;
37
+ ctx.res.once('close', () => (responseClosed = true));
38
+ try {
39
+ await next();
40
+ }
41
+ finally {
42
+ const responseLength = ctx.response.length;
43
+ if (responseLength && instruments) {
44
+ instruments.responseSizes.record(responseLength, { ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName });
45
+ }
46
+ if (instruments) {
47
+ instruments.totalRequests.add(1, {
48
+ ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName,
49
+ ["status_code" /* RequestsMetricLabels.STATUS_CODE */]: ctx.response.status,
50
+ });
51
+ }
52
+ const onResFinished = () => {
53
+ if (instruments) {
54
+ instruments.requestTimings.record((0, utils_1.hrToMillisFloat)(process.hrtime(start)), {
55
+ ["handler" /* RequestsMetricLabels.REQUEST_HANDLER */]: ctx.requestHandlerName,
56
+ });
57
+ instruments.concurrentRequests.subtract(1);
58
+ }
59
+ };
60
+ if (responseClosed) {
61
+ onResFinished();
62
+ }
63
+ else {
64
+ (0, stream_1.finished)(ctx.res, onResFinished);
65
+ }
66
+ }
67
+ };
68
+ };
69
+ exports.addOtelRequestMetricsMiddleware = addOtelRequestMetricsMiddleware;
@@ -3,27 +3,27 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resetTelemetry = exports.initializeTelemetry = void 0;
4
4
  const diagnostics_nodejs_1 = require("@vtex/diagnostics-nodejs");
5
5
  const constants_1 = require("../../constants");
6
- const CLIENT_NAME = constants_1.APP.NAME || 'node-vtex-api';
6
+ const instrumentation_koa_1 = require("@opentelemetry/instrumentation-koa");
7
+ const hostMetrics_1 = require("../metrics/instruments/hostMetrics");
7
8
  const APPLICATION_ID = constants_1.APP.ID || 'vtex-io-app';
8
- const EXPORTER_OTLP_ENDPOINT = process.env.EXPORTER_OTLP_ENDPOINT;
9
9
  class TelemetryClientSingleton {
10
10
  constructor() {
11
11
  this.initializationPromise = undefined;
12
12
  this.initializeTracesClient = async (telemetryClient) => await telemetryClient.newTracesClient({
13
13
  exporter: diagnostics_nodejs_1.Exporters.CreateExporter(diagnostics_nodejs_1.Exporters.CreateTracesExporterConfig({
14
- endpoint: EXPORTER_OTLP_ENDPOINT,
14
+ endpoint: constants_1.OTEL_EXPORTER_OTLP_ENDPOINT,
15
15
  }), 'otlp'),
16
16
  });
17
17
  this.initializeMetricsClient = async (telemetryClient) => await telemetryClient.newMetricsClient({
18
18
  exporter: diagnostics_nodejs_1.Exporters.CreateExporter(diagnostics_nodejs_1.Exporters.CreateMetricsExporterConfig({
19
- endpoint: EXPORTER_OTLP_ENDPOINT,
19
+ endpoint: constants_1.OTEL_EXPORTER_OTLP_ENDPOINT,
20
20
  interval: 5,
21
21
  timeoutSeconds: 5,
22
22
  }), 'otlp'),
23
23
  });
24
24
  this.initializeLogsClient = async (telemetryClient) => await telemetryClient.newLogsClient({
25
25
  exporter: diagnostics_nodejs_1.Exporters.CreateExporter(diagnostics_nodejs_1.Exporters.CreateLogsExporterConfig({
26
- endpoint: EXPORTER_OTLP_ENDPOINT,
26
+ endpoint: constants_1.OTEL_EXPORTER_OTLP_ENDPOINT,
27
27
  }), 'otlp'),
28
28
  loggerName: `node-vtex-api-${APPLICATION_ID}`,
29
29
  });
@@ -36,10 +36,15 @@ class TelemetryClientSingleton {
36
36
  }
37
37
  async initializeTelemetryClients() {
38
38
  try {
39
- const telemetryClient = await (0, diagnostics_nodejs_1.NewTelemetryClient)(APPLICATION_ID, CLIENT_NAME, 'node-vtex-api', {
39
+ const telemetryClient = await (0, diagnostics_nodejs_1.NewTelemetryClient)(constants_1.DK_APP_ID, 'node-vtex-api', APPLICATION_ID, {
40
+ // Use built-in no-op functionality when telemetry is disabled
41
+ noop: !constants_1.DIAGNOSTICS_TELEMETRY_ENABLED,
40
42
  additionalAttrs: {
43
+ 'app.id': APPLICATION_ID,
44
+ 'vendor': constants_1.APP.VENDOR,
41
45
  'version': constants_1.APP.VERSION || '',
42
- 'environment': process.env.VTEX_WORKSPACE || 'development',
46
+ 'workspace': constants_1.WORKSPACE,
47
+ 'production': constants_1.PRODUCTION.toString(),
43
48
  },
44
49
  });
45
50
  const [tracesClient, metricsClient, logsClient] = await Promise.all([
@@ -47,10 +52,18 @@ class TelemetryClientSingleton {
47
52
  this.initializeMetricsClient(telemetryClient),
48
53
  this.initializeLogsClient(telemetryClient),
49
54
  ]);
50
- const instrumentations = [
51
- ...diagnostics_nodejs_1.Instrumentation.CommonInstrumentations.minimal(),
52
- ];
53
- telemetryClient.registerInstrumentations(instrumentations);
55
+ if (constants_1.DIAGNOSTICS_TELEMETRY_ENABLED) {
56
+ console.log(`Telemetry enabled for app: ${constants_1.APP.ID} (vendor: ${constants_1.APP.VENDOR})`);
57
+ const instrumentations = [
58
+ ...diagnostics_nodejs_1.Instrumentation.CommonInstrumentations.minimal(),
59
+ new instrumentation_koa_1.KoaInstrumentation(),
60
+ new hostMetrics_1.HostMetricsInstrumentation({
61
+ name: 'host-metrics-instrumentation',
62
+ meterProvider: metricsClient.provider(),
63
+ }),
64
+ ];
65
+ telemetryClient.registerInstrumentations(instrumentations);
66
+ }
54
67
  const clients = {
55
68
  logsClient,
56
69
  metricsClient,
@@ -4,6 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.startWorker = void 0;
7
+ const diagnostics_nodejs_1 = require("@vtex/diagnostics-nodejs");
7
8
  const http_1 = require("http");
8
9
  const koa_1 = __importDefault(require("koa"));
9
10
  const koa_compress_1 = __importDefault(require("koa-compress"));
@@ -15,6 +16,7 @@ const loaders_1 = require("../loaders");
15
16
  const console_1 = require("../logger/console");
16
17
  const loggerTypes_1 = require("../logger/loggerTypes");
17
18
  const requestMetricsMiddleware_1 = require("../metrics/requestMetricsMiddleware");
19
+ const otelRequestMetricsMiddleware_1 = require("../metrics/otelRequestMetricsMiddleware");
18
20
  const TracerSingleton_1 = require("../tracing/TracerSingleton");
19
21
  const tracingMiddlewares_1 = require("../tracing/tracingMiddlewares");
20
22
  const listeners_1 = require("./listeners");
@@ -157,9 +159,11 @@ const startWorker = (serviceJSON) => {
157
159
  app.proxy = true;
158
160
  app
159
161
  .use(error_1.error)
162
+ .use(diagnostics_nodejs_1.Instrumentation.Middlewares.ContextMiddlewares.Koa.ContextPropagationMiddleware())
160
163
  .use((0, middlewares_1.prometheusLoggerMiddleware)())
161
164
  .use((0, tracingMiddlewares_1.addTracingMiddleware)(tracer))
162
165
  .use((0, requestMetricsMiddleware_1.addRequestMetricsMiddleware)())
166
+ .use((0, otelRequestMetricsMiddleware_1.addOtelRequestMetricsMiddleware)())
163
167
  .use((0, middlewares_1.addMetricsLoggerMiddleware)())
164
168
  .use((0, rateLimit_1.concurrentRateLimiter)((_a = serviceJSON === null || serviceJSON === void 0 ? void 0 : serviceJSON.rateLimitPerReplica) === null || _a === void 0 ? void 0 : _a.concurrent))
165
169
  .use((0, koa_compress_1.default)())
@@ -190,8 +194,8 @@ const startWorker = (serviceJSON) => {
190
194
  const privateHandlersRouter = routerFromPrivateHttpHandlers(httpHandlers.pvt);
191
195
  app.use(privateHandlersRouter.routes());
192
196
  }
197
+ global.metrics = new MetricsAccumulator_1.MetricsAccumulator();
193
198
  process.on('message', onMessage(serviceJSON));
194
199
  return app;
195
200
  };
196
201
  exports.startWorker = startWorker;
197
- global.metrics = new MetricsAccumulator_1.MetricsAccumulator();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vtex/api",
3
- "version": "7.1.0",
3
+ "version": "7.2.1-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,13 @@
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-io-beta.19",
56
+ "@vtex/diagnostics-nodejs": "0.1.0-io-beta.20",
53
57
  "@vtex/node-error-report": "^0.0.3",
54
58
  "@wry/equality": "^0.1.9",
55
59
  "agentkeepalive": "^4.0.2",