diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/package.json b/aws-distro-opentelemetry-node-autoinstrumentation/package.json index 632ce527..16382efc 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/package.json +++ b/aws-distro-opentelemetry-node-autoinstrumentation/package.json @@ -40,7 +40,8 @@ "src/**/*.ts" ], "exclude": [ - "src/third-party/**/*.ts" + "src/third-party/**/*.ts", + "src/otlp-aws-span-exporter.ts" ] }, "bugs": { @@ -79,13 +80,17 @@ "@aws-sdk/client-sfn": "^3.632.0", "@aws-sdk/client-sns": "^3.632.0", "@opentelemetry/contrib-test-utils": "0.41.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", "@types/mocha": "7.0.2", "@types/node": "18.6.5", + "@types/proxyquire": "^1.3.31", "@types/sinon": "10.0.18", "expect": "29.2.0", "mocha": "7.2.0", "nock": "13.2.1", "nyc": "15.1.0", + "proxyquire": "^2.1.3", "rimraf": "5.0.5", "sinon": "15.2.0", "ts-mocha": "10.0.0", diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-opentelemetry-configurator.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-opentelemetry-configurator.ts index 6a6a797b..15180552 100644 --- a/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-opentelemetry-configurator.ts +++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/aws-opentelemetry-configurator.ts @@ -56,11 +56,14 @@ import { AttributePropagatingSpanProcessorBuilder } from './attribute-propagatin import { AwsBatchUnsampledSpanProcessor } from './aws-batch-unsampled-span-processor'; import { AwsMetricAttributesSpanExporterBuilder } from './aws-metric-attributes-span-exporter-builder'; import { AwsSpanMetricsProcessorBuilder } from './aws-span-metrics-processor-builder'; +import { OTLPAwsSpanExporter } from './otlp-aws-span-exporter'; import { OTLPUdpSpanExporter } from './otlp-udp-exporter'; import { AwsXRayRemoteSampler } from './sampler/aws-xray-remote-sampler'; // This file is generated via `npm run compile` import { LIB_VERSION } from './version'; +const XRAY_OTLP_ENDPOINT_PATTERN = '^https://xray\\.([a-z0-9-]+)\\.amazonaws\\.com/v1/traces$'; + const APPLICATION_SIGNALS_ENABLED_CONFIG: string = 'OTEL_AWS_APPLICATION_SIGNALS_ENABLED'; const APPLICATION_SIGNALS_EXPORTER_ENDPOINT_CONFIG: string = 'OTEL_AWS_APPLICATION_SIGNALS_EXPORTER_ENDPOINT'; const METRIC_EXPORT_INTERVAL_CONFIG: string = 'OTEL_METRIC_EXPORT_INTERVAL'; @@ -235,6 +238,11 @@ export class AwsOpentelemetryConfigurator { } spanProcessors.push(AttributePropagatingSpanProcessorBuilder.create().build()); + + if (isXrayOtlpEndpoint(process.env['OTEL_EXPORTER_OTLP_TRACES_ENDPOINT'])) { + return; + } + const applicationSignalsMetricExporter: PushMetricExporter = ApplicationSignalsExporterProvider.Instance.createExporter(); const periodicExportingMetricReader: PeriodicExportingMetricReader = new PeriodicExportingMetricReader({ @@ -422,6 +430,7 @@ export class AwsSpanProcessorProvider { private resource: Resource; static configureOtlp(): SpanExporter { + const otlp_exporter_traces_endpoint = process.env['OTEL_EXPORTER_OTLP_TRACES_ENDPOINT']; // eslint-disable-next-line @typescript-eslint/typedef let protocol = this.getOtlpProtocol(); @@ -438,12 +447,18 @@ export class AwsSpanProcessorProvider { case 'http/json': return new OTLPHttpTraceExporter(); case 'http/protobuf': + if (otlp_exporter_traces_endpoint && isXrayOtlpEndpoint(otlp_exporter_traces_endpoint)) { + return new OTLPAwsSpanExporter(otlp_exporter_traces_endpoint); + } return new OTLPProtoTraceExporter(); case 'udp': diag.debug('Detected AWS Lambda environment and enabling UDPSpanExporter'); return new OTLPUdpSpanExporter(getXrayDaemonEndpoint(), FORMAT_OTEL_SAMPLED_TRACES_BINARY_PREFIX); default: diag.warn(`Unsupported OTLP traces protocol: ${protocol}. Using http/protobuf.`); + if (otlp_exporter_traces_endpoint && isXrayOtlpEndpoint(otlp_exporter_traces_endpoint)) { + return new OTLPAwsSpanExporter(otlp_exporter_traces_endpoint); + } return new OTLPProtoTraceExporter(); } } @@ -652,4 +667,8 @@ function getXrayDaemonEndpoint() { return process.env[AWS_XRAY_DAEMON_ADDRESS_CONFIG]; } +function isXrayOtlpEndpoint(otlpEndpoint: string | undefined) { + return otlpEndpoint && new RegExp(XRAY_OTLP_ENDPOINT_PATTERN).test(otlpEndpoint.toLowerCase()); +} + // END The OpenTelemetry Authors code diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/otlp-aws-span-exporter.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/otlp-aws-span-exporter.ts new file mode 100644 index 00000000..e3b5d591 --- /dev/null +++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/otlp-aws-span-exporter.ts @@ -0,0 +1,129 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import { OTLPTraceExporter as OTLPProtoTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto'; +import { diag } from '@opentelemetry/api'; +import { OTLPExporterNodeConfigBase } from '@opentelemetry/otlp-exporter-base'; +import { ProtobufTraceSerializer } from '@opentelemetry/otlp-transformer'; +import { ReadableSpan } from '@opentelemetry/sdk-trace-base'; +import { ExportResult } from '@opentelemetry/core'; +import { getNodeVersion } from './utils'; + +/** + * This exporter extends the functionality of the OTLPProtoTraceExporter to allow spans to be exported + * to the XRay OTLP endpoint https://xray.[AWSRegion].amazonaws.com/v1/traces. Utilizes the aws-sdk + * library to sign and directly inject SigV4 Authentication to the exported request's headers. ... + * + * This only works with version >=16 Node.js environments. + */ +export class OTLPAwsSpanExporter extends OTLPProtoTraceExporter { + private static readonly SERVICE_NAME: string = 'xray'; + private endpoint: string; + private region: string; + + // Holds the dependencies needed to sign the SigV4 headers + private defaultProvider: any; + private sha256: any; + private signatureV4: any; + private httpRequest: any; + + // If the required dependencies are installed then we enable SigV4 signing. Otherwise skip it + private hasRequiredDependencies: boolean = false; + + constructor(endpoint: string, config?: OTLPExporterNodeConfigBase) { + super(OTLPAwsSpanExporter.changeUrlConfig(endpoint, config)); + this.initDependencies(); + this.region = endpoint.split('.')[1]; + this.endpoint = endpoint; + } + + /** + * Overrides the upstream implementation of export. All behaviors are the same except if the + * endpoint is an XRay OTLP endpoint, we will sign the request with SigV4 in headers before + * sending it to the endpoint. Otherwise, we will skip signing. + */ + public override async export(items: ReadableSpan[], resultCallback: (result: ExportResult) => void): Promise { + // Only do SigV4 Signing if the required dependencies are installed. Otherwise default to the regular http/protobuf exporter. + if (this.hasRequiredDependencies) { + const url = new URL(this.endpoint); + const serializedSpans: Uint8Array | undefined = ProtobufTraceSerializer.serializeRequest(items); + + if (serializedSpans === undefined) { + return; + } + + /* + This is bad practice but there is no other way to access and inject SigV4 headers + into the request headers before the traces get exported. + */ + const oldHeaders = (this as any)._transport?._transport?._parameters?.headers; + + if (oldHeaders) { + const request = new this.httpRequest({ + method: 'POST', + protocol: 'https', + hostname: url.hostname, + path: url.pathname, + body: serializedSpans, + headers: { + ...oldHeaders, + host: url.hostname, + }, + }); + + try { + const signer = new this.signatureV4({ + credentials: this.defaultProvider(), + region: this.region, + service: OTLPAwsSpanExporter.SERVICE_NAME, + sha256: this.sha256, + }); + + const signedRequest = await signer.sign(request); + + (this as any)._transport._transport._parameters.headers = signedRequest.headers; + } catch (exception) { + diag.debug( + `Failed to sign/authenticate the given exported Span request to OTLP XRay endpoint with error: ${exception}` + ); + } + } + } + + await super.export(items, resultCallback); + } + + private initDependencies(): any { + if (getNodeVersion() < 16) { + diag.error('SigV4 signing requires atleast Node major version 16'); + return; + } + + try { + const awsSdkModule = require('@aws-sdk/credential-provider-node'); + const awsCryptoModule = require('@aws-crypto/sha256-js'); + const signatureModule = require('@smithy/signature-v4'); + const httpModule = require('@smithy/protocol-http'); + + (this.defaultProvider = awsSdkModule.defaultProvider), + (this.sha256 = awsCryptoModule.Sha256), + (this.signatureV4 = signatureModule.SignatureV4), + (this.httpRequest = httpModule.HttpRequest); + this.hasRequiredDependencies = true; + } catch (error) { + diag.error(`Failed to load required AWS dependency for SigV4 Signing: ${error}`); + } + } + + private static changeUrlConfig(endpoint: string, config?: OTLPExporterNodeConfigBase) { + const newConfig = + config === undefined + ? { url: endpoint } + : { + ...config, + url: endpoint, + }; + + return newConfig; + } +} diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/src/utils.ts b/aws-distro-opentelemetry-node-autoinstrumentation/src/utils.ts new file mode 100644 index 00000000..0fd74c0d --- /dev/null +++ b/aws-distro-opentelemetry-node-autoinstrumentation/src/utils.ts @@ -0,0 +1,19 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +export const getNodeVersion = () => { + const nodeVersion = process.versions.node; + const versionParts = nodeVersion.split('.'); + + if (versionParts.length === 0) { + return -1; + } + + const majorVersion = parseInt(versionParts[0], 10); + + if (isNaN(majorVersion)) { + return -1; + } + + return majorVersion; +}; diff --git a/aws-distro-opentelemetry-node-autoinstrumentation/test/otlp-aws-span-exporter.test.ts b/aws-distro-opentelemetry-node-autoinstrumentation/test/otlp-aws-span-exporter.test.ts new file mode 100644 index 00000000..b2cdb2df --- /dev/null +++ b/aws-distro-opentelemetry-node-autoinstrumentation/test/otlp-aws-span-exporter.test.ts @@ -0,0 +1,173 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import expect from 'expect'; +import { OTLPAwsSpanExporter } from '../src/otlp-aws-span-exporter'; +import * as sinon from 'sinon'; +import * as proxyquire from 'proxyquire'; +import * as nock from 'nock'; +import { getNodeVersion } from '../src/utils'; + +const XRAY_OTLP_ENDPOINT = 'https://xray.us-east-1.amazonaws.com'; +const XRAY_OTLP_ENDPOINT_PATH = '/v1/traces'; +const AUTHORIZATION_HEADER = 'Authorization'; +const X_AMZ_DATE_HEADER = 'X-Amz-Date'; +const X_AMZ_SECURITY_TOKEN_HEADER = 'X-Amz-Security-Token'; + +const EXPECTED_AUTH_HEADER = 'AWS4-HMAC-SHA256 Credential=test_key/some_date/us-east-1/xray/aws4_request'; +const EXPECTED_AUTH_X_AMZ_DATE = 'some_date'; +const EXPECTED_AUTH_SECURITY_TOKEN = 'test_token'; + +const nodeVersion = getNodeVersion(); + +// SigV4 exporter requires packages that require Node environments >= 16 +/* istanbul ignore next */ +if (nodeVersion >= 16) { + describe('OTLPAwsSpanExporter', () => { + let sandbox: sinon.SinonSandbox; + let scope: nock.Scope; + let mockModule: any; + + beforeEach(() => { + sandbox = sinon.createSandbox(); + + scope = nock(XRAY_OTLP_ENDPOINT) + .post(XRAY_OTLP_ENDPOINT_PATH) + .reply((uri: any, requestBody: any) => { + return [200, '']; + }); + + mockModule = proxyquire('../src/otlp-aws-span-exporter', { + '@smithy/signature-v4': { + SignatureV4: class MockSignatureV4 { + sign(req: any) { + req.headers = { + ...req.headers, + [AUTHORIZATION_HEADER]: EXPECTED_AUTH_HEADER, + [X_AMZ_DATE_HEADER]: EXPECTED_AUTH_X_AMZ_DATE, + [X_AMZ_SECURITY_TOKEN_HEADER]: EXPECTED_AUTH_SECURITY_TOKEN, + }; + + return req; + } + }, + }, + '@aws-sdk/credential-provider-node': { + defaultProvider: () => async () => { + return { + accessKeyId: 'test_access_key', + secretAccessKey: 'test_secret_key', + }; + }, + }, + }); + }); + + afterEach(() => { + sandbox.restore(); + }); + + it('Should inject SigV4 Headers successfully', async () => { + const exporter = new mockModule.OTLPAwsSpanExporter(XRAY_OTLP_ENDPOINT + XRAY_OTLP_ENDPOINT_PATH); + + scope.on('request', (req, interceptor, body) => { + const headers = req.headers; + expect(headers).toHaveProperty(AUTHORIZATION_HEADER.toLowerCase()); + expect(headers).toHaveProperty(X_AMZ_SECURITY_TOKEN_HEADER.toLowerCase()); + expect(headers).toHaveProperty(X_AMZ_DATE_HEADER.toLowerCase()); + + expect(headers[AUTHORIZATION_HEADER.toLowerCase()]).toBe(EXPECTED_AUTH_HEADER); + expect(headers[X_AMZ_SECURITY_TOKEN_HEADER.toLowerCase()]).toBe(EXPECTED_AUTH_SECURITY_TOKEN); + expect(headers[X_AMZ_DATE_HEADER.toLowerCase()]).toBe(EXPECTED_AUTH_X_AMZ_DATE); + + expect(headers['content-type']).toBe('application/x-protobuf'); + expect(headers['user-agent']).toMatch(/^OTel-OTLP-Exporter-JavaScript\/\d+\.\d+\.\d+$/); + }); + + await exporter.export([], () => {}); + }); + + describe('Should not inject SigV4 headers if dependencies are missing', () => { + const dependencies = [ + '@aws-sdk/credential-provider-node', + '@aws-crypto/sha256-js', + '@smithy/signature-v4', + '@smithy/protocol-http', + ]; + + dependencies.forEach(dependency => { + it(`should not sign headers if missing dependency: ${dependency}`, async () => { + const exporter = new OTLPAwsSpanExporter(XRAY_OTLP_ENDPOINT + XRAY_OTLP_ENDPOINT_PATH); + + scope.on('request', (req, interceptor, body) => { + const headers = req.headers; + expect(headers).not.toHaveProperty(AUTHORIZATION_HEADER); + expect(headers).not.toHaveProperty(X_AMZ_DATE_HEADER); + expect(headers).not.toHaveProperty(X_AMZ_SECURITY_TOKEN_HEADER); + + expect(headers['content-type']).toBe('application/x-protobuf'); + expect(headers['user-agent']).toMatch(/^OTel-OTLP-Exporter-JavaScript\/\d+\.\d+\.\d+$/); + }); + + Object.keys(require.cache).forEach(key => { + delete require.cache[key]; + }); + const requireStub = sandbox.stub(require('module'), '_load'); + requireStub.withArgs(dependency).throws(new Error(`Cannot find module '${dependency}'`)); + requireStub.callThrough(); + + await exporter.export([], () => {}); + }); + }); + }); + + it('should not inject SigV4 headers if failure to sign headers', async () => { + scope.on('request', (req, interceptor, body) => { + const headers = req.headers; + expect(headers).not.toHaveProperty(AUTHORIZATION_HEADER); + expect(headers).not.toHaveProperty(X_AMZ_DATE_HEADER); + expect(headers).not.toHaveProperty(X_AMZ_SECURITY_TOKEN_HEADER); + + expect(headers['content-type']).toBe('application/x-protobuf'); + expect(headers['user-agent']).toMatch(/^OTel-OTLP-Exporter-JavaScript\/\d+\.\d+\.\d+$/); + }); + + const stubbedModule = proxyquire('../src/otlp-aws-span-exporter', { + '@smithy/signature-v4': { + SignatureV4: class MockSignatureV4 { + sign() { + throw new Error('signing error'); + } + }, + }, + }); + + const exporter = new stubbedModule.OTLPAwsSpanExporter(XRAY_OTLP_ENDPOINT); + + await exporter.export([], () => {}); + }); + + it('should not inject SigV4 headers if failure to retrieve credentials', async () => { + scope.on('request', (req, interceptor, body) => { + const headers = req.headers; + expect(headers).not.toHaveProperty(AUTHORIZATION_HEADER); + expect(headers).not.toHaveProperty(X_AMZ_DATE_HEADER); + expect(headers).not.toHaveProperty(X_AMZ_SECURITY_TOKEN_HEADER); + + expect(headers['content-type']).toBe('application/x-protobuf'); + expect(headers['user-agent']).toMatch(/^OTel-OTLP-Exporter-JavaScript\/\d+\.\d+\.\d+$/); + }); + + const stubbedModule = proxyquire('../src/otlp-aws-span-exporter', { + '@aws-sdk/credential-provider-node': { + defaultProvider: () => async () => { + throw new Error('credentials error'); + }, + }, + }); + + const exporter = new stubbedModule.OTLPAwsSpanExporter(XRAY_OTLP_ENDPOINT); + + await exporter.export([], () => {}); + }); + }); +} diff --git a/package-lock.json b/package-lock.json index 941386f0..98990ae7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,6 +48,7 @@ "@opentelemetry/id-generator-aws-xray": "1.2.2", "@opentelemetry/instrumentation": "0.53.0", "@opentelemetry/instrumentation-aws-sdk": "0.44.0", + "@opentelemetry/otlp-transformer": "0.53.0", "@opentelemetry/propagator-aws-xray": "1.26.0", "@opentelemetry/resource-detector-aws": "1.6.1", "@opentelemetry/resources": "1.26.0", @@ -68,13 +69,17 @@ "@aws-sdk/client-sfn": "^3.632.0", "@aws-sdk/client-sns": "^3.632.0", "@opentelemetry/contrib-test-utils": "0.41.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/signature-v4": "^5.0.1", "@types/mocha": "7.0.2", "@types/node": "18.6.5", + "@types/proxyquire": "^1.3.31", "@types/sinon": "10.0.18", "expect": "29.2.0", "mocha": "7.2.0", "nock": "13.2.1", "nyc": "15.1.0", + "proxyquire": "^2.1.3", "rimraf": "5.0.5", "sinon": "15.2.0", "ts-mocha": "10.0.0", @@ -245,6 +250,189 @@ "node": ">=16.0.0" } }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@aws-sdk/client-bedrock-agent-runtime/node_modules/@smithy/protocol-http": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", + "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@aws-sdk/client-bedrock-agent/node_modules/@smithy/protocol-http": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", + "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@aws-sdk/client-bedrock/node_modules/@smithy/protocol-http": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", + "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^3.7.2", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/is-array-buffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.0.0.tgz", + "integrity": "sha512-saYhF8ZZNoJDTvJBEWgeBccCg+yvp1CX+ed12yORU3NilJScfc6gfch2oVb4QgxZrGUx3/ZJlb+c/dJbyupxlw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/protocol-http": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.0.1.tgz", + "integrity": "sha512-TE4cpj49jJNB/oHyh/cRVEgNZaoPaxd4vteJNB0yGidOCVR0jCw/hjPVsT8Q8FRmj8Bd3bFZt8Dh7xGCT+xMBQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/protocol-http/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/signature-v4": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.0.1.tgz", + "integrity": "sha512-nCe6fQ+ppm1bQuw5iKoeJ0MJfz2os7Ic3GBjOkLOPtavbD1ONoyE3ygjBfz2ythFWm4YnRm6OxW+8p/m9uCoIA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "@smithy/protocol-http": "^5.0.1", + "@smithy/types": "^4.1.0", + "@smithy/util-hex-encoding": "^4.0.0", + "@smithy/util-middleware": "^4.0.1", + "@smithy/util-uri-escape": "^4.0.0", + "@smithy/util-utf8": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/signature-v4/node_modules/@smithy/types": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.1.0.tgz", + "integrity": "sha512-enhjdwp4D7CXmwLtD6zbcDMbo6/T6WtuuKCY49Xxc6OMOmUWlBEBDREsxxgV2LIdeQPW756+f97GzcgAwp3iLw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/signature-v4/node_modules/@smithy/util-middleware": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.0.1.tgz", + "integrity": "sha512-HiLAvlcqhbzhuiOa0Lyct5IIlyIz0PQO5dnMlmQ/ubYM46dPInB+3yQGkfxsk6Q24Y0n3/JmcA1v5iEhmOF5mA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/types": "^4.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/signature-v4/node_modules/@smithy/util-utf8": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.0.0.tgz", + "integrity": "sha512-b+zebfKCfRdgNJDknHCob3O7FpeYQN6ZG6YLExMcasDHsCXlsXCEuiPZeLnJLpwa5dvPetGlnGCiMHuLwGvFow==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/util-buffer-from": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/util-buffer-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.0.0.tgz", + "integrity": "sha512-9TOQ7781sZvddgO8nxueKi3+yGvkY35kotA0Y6BWRajAv8jjmigQ1sBwz0UX47pQMYXJPahSKEKYFgt+rXdcug==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@smithy/is-array-buffer": "^4.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/util-hex-encoding": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.0.0.tgz", + "integrity": "sha512-Yk5mLhHtfIgW2W2WQZWSg5kuMZCVbvhFmC7rV4IO2QqnZdbEFPmQnCcGMAX2z/8Qj3B9hYYNjZOhWym+RwhePw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/@smithy/util-uri-escape": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.0.0.tgz", + "integrity": "sha512-77yfbCbQMtgtTylO9itEAdpPXSog3ZxMe09AEhm0dU0NLTalV70ghDZFR+Nfi1C60jnJoh/Re4090/DuZh2Omg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, "aws-distro-opentelemetry-node-autoinstrumentation/node_modules/typescript": { "version": "4.4.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", @@ -6774,9 +6962,9 @@ } }, "node_modules/@smithy/types": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.1.tgz", - "integrity": "sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", + "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -7210,6 +7398,13 @@ "@types/pg": "*" } }, + "node_modules/@types/proxyquire": { + "version": "1.3.31", + "resolved": "https://registry.npmjs.org/@types/proxyquire/-/proxyquire-1.3.31.tgz", + "integrity": "sha512-uALowNG2TSM1HNPMMOR0AJwv4aPYPhqB0xlEhkeRTMuto5hjoSPZkvgu1nbPUkz3gEPAHv4sy4DmKsurZiEfRQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", @@ -10659,6 +10854,20 @@ "node": ">=10" } }, + "node_modules/fill-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/fill-keys/-/fill-keys-1.0.2.tgz", + "integrity": "sha512-tcgI872xXjwFF4xgQmLxi76GnwJG3g/3isB1l4/G5Z4zrbddGpBjqZCO9oEAcB5wX0Hj/5iQB3toxfO7in1hHA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-object": "~1.0.1", + "merge-descriptors": "~1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -12467,6 +12676,16 @@ "node": ">=8" } }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", @@ -15022,6 +15241,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -15813,6 +16042,13 @@ "integrity": "sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A==", "license": "MIT" }, + "node_modules/module-not-found-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/module-not-found-error/-/module-not-found-error-1.0.1.tgz", + "integrity": "sha512-pEk4ECWQXV6z2zjhRZUongnLJNUeGQJ3w6OQ5ctGwD+i5o93qjRQUk2Rt6VdNeu3sEP0AB4LcfvdebpxBRVr4g==", + "dev": true, + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -18612,6 +18848,18 @@ "dev": true, "license": "MIT" }, + "node_modules/proxyquire": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/proxyquire/-/proxyquire-2.1.3.tgz", + "integrity": "sha512-BQWfCqYM+QINd+yawJz23tbBM40VIGXOdDw3X344KcclI/gtBbdWF6SlQ4nK/bYhF9d27KYug9WzljHC6B9Ysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-keys": "^1.0.2", + "module-not-found-error": "^1.0.1", + "resolve": "^1.11.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",