diff --git a/package.json b/package.json index c58e25199..901bfd7f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@vtex/api", - "version": "6.49.7", + "version": "6.49.8-beta.2", "description": "VTEX I/O API client", "main": "lib/index.js", "typings": "lib/index.d.ts", @@ -47,9 +47,13 @@ }, "license": "MIT", "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/host-metrics": "0.35.5", + "@opentelemetry/instrumentation": "0.57.2", + "@opentelemetry/instrumentation-koa": "0.47.1", "@types/koa": "^2.11.0", "@types/koa-compose": "^3.2.3", - "@vtex/diagnostics-nodejs": "0.1.0-beta.10", + "@vtex/diagnostics-nodejs": "0.1.0-io-beta.19", "@vtex/node-error-report": "^0.0.3", "@wry/equality": "^0.1.9", "agentkeepalive": "^4.0.2", @@ -124,5 +128,8 @@ "typemoq": "^2.1.0", "typescript": "^4.4.4", "typescript-json-schema": "^0.52.0" + }, + "resolutions": { + "@grpc/grpc-js": "^1.13.4" } } diff --git a/src/service/index.ts b/src/service/index.ts index 190150df7..fd5a8373d 100644 --- a/src/service/index.ts +++ b/src/service/index.ts @@ -1,20 +1,23 @@ +import { initializeTelemetry } from './telemetry' import cluster from 'cluster' import { HTTP_SERVER_PORT } from '../constants' import { getServiceJSON } from './loaders' import { LogLevel, logOnceToDevConsole } from './logger' -import { startMaster } from './master' -import { startWorker } from './worker' -export const startApp = () => { +export const startApp = async () => { + await initializeTelemetry() const serviceJSON = getServiceJSON() try { // if it is a master process then call setting up worker process if(cluster.isMaster) { + const { startMaster } = await import('./master') startMaster(serviceJSON) } else { // to setup server configurations and share port address for incoming requests - startWorker(serviceJSON).listen(HTTP_SERVER_PORT) + const { startWorker } = await import('./worker') + const app = await startWorker(serviceJSON) + app.listen(HTTP_SERVER_PORT) } } catch (err: any) { logOnceToDevConsole(err.stack || err.message, LogLevel.Error) diff --git a/src/service/logger/client.ts b/src/service/logger/client.ts index 1850d7a5d..c307d89b7 100644 --- a/src/service/logger/client.ts +++ b/src/service/logger/client.ts @@ -1,15 +1,14 @@ -import { Exporters } from '@vtex/diagnostics-nodejs'; -import { LogClient } from '@vtex/diagnostics-nodejs/dist/types'; -import { getTelemetryClient } from '../telemetry'; +import { Types } from '@vtex/diagnostics-nodejs'; +import { initializeTelemetry } from '../telemetry'; -let logClient: LogClient | undefined; +let client: Types.LogClient | undefined; let isInitializing = false; -let initPromise: Promise | undefined = undefined; +let initPromise: Promise | undefined = undefined; -export async function getLogClient(account: string, workspace: string, appName: string): Promise { +export async function getLogClient(): Promise { - if (logClient) { - return logClient; + if (client) { + return client; } if (initPromise) { @@ -17,36 +16,20 @@ export async function getLogClient(account: string, workspace: string, appName: } isInitializing = true; - initPromise = initializeClient(account, workspace, appName); + initPromise = initializeClient(); return initPromise; } -async function initializeClient(account: string, workspace: string, appName: string): Promise { +async function initializeClient(): Promise { try { - const telemetryClient = await getTelemetryClient(); - - const logsConfig = Exporters.CreateLogsExporterConfig({ - endpoint: process.env.OTEL_EXPORTER_OTLP_ENDPOINT, - path: process.env.OTEL_EXPORTER_OTLP_PATH || '/v1/logs', - protocol: 'http', - interval: 5, - timeoutSeconds: 5, - headers: { 'Content-Type': 'application/json' }, - }); - - const logsExporter = Exporters.CreateExporter(logsConfig, 'otlp'); - await logsExporter.initialize(); - - const clientKey = `${account}-${workspace}-${appName}`; - logClient = await telemetryClient.newLogsClient({ - exporter: logsExporter, - loggerName: `node-vtex-api-${clientKey}`, - }); - - return logClient; + const { logsClient } = await initializeTelemetry(); + client = logsClient; + initPromise = undefined; + return logsClient; } catch (error) { console.error('Failed to initialize logs client:', error); + initPromise = undefined; throw error; } finally { isInitializing = false; diff --git a/src/service/logger/logger.ts b/src/service/logger/logger.ts index 06a467f05..1441fb55e 100644 --- a/src/service/logger/logger.ts +++ b/src/service/logger/logger.ts @@ -1,7 +1,7 @@ import { APP, LOG_CLIENT_INIT_TIMEOUT_MS } from '../../constants' import { cleanError } from '../../utils/error' import { cleanLog } from '../../utils/log' -import { LogClient } from '@vtex/diagnostics-nodejs/dist/types'; +import { Types } from '@vtex/diagnostics-nodejs'; import { LoggerContext, LogLevel, TracingState } from './loggerTypes' import { getLogClient } from './client' @@ -15,8 +15,8 @@ export class Logger { private requestId: string private production: boolean private tracingState?: TracingState - private logClient: LogClient | undefined = undefined - private clientInitPromise: Promise | undefined = undefined + private logClient: Types.LogClient | undefined = undefined + private clientInitPromise: Promise | undefined = undefined constructor(ctx: LoggerContext) { this.account = ctx.account @@ -35,7 +35,7 @@ export class Logger { // this.initLogClient(); } - private initLogClient(): Promise { + private initLogClient(): Promise { if (this.clientInitPromise) { return this.clientInitPromise; } @@ -47,7 +47,7 @@ export class Logger { }); this.logClient = await Promise.race([ - getLogClient(this.account, this.workspace, APP.NAME), + getLogClient(), timeoutPromise ]); diff --git a/src/service/metrics/client.ts b/src/service/metrics/client.ts new file mode 100644 index 000000000..e45eb5376 --- /dev/null +++ b/src/service/metrics/client.ts @@ -0,0 +1,35 @@ +import { Types } from "@vtex/diagnostics-nodejs"; +import { initializeTelemetry } from '../telemetry'; + +let client: Types.MetricClient | undefined; +let isInitializing = false; +let initPromise: Promise | undefined = undefined; + +export async function getMetricClient(): Promise { + if (client) { + return client; + } + + if (initPromise) { + return initPromise; + } + + isInitializing = true; + initPromise = initializeClient(); + + return initPromise; +} +async function initializeClient(): Promise { + try { + const { metricsClient } = await initializeTelemetry(); + client = metricsClient; + initPromise = undefined; + return metricsClient; + } catch (error) { + console.error('Failed to initialize metrics client:', error); + initPromise = undefined; + throw error; + } finally { + isInitializing = false; + } +} diff --git a/src/service/metrics/instruments/hostMetrics.ts b/src/service/metrics/instruments/hostMetrics.ts new file mode 100644 index 000000000..0851c1096 --- /dev/null +++ b/src/service/metrics/instruments/hostMetrics.ts @@ -0,0 +1,41 @@ +import { InstrumentationBase, InstrumentationConfig } from "@opentelemetry/instrumentation"; +import { MeterProvider } from '@opentelemetry/api'; +import { HostMetrics } from "@opentelemetry/host-metrics"; + +interface HostMetricsInstrumentationConfig extends InstrumentationConfig { + name?: string; + meterProvider?: MeterProvider; +} + +export class HostMetricsInstrumentation extends InstrumentationBase { + private hostMetrics?: HostMetrics; + + constructor(config: HostMetricsInstrumentationConfig = {}) { + const instrumentation_name = config.name || 'host-metrics-instrumentation'; + const instrumentation_version = '1.0.0'; + super(instrumentation_name, instrumentation_version, config); + } + + init(): void {} + + enable(): void { + if (!this._config.meterProvider) { + throw new Error('MeterProvider is required for HostMetricsInstrumentation'); + } + + this.hostMetrics = new HostMetrics({ + meterProvider: this._config.meterProvider, + name: this._config.name || 'host-metrics', + }); + + this.hostMetrics.start(); + console.debug('HostMetricsInstrumentation enabled'); + } + + disable(): void { + if (this.hostMetrics) { + this.hostMetrics = undefined; + console.debug('HostMetricsInstrumentation disabled'); + } + } +} diff --git a/src/service/metrics/metrics.ts b/src/service/metrics/metrics.ts new file mode 100644 index 000000000..1c6f561f9 --- /dev/null +++ b/src/service/metrics/metrics.ts @@ -0,0 +1,101 @@ +import { Types } from '@vtex/diagnostics-nodejs' +import { getMetricClient } from './client' + +export const enum RequestsMetricLabels { + STATUS_CODE = 'status_code', + REQUEST_HANDLER = 'handler', +} + +export interface OtelRequestInstruments { + concurrentRequests: Types.Gauge + requestTimings: Types.Histogram + totalRequests: Types.Counter + responseSizes: Types.Histogram + abortedRequests: Types.Counter +} + +let instruments: OtelRequestInstruments | undefined +let initializingPromise: Promise | undefined + +const createOtelConcurrentRequestsInstrument = async (): Promise => { + const metricsClient = await getMetricClient() + return metricsClient.createGauge('io_http_requests_current', { + description: 'The current number of requests in course.', + unit: '1' + }) +} + +const createOtelRequestsTimingsInstrument = async (): Promise => { + const metricsClient = await getMetricClient() + return metricsClient.createHistogram('runtime_http_requests_duration_milliseconds', { + description: 'The incoming http requests total duration.', + unit: 'ms' + }) +} + +const createOtelTotalRequestsInstrument = async (): Promise => { + const metricsClient = await getMetricClient() + return metricsClient.createCounter('runtime_http_requests_total', { + description: 'The total number of HTTP requests.', + unit: '1' + }) +} + +const createOtelRequestsResponseSizesInstrument = async (): Promise => { + const metricsClient = await getMetricClient() + return metricsClient.createHistogram('runtime_http_response_size_bytes', { + description: 'The outgoing response sizes (only applicable when the response isn\'t a stream).', + unit: 'bytes' + }) +} + +const createOtelTotalAbortedRequestsInstrument = async (): Promise => { + const metricsClient = await getMetricClient() + return metricsClient.createCounter('runtime_http_aborted_requests_total', { + description: 'The total number of HTTP requests aborted.', + unit: '1' + }) +} + +export const getOtelInstruments = async (): Promise => { + if (instruments) { + return instruments + } + + if (initializingPromise) { + return initializingPromise + } + + initializingPromise = initializeOtelInstruments() + + try { + instruments = await initializingPromise + return instruments + } finally { + initializingPromise = undefined + } +} + +const initializeOtelInstruments = async (): Promise => { + const [ + concurrentRequests, + requestTimings, + totalRequests, + responseSizes, + abortedRequests + ] = await Promise.all([ + createOtelConcurrentRequestsInstrument(), + createOtelRequestsTimingsInstrument(), + createOtelTotalRequestsInstrument(), + createOtelRequestsResponseSizesInstrument(), + createOtelTotalAbortedRequestsInstrument() + ]) + + return { + concurrentRequests, + requestTimings, + totalRequests, + responseSizes, + abortedRequests + } +} diff --git a/src/service/metrics/otelRequestMetricsMiddleware.ts b/src/service/metrics/otelRequestMetricsMiddleware.ts new file mode 100644 index 000000000..d62da9469 --- /dev/null +++ b/src/service/metrics/otelRequestMetricsMiddleware.ts @@ -0,0 +1,82 @@ +import { finished as onStreamFinished } from 'stream' +import { hrToMillisFloat } from '../../utils' +import { getOtelInstruments, RequestsMetricLabels, OtelRequestInstruments } from './metrics' +import { ServiceContext } from '../worker/runtime/typings' + +const INSTRUMENTS_INITIALIZATION_TIMEOUT = 500 + +export const addOtelRequestMetricsMiddleware = () => { + let instruments: OtelRequestInstruments | undefined + + return async function addOtelRequestMetrics(ctx: ServiceContext, next: () => Promise) { + if (!instruments) { + try { + instruments = await Promise.race([ + getOtelInstruments(), + new Promise((_, reject) => + setTimeout(() => reject(new Error('Timeout waiting for OpenTelemetry instruments initialization')), + INSTRUMENTS_INITIALIZATION_TIMEOUT) + ) + ]) + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + console.warn(`OpenTelemetry instruments not ready for request ${ctx.requestHandlerName}: ${errorMessage}`) + await next() + return + } + } + + const start = process.hrtime() + instruments.concurrentRequests.add(1) + + ctx.req.once('aborted', () => { + if (instruments) { + instruments.abortedRequests.add(1, { [RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName }) + } + }) + + let responseClosed = false + ctx.res.once('close', () => (responseClosed = true)) + + try { + await next() + } finally { + const responseLength = ctx.response.length + if (responseLength && instruments) { + instruments.responseSizes.record( + responseLength, + { [RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName } + ) + } + + if (instruments) { + instruments.totalRequests.add( + 1, + { + [RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName, + [RequestsMetricLabels.STATUS_CODE]: ctx.response.status, + } + ) + } + + const onResFinished = () => { + if (instruments) { + instruments.requestTimings.record( + hrToMillisFloat(process.hrtime(start)), + { + [RequestsMetricLabels.REQUEST_HANDLER]: ctx.requestHandlerName, + } + ) + + instruments.concurrentRequests.subtract(1) + } + } + + if (responseClosed) { + onResFinished() + } else { + onStreamFinished(ctx.res, onResFinished) + } + } + } +} diff --git a/src/service/telemetry/client.ts b/src/service/telemetry/client.ts index efe704d78..db42e276d 100644 --- a/src/service/telemetry/client.ts +++ b/src/service/telemetry/client.ts @@ -1,11 +1,30 @@ -import { NewTelemetryClient } from '@vtex/diagnostics-nodejs'; -import { TelemetryClient } from '@vtex/diagnostics-nodejs/dist/telemetry'; +import { + NewTelemetryClient, + Instrumentation, + Exporters, + Logs, + Metrics, + Traces, +} from '@vtex/diagnostics-nodejs'; import { APP } from '../../constants'; +import { TelemetryClient } from '@vtex/diagnostics-nodejs/dist/telemetry'; +import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa'; +import { HostMetricsInstrumentation } from '../metrics/instruments/hostMetrics'; + +const CLIENT_NAME = APP.NAME || 'node-vtex-api'; +const APPLICATION_ID = APP.ID || 'vtex-io-app'; +const EXPORTER_OTLP_ENDPOINT = process.env.EXPORTER_OTLP_ENDPOINT; + +interface TelemetryClients { + logsClient: Logs.LogClient; + metricsClient: Metrics.MetricsClient; + tracesClient: Traces.TraceClient; +} class TelemetryClientSingleton { private static instance: TelemetryClientSingleton; - private telemetryClient: TelemetryClient | undefined; - private initializationPromise: Promise | undefined = undefined; + private telemetryClients: TelemetryClients | undefined; + private initializationPromise: Promise | undefined = undefined; private constructor() {} @@ -16,11 +35,36 @@ class TelemetryClientSingleton { return TelemetryClientSingleton.instance; } - private async initTelemetryClient(): Promise { + private initializeTracesClient = async (telemetryClient: TelemetryClient) => + await telemetryClient.newTracesClient({ + exporter: Exporters.CreateExporter(Exporters.CreateTracesExporterConfig({ + endpoint: EXPORTER_OTLP_ENDPOINT, + }), 'otlp'), + }); + + private initializeMetricsClient = async (telemetryClient: TelemetryClient) => + await telemetryClient.newMetricsClient({ + exporter: Exporters.CreateExporter(Exporters.CreateMetricsExporterConfig({ + endpoint: EXPORTER_OTLP_ENDPOINT, + interval: 5, + timeoutSeconds: 5, + }), 'otlp'), + }); + + private initializeLogsClient = async (telemetryClient: TelemetryClient) => + await telemetryClient.newLogsClient({ + exporter: Exporters.CreateExporter(Exporters.CreateLogsExporterConfig({ + endpoint: EXPORTER_OTLP_ENDPOINT, + }), 'otlp'), + loggerName: `node-vtex-api-${APPLICATION_ID}`, + }); + + private async initializeTelemetryClients(): Promise { try { const telemetryClient = await NewTelemetryClient( + APPLICATION_ID, + CLIENT_NAME, 'node-vtex-api', - APP.ID || 'vtex-app', { additionalAttrs: { 'version': APP.VERSION || '', @@ -29,41 +73,62 @@ class TelemetryClientSingleton { } ); - this.telemetryClient = telemetryClient; - return telemetryClient; + const [tracesClient, metricsClient, logsClient] = await Promise.all([ + this.initializeTracesClient(telemetryClient), + this.initializeMetricsClient(telemetryClient), + this.initializeLogsClient(telemetryClient), + ]); + + const instrumentations = [ + ...Instrumentation.CommonInstrumentations.minimal(), + new KoaInstrumentation(), + new HostMetricsInstrumentation({ + name: 'host-metrics-instrumentation', + meterProvider: metricsClient.provider(), + }), + ]; + + telemetryClient.registerInstrumentations(instrumentations); + + const clients: TelemetryClients = { + logsClient, + metricsClient, + tracesClient, + }; + + this.telemetryClients = clients; + return clients; } catch (error) { - console.error('Failed to initialize telemetry client:', error); + console.error('Failed to initialize telemetry clients:', error); throw error; } finally { this.initializationPromise = undefined; } } - public async getClient(): Promise { - if (this.telemetryClient) { - return this.telemetryClient; + public async getTelemetryClients(): Promise { + if (this.telemetryClients) { + return this.telemetryClients; } if (this.initializationPromise) { return this.initializationPromise; } - this.initializationPromise = this.initTelemetryClient(); - + this.initializationPromise = this.initializeTelemetryClients(); return this.initializationPromise; } public reset(): void { - this.telemetryClient = undefined; + this.telemetryClients = undefined; this.initializationPromise = undefined; } - } -export async function getTelemetryClient(): Promise { - return TelemetryClientSingleton.getInstance().getClient(); +export async function initializeTelemetry(): Promise { + return TelemetryClientSingleton.getInstance().getTelemetryClients(); } -export function resetTelemetryClient(): void { +export function resetTelemetry(): void { TelemetryClientSingleton.getInstance().reset(); } diff --git a/src/service/worker/index.ts b/src/service/worker/index.ts index 420e10ff1..0e64fcf29 100644 --- a/src/service/worker/index.ts +++ b/src/service/worker/index.ts @@ -1,3 +1,4 @@ +import { Instrumentation } from '@vtex/diagnostics-nodejs'; import { request } from 'http' import Koa from 'koa' import compress from 'koa-compress' @@ -13,6 +14,7 @@ import { getService } from '../loaders' import { logOnceToDevConsole } from '../logger/console' import { LogLevel } from '../logger/loggerTypes' import { addRequestMetricsMiddleware } from '../metrics/requestMetricsMiddleware' +import { addOtelRequestMetricsMiddleware } from '../metrics/otelRequestMetricsMiddleware' import { TracerSingleton } from '../tracing/TracerSingleton' import { addTracingMiddleware } from '../tracing/tracingMiddlewares' import { addProcessListeners, logger } from './listeners' @@ -220,9 +222,11 @@ export const startWorker = (serviceJSON: ServiceJSON) => { app.proxy = true app .use(error) + .use(Instrumentation.Middlewares.ContextMiddlewares.Koa.ContextPropagationMiddleware()) .use(prometheusLoggerMiddleware()) .use(addTracingMiddleware(tracer)) .use(addRequestMetricsMiddleware()) + .use(addOtelRequestMetricsMiddleware()) .use(addMetricsLoggerMiddleware()) .use(concurrentRateLimiter(serviceJSON?.rateLimitPerReplica?.concurrent)) .use(compress()) diff --git a/yarn.lock b/yarn.lock index 7754ea1ab..2c6b71c67 100644 --- a/yarn.lock +++ b/yarn.lock @@ -236,10 +236,10 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@grpc/grpc-js@^1.7.1": - version "1.13.3" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.13.3.tgz#6ad08d186c2a8651697085f790c5c68eaca45904" - integrity sha512-FTXHdOoPbZrBjlVLHuKbDZnsTxXv2BlHF57xw6LuThXacXvtkahEPED0CKMk6obZDf65Hv4k3z62eyPNpvinIg== +"@grpc/grpc-js@^1.13.4", "@grpc/grpc-js@^1.7.1": + version "1.13.4" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.13.4.tgz#922fbc496e229c5fa66802d2369bf181c1df1c5a" + integrity sha512-GsFaMXCkMqkKIvwCQjCrwH+GHbPKBjhwo/8ZuUkWHqbI73Kky9I+pQltrlT0+MWpedCoosda53lgjYfyEPgxBg== dependencies: "@grpc/proto-loader" "^0.7.13" "@js-sdsl/ordered-map" "^4.4.2" @@ -470,12 +470,19 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== -"@opentelemetry/context-async-hooks@1.30.1": +"@opentelemetry/baggage-span-processor@^0.3.1": + version "0.3.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/baggage-span-processor/-/baggage-span-processor-0.3.1.tgz#8bca006ad0ca5e43d452a615ac2469a09cab7711" + integrity sha512-m4XXch3/NraA0XEogdQgdMbhg0ZWQWnwXRxuWZJLskIFvIatvUZwoWZm+8gApEZNJNz/Jk/dwtMylUQZBwcyYA== + dependencies: + "@opentelemetry/sdk-trace-base" "^1.0.0" + +"@opentelemetry/context-async-hooks@1.30.1", "@opentelemetry/context-async-hooks@^1.30.1": version "1.30.1" resolved "https://registry.yarnpkg.com/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz#4f76280691a742597fd0bf682982126857622948" integrity sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA== -"@opentelemetry/core@1.30.1", "@opentelemetry/core@^1.0.0", "@opentelemetry/core@^1.30.1": +"@opentelemetry/core@1.30.1", "@opentelemetry/core@^1.0.0", "@opentelemetry/core@^1.30.1", "@opentelemetry/core@^1.8.0": version "1.30.1" resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.30.1.tgz#a0b468bb396358df801881709ea38299fc30ab27" integrity sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ== @@ -494,7 +501,7 @@ "@opentelemetry/otlp-transformer" "0.57.2" "@opentelemetry/sdk-logs" "0.57.2" -"@opentelemetry/exporter-logs-otlp-http@0.57.2", "@opentelemetry/exporter-logs-otlp-http@^0.57.2": +"@opentelemetry/exporter-logs-otlp-http@0.57.2": version "0.57.2" resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-logs-otlp-http/-/exporter-logs-otlp-http-0.57.2.tgz#01d4668b8f781540f94592da9284b92fd6a2ccd8" integrity sha512-0rygmvLcehBRp56NQVLSleJ5ITTduq/QfU7obOkyWgPpFHulwpw2LYTqNIz5TczKZuy5YY+5D3SDnXZL1tXImg== @@ -532,7 +539,7 @@ "@opentelemetry/resources" "1.30.1" "@opentelemetry/sdk-metrics" "1.30.1" -"@opentelemetry/exporter-metrics-otlp-http@0.57.2", "@opentelemetry/exporter-metrics-otlp-http@^0.57.2": +"@opentelemetry/exporter-metrics-otlp-http@0.57.2": version "0.57.2" resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-metrics-otlp-http/-/exporter-metrics-otlp-http-0.57.2.tgz#0983b28a4a36dee3af2c258394214004e4c68b53" integrity sha512-ttb9+4iKw04IMubjm3t0EZsYRNWr3kg44uUuzfo9CaccYlOh8cDooe4QObDUkvx9d5qQUrbEckhrWKfJnKhemA== @@ -577,7 +584,7 @@ "@opentelemetry/resources" "1.30.1" "@opentelemetry/sdk-trace-base" "1.30.1" -"@opentelemetry/exporter-trace-otlp-http@0.57.2", "@opentelemetry/exporter-trace-otlp-http@^0.57.2": +"@opentelemetry/exporter-trace-otlp-http@0.57.2": version "0.57.2" resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.57.2.tgz#0ab8e97dc30dbabb8252b68128b80c4685f7c691" integrity sha512-sB/gkSYFu+0w2dVQ0PWY9fAMl172PKMZ/JrHkkW8dmjCL0CYkmXeE+ssqIL/yBUTPOvpLIpenX5T9RwXRBW/3g== @@ -609,6 +616,22 @@ "@opentelemetry/sdk-trace-base" "1.30.1" "@opentelemetry/semantic-conventions" "1.28.0" +"@opentelemetry/host-metrics@0.35.5": + version "0.35.5" + resolved "https://registry.yarnpkg.com/@opentelemetry/host-metrics/-/host-metrics-0.35.5.tgz#1bb7453558b2623c8331d0fea5b7766c995a68f1" + integrity sha512-Zf9Cjl7H6JalspnK5KD1+LLKSVecSinouVctNmUxRy+WP+20KwHq+qg4hADllkEmJ99MZByLLmEmzrr7s92V6g== + dependencies: + systeminformation "5.23.8" + +"@opentelemetry/instrumentation-express@^0.47.1": + version "0.47.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-express/-/instrumentation-express-0.47.1.tgz#7cf74f35e43cc3c8186edd1249fdb225849c48b2" + integrity sha512-QNXPTWteDclR2B4pDFpz0TNghgB33UMjUt14B+BZPmtH1MwUFAfLHBaP5If0Z5NZC+jaH8oF2glgYjrmhZWmSw== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.57.1" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-http@^0.57.2": version "0.57.2" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-http/-/instrumentation-http-0.57.2.tgz#f425eda67b6241c3abe08e4ea972169b85ef3064" @@ -620,6 +643,15 @@ forwarded-parse "2.1.2" semver "^7.5.2" +"@opentelemetry/instrumentation-koa@0.47.1": + version "0.47.1" + resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.47.1.tgz#ba57eccd44a75ec59e3129757fda4e8c8dd7ce2c" + integrity sha512-l/c+Z9F86cOiPJUllUCt09v+kICKvT+Vg1vOAJHtHPsJIzurGayucfCMq2acd/A/yxeNWunl9d9eqZ0G+XiI6A== + dependencies: + "@opentelemetry/core" "^1.8.0" + "@opentelemetry/instrumentation" "^0.57.1" + "@opentelemetry/semantic-conventions" "^1.27.0" + "@opentelemetry/instrumentation-net@^0.43.1": version "0.43.1" resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation-net/-/instrumentation-net-0.43.1.tgz#10a3030fe090ed76204ac025179501f902dcf282" @@ -745,7 +777,7 @@ "@opentelemetry/sdk-trace-node" "1.30.1" "@opentelemetry/semantic-conventions" "1.28.0" -"@opentelemetry/sdk-trace-base@1.30.1", "@opentelemetry/sdk-trace-base@^1.30.1": +"@opentelemetry/sdk-trace-base@1.30.1", "@opentelemetry/sdk-trace-base@^1.0.0", "@opentelemetry/sdk-trace-base@^1.30.1": version "1.30.1" resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz#41a42234096dc98e8f454d24551fc80b816feb34" integrity sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg== @@ -1219,21 +1251,22 @@ dependencies: "@types/yargs-parser" "*" -"@vtex/diagnostics-nodejs@0.1.0-beta.10": - version "0.1.0-beta.10" - resolved "https://registry.yarnpkg.com/@vtex/diagnostics-nodejs/-/diagnostics-nodejs-0.1.0-beta.10.tgz#af255418c0777bf49d02f1e650d654d20f11e513" - integrity sha512-w5IOo+P1RcGXYZZw5RV4guQFIKpIqmq7reEQRx6qJYDh0RwLFFhr7NS8MNGm792xOs59hyYMulhx8FMmcOXVxA== +"@vtex/diagnostics-nodejs@0.1.0-io-beta.19": + version "0.1.0-io-beta.19" + resolved "https://registry.yarnpkg.com/@vtex/diagnostics-nodejs/-/diagnostics-nodejs-0.1.0-io-beta.19.tgz#e8ebc6a0b44014d0ffcda9df736291c52604ee9e" + integrity sha512-p3bcfpCI12k1DXqD2wJvO53dDdrULYsK7muJFHlwiZio4WvnSfPU1Ay5ni9Y8alD/MLX4fP4EEjRYXTGc7wFWQ== dependencies: + "@grpc/grpc-js" "^1.13.4" "@opentelemetry/api" "^1.9.0" "@opentelemetry/api-logs" "^0.200.0" + "@opentelemetry/baggage-span-processor" "^0.3.1" + "@opentelemetry/context-async-hooks" "^1.30.1" "@opentelemetry/core" "^1.30.1" "@opentelemetry/exporter-logs-otlp-grpc" "^0.57.2" - "@opentelemetry/exporter-logs-otlp-http" "^0.57.2" "@opentelemetry/exporter-metrics-otlp-grpc" "^0.57.2" - "@opentelemetry/exporter-metrics-otlp-http" "^0.57.2" "@opentelemetry/exporter-trace-otlp-grpc" "^0.57.2" - "@opentelemetry/exporter-trace-otlp-http" "^0.57.2" "@opentelemetry/instrumentation" "^0.57.2" + "@opentelemetry/instrumentation-express" "^0.47.1" "@opentelemetry/instrumentation-http" "^0.57.2" "@opentelemetry/instrumentation-net" "^0.43.1" "@opentelemetry/propagator-b3" "^1.30.1" @@ -1245,14 +1278,14 @@ "@opentelemetry/sdk-trace-base" "^1.30.1" "@opentelemetry/sdk-trace-node" "^1.30.1" "@opentelemetry/semantic-conventions" "^1.30.0" - "@vtex/diagnostics-semconv" "0.1.0-beta.10" + "@vtex/diagnostics-semconv" "0.1.0-beta.11" tslib "^2.8.1" uuid "^11.1.0" -"@vtex/diagnostics-semconv@0.1.0-beta.10": - version "0.1.0-beta.10" - resolved "https://registry.yarnpkg.com/@vtex/diagnostics-semconv/-/diagnostics-semconv-0.1.0-beta.10.tgz#f5b6aa4444cbb4bc1fb0c9e38ca52594d9c2b939" - integrity sha512-a5D8tlBJjBqJBTPsbm3la4gy6hiduWyTTWzjOqoICdgsmCNB9E8mw6NcloEMkBILQ7n8X3EDfXZvkea6OILibQ== +"@vtex/diagnostics-semconv@0.1.0-beta.11": + version "0.1.0-beta.11" + resolved "https://registry.yarnpkg.com/@vtex/diagnostics-semconv/-/diagnostics-semconv-0.1.0-beta.11.tgz#2ddfff7dffdc1c052d23b335f914de91653d9659" + integrity sha512-H3KM5fYAFmcxhlA4wT5iPgWJtgKsumFqGkkxjcA/BSwC5tgSWezN82sZDKvBsVo24EoZxVGgLlsjNw1tsp9U3Q== "@vtex/node-error-report@^0.0.3": version "0.0.3" @@ -5128,6 +5161,11 @@ symbol-tree@^3.2.2: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +systeminformation@5.23.8: + version "5.23.8" + resolved "https://registry.yarnpkg.com/systeminformation/-/systeminformation-5.23.8.tgz#b8efa73b36221cbcb432e3fe83dc1878a43f986a" + integrity sha512-Osd24mNKe6jr/YoXLLK3k8TMdzaxDffhpCxgkfgBHcapykIkd50HXThM3TCEuHO2pPuCsSx2ms/SunqhU5MmsQ== + tar-fs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad"