From 39e812041b414d60db6fceeae53842255b89c82e Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 29 Jul 2026 15:06:10 +0200 Subject: [PATCH] ref(aws-serverless): Remove dead vendored aws-sdk OTel instrumentation The vendored OpenTelemetry `AwsInstrumentation` and its service extensions are dead code: aws-sdk spans come from the channel-based `awsIntegration()` in `@sentry/server-utils`, and nothing instantiated the vendored class. Remove the whole tree and the now-unused `@opentelemetry/instrumentation` and `@opentelemetry/api` dependencies. Co-Authored-By: Claude Opus 4.8 --- packages/aws-serverless/package.json | 2 - packages/aws-serverless/rollup.npm.config.mjs | 2 - .../src/integration/aws/vendored/aws-sdk.ts | 344 ----------- .../integration/aws/vendored/aws-sdk.types.ts | 112 ---- .../src/integration/aws/vendored/enums.ts | 14 - .../src/integration/aws/vendored/propwrap.ts | 135 ----- .../aws/vendored/semconv-obsolete.ts | 52 -- .../src/integration/aws/vendored/semconv.ts | 381 ------------ .../vendored/services/MessageAttributes.ts | 77 --- .../aws/vendored/services/ServiceExtension.ts | 38 -- .../vendored/services/ServicesExtensions.ts | 66 --- .../aws/vendored/services/bedrock-runtime.ts | 547 ------------------ .../aws/vendored/services/dynamodb.ts | 206 ------- .../aws/vendored/services/index.ts | 10 - .../aws/vendored/services/kinesis.ts | 31 - .../aws/vendored/services/lambda.ts | 106 ---- .../integration/aws/vendored/services/s3.ts | 31 - .../aws/vendored/services/secretsmanager.ts | 35 -- .../integration/aws/vendored/services/sns.ts | 87 --- .../integration/aws/vendored/services/sqs.ts | 148 ----- .../aws/vendored/services/stepfunctions.ts | 34 -- .../src/integration/aws/vendored/types.ts | 31 - .../src/integration/aws/vendored/utils.ts | 61 -- 23 files changed, 2550 deletions(-) delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/aws-sdk.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/aws-sdk.types.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/enums.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/propwrap.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/semconv-obsolete.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/semconv.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/MessageAttributes.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/ServiceExtension.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/ServicesExtensions.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/bedrock-runtime.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/dynamodb.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/index.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/kinesis.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/lambda.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/s3.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/secretsmanager.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/sns.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/sqs.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/services/stepfunctions.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/types.ts delete mode 100644 packages/aws-serverless/src/integration/aws/vendored/utils.ts diff --git a/packages/aws-serverless/package.json b/packages/aws-serverless/package.json index 8a09a165b0d3..39e45f8ff360 100644 --- a/packages/aws-serverless/package.json +++ b/packages/aws-serverless/package.json @@ -62,8 +62,6 @@ "access": "public" }, "dependencies": { - "@opentelemetry/api": "^1.9.1", - "@opentelemetry/instrumentation": "^0.220.0", "@sentry/conventions": "^0.16.0", "@sentry/core": "10.67.0", "@sentry/node": "10.67.0", diff --git a/packages/aws-serverless/rollup.npm.config.mjs b/packages/aws-serverless/rollup.npm.config.mjs index 0d1a5905ee67..17547d8b1a70 100644 --- a/packages/aws-serverless/rollup.npm.config.mjs +++ b/packages/aws-serverless/rollup.npm.config.mjs @@ -35,8 +35,6 @@ export default [ // packages with bundles have a different build directory structure hasBundles: true, packageSpecificConfig: { - // Used for our custom eventContextExtractor - external: ['@opentelemetry/api'], output: { preserveModulesRoot: 'src', }, diff --git a/packages/aws-serverless/src/integration/aws/vendored/aws-sdk.ts b/packages/aws-serverless/src/integration/aws/vendored/aws-sdk.ts deleted file mode 100644 index de218bc58b98..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/aws-sdk.ts +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - * - Backported the `@smithy/core` >= 3.24.0 support from upstream 0.74.0 - * (https://github.com/open-telemetry/opentelemetry-js-contrib/pull/3530) - */ - -import { Span, context, trace, diag, SpanStatusCode } from '@opentelemetry/api'; -import { AWS_REQUEST_EXTENDED_ID, AWS_REQUEST_ID, CLOUD_REGION } from './enums'; -import { ServicesExtensions } from './services'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from './types'; -import { - InstrumentationBase, - InstrumentationModuleDefinition, - InstrumentationNodeModuleDefinition, - InstrumentationNodeModuleFile, - isWrapped, -} from '@opentelemetry/instrumentation'; -import type { - MiddlewareStack, - HandlerExecutionContext, - Command as AwsV3Command, - Handler as AwsV3MiddlewareHandler, - InitializeHandlerArguments, -} from '@aws-sdk/types'; -import { - bindPromise, - extractAttributesFromNormalizedRequest, - normalizeV3Request, - removeSuffixFromStringIfExists, -} from './utils'; -import { propwrap } from './propwrap'; -import { RequestMetadata } from './services/ServiceExtension'; -import { HTTP_STATUS_CODE, SENTRY_KIND } from '@sentry/conventions/attributes'; -import { SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/core'; - -const PACKAGE_NAME = '@sentry/instrumentation-aws-sdk'; - -const V3_CLIENT_CONFIG_KEY = Symbol('opentelemetry.instrumentation.aws-sdk.client.config'); -type V3PluginCommand = AwsV3Command & { - [V3_CLIENT_CONFIG_KEY]?: any; -}; - -export class AwsInstrumentation extends InstrumentationBase { - static readonly component = 'aws-sdk'; - private servicesExtensions: ServicesExtensions; - - constructor(config: AwsSdkInstrumentationConfig = {}) { - super(PACKAGE_NAME, SDK_VERSION, config); - this.servicesExtensions = new ServicesExtensions(); - } - - protected init(): InstrumentationModuleDefinition[] { - const v3MiddlewareStackFileOldVersions = new InstrumentationNodeModuleFile( - '@aws-sdk/middleware-stack/dist/cjs/MiddlewareStack.js', - ['>=3.1.0 <3.35.0'], - this.patchV3ConstructStack.bind(this), - this.unpatchV3ConstructStack.bind(this), - ); - const v3MiddlewareStackFileNewVersions = new InstrumentationNodeModuleFile( - '@aws-sdk/middleware-stack/dist-cjs/MiddlewareStack.js', - ['>=3.35.0'], - this.patchV3ConstructStack.bind(this), - this.unpatchV3ConstructStack.bind(this), - ); - - // as for aws-sdk v3.13.1, constructStack is exported from @aws-sdk/middleware-stack as - // getter instead of function, which fails shimmer. - // so we are patching the MiddlewareStack.js file directly to get around it. - const v3MiddlewareStack = new InstrumentationNodeModuleDefinition( - '@aws-sdk/middleware-stack', - ['^3.1.0'], - undefined, - undefined, - [v3MiddlewareStackFileOldVersions, v3MiddlewareStackFileNewVersions], - ); - - // Patch for @smithy/middleware-stack for @aws-sdk/* packages v3.363.0+. - // As of @smithy/middleware-stack@2.1.0 `constructStack` is only available - // as a getter, so we cannot use `this._wrap()`. - const self = this; - const v3SmithyMiddlewareStack = new InstrumentationNodeModuleDefinition( - '@smithy/middleware-stack', - ['>=2.0.0'], - (moduleExports, moduleVersion) => { - const newExports = propwrap(moduleExports, 'constructStack', (orig: any) => { - self._diag.debug('propwrapping aws-sdk v3 constructStack'); - return self._getV3ConstructStackPatch(moduleVersion, orig); - }); - return newExports; - }, - ); - - // Patch for @smithy/core >= 3.24.0: the `Client` class moved from @smithy/smithy-client - // into the @smithy/core/client bundle, and `constructStack` became a closed-over local in - // that bundle (so wrapping the @smithy/middleware-stack export no longer applies). We patch - // `Client.prototype.send` there, and patch the live middleware stack from within `send`. - const v3SmithyCoreClientFile = new InstrumentationNodeModuleFile( - '@smithy/core/dist-cjs/submodules/client/index.js', - ['>=3.24.0'], - this.patchV3SmithyClient.bind(this), - this.unpatchV3SmithyClient.bind(this), - ); - const v3SmithyCore = new InstrumentationNodeModuleDefinition('@smithy/core', ['>=3.24.0'], undefined, undefined, [ - v3SmithyCoreClientFile, - ]); - - const v3SmithyClient = new InstrumentationNodeModuleDefinition( - '@aws-sdk/smithy-client', - ['^3.1.0'], - this.patchV3SmithyClient.bind(this), - this.unpatchV3SmithyClient.bind(this), - ); - - // patch for new @smithy/smithy-client for aws-sdk packages v3.363.0+ - const v3NewSmithyClient = new InstrumentationNodeModuleDefinition( - '@smithy/smithy-client', - ['>=1.0.3'], - this.patchV3SmithyClient.bind(this), - this.unpatchV3SmithyClient.bind(this), - ); - - return [v3MiddlewareStack, v3SmithyMiddlewareStack, v3SmithyCore, v3SmithyClient, v3NewSmithyClient]; - } - - protected patchV3ConstructStack(moduleExports: any, moduleVersion?: string) { - this._wrap(moduleExports, 'constructStack', this._getV3ConstructStackPatch.bind(this, moduleVersion)); - return moduleExports; - } - - protected unpatchV3ConstructStack(moduleExports: any) { - this._unwrap(moduleExports, 'constructStack'); - return moduleExports; - } - - protected patchV3SmithyClient(moduleExports: any, moduleVersion?: string) { - this._wrap(moduleExports.Client.prototype, 'send', this._getV3SmithyClientSendPatch.bind(this, moduleVersion)); - return moduleExports; - } - - protected unpatchV3SmithyClient(moduleExports: any) { - this._unwrap(moduleExports.Client.prototype, 'send'); - return moduleExports; - } - - private _startAwsV3Span(normalizedRequest: NormalizedRequest, metadata: RequestMetadata): Span { - const name = metadata.spanName ?? `${normalizedRequest.serviceName}.${normalizedRequest.commandName}`; - return startInactiveSpan({ - name, - - attributes: { - [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.otel.aws', - [SENTRY_KIND]: 'client', - ...extractAttributesFromNormalizedRequest(normalizedRequest), - ...metadata.spanAttributes, - }, - }); - } - - private _getV3ConstructStackPatch( - moduleVersion: string | undefined, - original: (...args: unknown[]) => MiddlewareStack, - ) { - const self = this; - return function constructStack(this: any, ...args: unknown[]): MiddlewareStack { - const stack: MiddlewareStack = original.apply(this, args); - self.patchV3MiddlewareStack(moduleVersion, stack); - return stack; - }; - } - - private _getV3SmithyClientSendPatch( - moduleVersion: string | undefined, - original: (...args: unknown[]) => Promise, - ) { - const self = this; - return function send(this: any, command: V3PluginCommand, ...args: unknown[]): Promise { - command[V3_CLIENT_CONFIG_KEY] = this.config; - // For @smithy/core >= 3.24.0 `constructStack` is no longer patchable via its export, so we - // patch the live middleware stack instance here instead. This is a no-op (guarded by - // `isWrapped`) for older versions where the stack was already patched via `constructStack`. - self.patchV3MiddlewareStack(moduleVersion, this.middlewareStack); - return original.apply(this, [command, ...args]); - }; - } - - private patchV3MiddlewareStack(moduleVersion: string | undefined, middlewareStackToPatch: MiddlewareStack) { - if (!isWrapped(middlewareStackToPatch.resolve)) { - this._wrap(middlewareStackToPatch, 'resolve', this._getV3MiddlewareStackResolvePatch.bind(this)); - } - - // 'clone' and 'concat' functions are internally calling 'constructStack' which is in same - // module, thus not patched, and we need to take care of it specifically. - if (!isWrapped(middlewareStackToPatch.clone)) { - this._wrap(middlewareStackToPatch, 'clone', this._getV3MiddlewareStackClonePatch.bind(this, moduleVersion)); - } - if (!isWrapped(middlewareStackToPatch.concat)) { - this._wrap(middlewareStackToPatch, 'concat', this._getV3MiddlewareStackClonePatch.bind(this, moduleVersion)); - } - } - - private _getV3MiddlewareStackClonePatch( - moduleVersion: string | undefined, - original: (...args: any[]) => MiddlewareStack, - ) { - const self = this; - return function (this: any, ...args: any[]) { - const newStack = original.apply(this, args); - self.patchV3MiddlewareStack(moduleVersion, newStack); - return newStack; - }; - } - - private _getV3MiddlewareStackResolvePatch( - original: (_handler: any, context: HandlerExecutionContext) => AwsV3MiddlewareHandler, - ) { - const self = this; - return function ( - this: any, - _handler: any, - awsExecutionContext: HandlerExecutionContext, - ): AwsV3MiddlewareHandler { - const origHandler = original.call(this, _handler, awsExecutionContext); - const patchedHandler = function ( - this: any, - command: InitializeHandlerArguments & { - [V3_CLIENT_CONFIG_KEY]?: any; - }, - ): Promise { - const clientConfig = command[V3_CLIENT_CONFIG_KEY]; - const regionPromise = clientConfig?.region?.(); - const serviceName = - clientConfig?.serviceId ?? - removeSuffixFromStringIfExists( - // Use 'AWS' as a fallback serviceName to match type definition. - // In practice, `clientName` should always be set. - awsExecutionContext.clientName || 'AWS', - 'Client', - ); - const commandName = awsExecutionContext.commandName ?? command.constructor?.name; - const normalizedRequest = normalizeV3Request(serviceName, commandName, command.input, undefined); - const requestMetadata = self.servicesExtensions.requestPreSpanHook( - normalizedRequest, - self.getConfig(), - self._diag, - ); - const span = self._startAwsV3Span(normalizedRequest, requestMetadata); - const activeContextWithSpan = trace.setSpan(context.active(), span); - - const handlerPromise = new Promise((resolve, reject) => { - Promise.resolve(regionPromise) - .then(resolvedRegion => { - normalizedRequest.region = resolvedRegion; - span.setAttribute(CLOUD_REGION, resolvedRegion); - }) - .catch(e => { - // there is nothing much we can do in this case. - // we'll just continue without region - diag.debug( - `${AwsInstrumentation.component} instrumentation: failed to extract region from async function`, - e, - ); - }) - .finally(() => { - const resultPromise = context.with(activeContextWithSpan, () => { - self.servicesExtensions.requestPostSpanHook(normalizedRequest); - return origHandler.call(this, command); - }); - const promiseWithResponseLogic = resultPromise - .then((response: any) => { - const requestId = response.output?.$metadata?.requestId; - if (requestId) { - span.setAttribute(AWS_REQUEST_ID, requestId); - } - - const httpStatusCode = response.output?.$metadata?.httpStatusCode; - if (httpStatusCode) { - // oxlint-disable-next-line typescript/no-deprecated - span.setAttribute(HTTP_STATUS_CODE, httpStatusCode); - } - - const extendedRequestId = response.output?.$metadata?.extendedRequestId; - if (extendedRequestId) { - span.setAttribute(AWS_REQUEST_EXTENDED_ID, extendedRequestId); - } - - const normalizedResponse: NormalizedResponse = { - data: response.output, - request: normalizedRequest, - requestId: requestId, - }; - const override = self.servicesExtensions.responseHook(normalizedResponse, span); - if (override) { - response.output = override; - normalizedResponse.data = override; - } - return response; - }) - .catch((err: any) => { - const requestId = err?.RequestId; - if (requestId) { - span.setAttribute(AWS_REQUEST_ID, requestId); - } - - const httpStatusCode = err?.$metadata?.httpStatusCode; - if (httpStatusCode) { - // oxlint-disable-next-line typescript/no-deprecated - span.setAttribute(HTTP_STATUS_CODE, httpStatusCode); - } - - const extendedRequestId = err?.extendedRequestId; - if (extendedRequestId) { - span.setAttribute(AWS_REQUEST_EXTENDED_ID, extendedRequestId); - } - - span.setStatus({ - code: SpanStatusCode.ERROR, - message: err.message, - }); - throw err; - }) - .finally(() => { - if (!requestMetadata.isStream) { - span.end(); - } - }); - promiseWithResponseLogic - .then((res: any) => { - resolve(res); - }) - .catch((err: any) => reject(err)); - }); - }); - - return requestMetadata.isIncoming ? bindPromise(handlerPromise, activeContextWithSpan, 2) : handlerPromise; - }; - return patchedHandler; - }; - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/aws-sdk.types.ts b/packages/aws-serverless/src/integration/aws/vendored/aws-sdk.types.ts deleted file mode 100644 index 8dbdc766100b..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/aws-sdk.types.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -/* - * AWS SDK for JavaScript - * Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * This product includes software developed at - * Amazon Web Services, Inc. (http://aws.amazon.com/). - */ - -/* - These are slightly modified and simplified versions of the actual SQS types included - in the official distribution: - https://github.com/aws/aws-sdk-js/blob/master/clients/sqs.d.ts - These are brought here to avoid having users install the `aws-sdk` whenever they - require this instrumentation. -*/ - -interface Blob {} -type Binary = Buffer | Uint8Array | Blob | string; - -// eslint-disable-next-line @typescript-eslint/no-namespace -- Prefer to contain the types copied over in one location -export namespace SNS { - interface MessageAttributeValue { - /** - * Amazon SNS supports the following logical data types: String, String.Array, Number, and Binary. For more information, see Message Attribute Data Types. - */ - DataType: string; - /** - * Strings are Unicode with UTF8 binary encoding. For a list of code values, see ASCII Printable Characters. - */ - StringValue?: string; - /** - * Binary type attributes can store any binary data, for example, compressed data, encrypted data, or images. - */ - BinaryValue?: Binary; - } - - export type MessageAttributeMap = { [key: string]: MessageAttributeValue }; -} - -// eslint-disable-next-line @typescript-eslint/no-namespace -- Prefer to contain the types copied over in one location -export namespace SQS { - type StringList = string[]; - type BinaryList = Binary[]; - interface MessageAttributeValue { - /** - * Strings are Unicode with UTF-8 binary encoding. For a list of code values, see ASCII Printable Characters. - */ - StringValue?: string; - /** - * Binary type attributes can store any binary data, such as compressed data, encrypted data, or images. - */ - BinaryValue?: Binary; - /** - * Not implemented. Reserved for future use. - */ - StringListValues?: StringList; - /** - * Not implemented. Reserved for future use. - */ - BinaryListValues?: BinaryList; - /** - * Amazon SQS supports the following logical data types: String, Number, and Binary. For the Number data type, you must use StringValue. You can also append custom labels. For more information, see Amazon SQS Message Attributes in the Amazon SQS Developer Guide. - */ - DataType: string; - } - - export type MessageBodyAttributeMap = { - [key: string]: MessageAttributeValue; - }; - - type MessageSystemAttributeMap = { [key: string]: string }; - - export interface Message { - /** - * A unique identifier for the message. A MessageId is considered unique across all accounts for an extended period of time. - */ - MessageId?: string; - /** - * An identifier associated with the act of receiving the message. A new receipt handle is returned every time you receive a message. When deleting a message, you provide the last received receipt handle to delete the message. - */ - ReceiptHandle?: string; - /** - * An MD5 digest of the non-URL-encoded message body string. - */ - MD5OfBody?: string; - /** - * The message's contents (not URL-encoded). - */ - Body?: string; - /** - * A map of the attributes requested in ReceiveMessage to their respective values. Supported attributes: ApproximateReceiveCount ApproximateFirstReceiveTimestamp MessageDeduplicationId MessageGroupId SenderId SentTimestamp SequenceNumber ApproximateFirstReceiveTimestamp and SentTimestamp are each returned as an integer representing the epoch time in milliseconds. - */ - Attributes?: MessageSystemAttributeMap; - /** - * An MD5 digest of the non-URL-encoded message attribute string. You can use this attribute to verify that Amazon SQS received the message correctly. Amazon SQS URL-decodes the message before creating the MD5 digest. For information about MD5, see RFC1321. - */ - MD5OfMessageAttributes?: string; - /** - * Each message attribute consists of a Name, Type, and Value. For more information, see Amazon SQS message attributes in the Amazon SQS Developer Guide. - */ - MessageAttributes?: MessageBodyAttributeMap; - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/enums.ts b/packages/aws-serverless/src/integration/aws/vendored/enums.ts deleted file mode 100644 index 6918ae70b5d3..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/enums.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -export const CLOUD_REGION = 'cloud.region'; -export const AWS_REQUEST_ID = 'aws.request.id'; -export const AWS_REQUEST_EXTENDED_ID = 'aws.request.extended_id'; -export const AWS_S3_BUCKET = 'aws.s3.bucket'; -export const AWS_KINESIS_STREAM_NAME = 'aws.kinesis.stream.name'; diff --git a/packages/aws-serverless/src/integration/aws/vendored/propwrap.ts b/packages/aws-serverless/src/integration/aws/vendored/propwrap.ts deleted file mode 100644 index 6ca8633d582c..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/propwrap.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -/* - * This block is derived from esbuild's bundling support. - * https://github.com/evanw/esbuild/blob/v0.14.42/internal/runtime/runtime.go#L22 - * - * License: - * MIT License - * - * Copyright (c) 2020 Evan Wallace - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -const __defProp = Object.defineProperty; -const __getOwnPropDesc = Object.getOwnPropertyDescriptor; -const __hasOwnProp = Object.prototype.hasOwnProperty; -const __getOwnPropNames = Object.getOwnPropertyNames; -const __copyProps = (to: any, from: any, except: string, desc?: PropertyDescriptor | undefined) => { - if ((from && typeof from === 'object') || typeof from === 'function') { - for (const key of __getOwnPropNames(from)) { - if (!__hasOwnProp.call(to, key) && key !== except) { - __defProp(to, key, { - get: () => from[key] as any, - enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable, - }); - } - } - } - return to; -}; - -/** - * Return a new object that is a copy of `obj`, with its `subpath` property - * replaced with the return value of `wrapper(original)`. - * - * This is similar to shimmer (i.e. `InstrumentationBase.prototype._wrap`). - * However, it uses a different technique to support wrapping properties that - * are only available via a getter (i.e. their property descriptor is `.writable - * === false`). - * - * For example: - * var os = propwrap(require('os'), 'platform', (orig) => { - * return function wrappedPlatform () { - * return orig().toUpperCase() - * } - * }) - * console.log(os.platform()) // => DARWIN - * - * The subpath can indicate a nested property. Each property in that subpath, - * except the last, must identify an *Object*. - * - * Limitations: - * - This doesn't handle possible Symbol properties on the copied object(s). - * - This cannot wrap a property of a function, because we cannot create a - * copy of the function. - * - * @param {object} obj - * @param {string} subpath - The property subpath on `obj` to wrap. This may - * point to a nested property by using a '.' to separate levels. For example: - * var fs = wrap(fs, 'promises.sync', (orig) => { ... }) - * @param {Function} wrapper - A function of the form `function (orig)`, where - * `orig` is the original property value. This must synchronously return the - * new property value. - * @returns {object} A new object with the wrapped property. - * @throws {TypeError} if the subpath points to a non-existent property, or if - * any but the last subpath part points to a non-Object. - */ -export const propwrap = (obj: any, subpath: string, wrapper: Function): any => { - const parts = subpath.split('.'); - const namespaces = [obj]; - let namespace = obj; - let key: string | undefined; - let val: any; - - // 1. Traverse the subpath parts to sanity check and get references to the - // Objects that we will be copying. - for (let i = 0; i < parts.length; i++) { - key = parts[i]; - val = namespace[key!]; - if (!val) { - throw new TypeError(`cannot wrap "${subpath}": ".${parts.slice(0, i).join('.')}" is ${typeof val}`); - } else if (i < parts.length - 1) { - if (typeof val !== 'object') { - throw new TypeError(`cannot wrap "${subpath}": ".${parts.slice(0, i).join('.')}" is not an Object`); - } - namespace = val; - namespaces.push(namespace); - } - } - - // 2. Now work backwards, wrapping each namespace with a new object that has a - // copy of all the properties, except the one that we've wrapped. - for (let i = parts.length - 1; i >= 0; i--) { - key = parts[i]; - namespace = namespaces[i]; - if (i === parts.length - 1) { - const orig = namespace[key!]; - val = wrapper(orig); - } else { - val = namespaces[i + 1]; - } - const desc = __getOwnPropDesc(namespace, key!); - const wrappedNamespace = __defProp({}, key!, { - value: val, - enumerable: !desc || desc.enumerable, - }); - __copyProps(wrappedNamespace, namespace, key!); - namespaces[i] = wrappedNamespace; - } - - return namespaces[0]; -}; diff --git a/packages/aws-serverless/src/integration/aws/vendored/semconv-obsolete.ts b/packages/aws-serverless/src/integration/aws/vendored/semconv-obsolete.ts deleted file mode 100644 index aabd72bccbe5..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/semconv-obsolete.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -/* - * This file contains constants for values that where replaced/removed from - * Semantic Conventions long enough ago that they do not have `ATTR_*` - * constants in the `@opentelemetry/semantic-conventions` package. Eventually - * it is expected that this instrumention will be updated to emit telemetry - * using modern Semantic Conventions, dropping the need for the constants in - * this file. - */ - -/** - * The execution ID of the current function execution. - * - * @deprecated Use ATTR_FAAS_INVOCATION_ID in [incubating entry-point]({@link https://github.com/open-telemetry/opentelemetry-js/blob/main/semantic-conventions/README.md#unstable-semconv}). - */ -export const ATTR_FAAS_EXECUTION = 'faas.execution' as const; - -/** - * The message destination name. This might be equal to the span name but is required nevertheless. - * - * @deprecated Use ATTR_MESSAGING_DESTINATION_NAME in [incubating entry-point]({@link https://github.com/open-telemetry/opentelemetry-js/blob/main/semantic-conventions/README.md#unstable-semconv}). - */ -export const ATTR_MESSAGING_DESTINATION = 'messaging.destination' as const; - -/** - * The kind of message destination. - * - * @deprecated Removed in semconv v1.20.0. - */ -export const ATTR_MESSAGING_DESTINATION_KIND = 'messaging.destination_kind' as const; - -/** - * The kind of message destination. - * - * @deprecated Removed in semconv v1.20.0. - */ -export const MESSAGING_DESTINATION_KIND_VALUE_TOPIC = 'topic' as const; - -/** - * A string identifying the kind of message consumption as defined in the [Operation names](#operation-names) section above. If the operation is "send", this attribute MUST NOT be set, since the operation can be inferred from the span kind in that case. - * - * @deprecated Use MESSAGING_OPERATION_TYPE_VALUE_RECEIVE in [incubating entry-point]({@link https://github.com/open-telemetry/opentelemetry-js/blob/main/semantic-conventions/README.md#unstable-semconv}). - */ -export const MESSAGING_OPERATION_VALUE_RECEIVE = 'receive' as const; diff --git a/packages/aws-serverless/src/integration/aws/vendored/semconv.ts b/packages/aws-serverless/src/integration/aws/vendored/semconv.ts deleted file mode 100644 index 2b8403bed5bd..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/semconv.ts +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -/* - * This file contains a copy of unstable semantic convention definitions - * used by this package. - * @see https://github.com/open-telemetry/opentelemetry-js/tree/main/semantic-conventions#unstable-semconv - */ - -/** - * The JSON-serialized value of each item in the `AttributeDefinitions` request field. - * - * @example ["{ "AttributeName": "string", "AttributeType": "string" }"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS = 'aws.dynamodb.attribute_definitions' as const; - -/** - * The value of the `ConsistentRead` request parameter. - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_CONSISTENT_READ = 'aws.dynamodb.consistent_read' as const; - -/** - * The JSON-serialized value of each item in the `ConsumedCapacity` response field. - * - * @example ["{ "CapacityUnits": number, "GlobalSecondaryIndexes": { "string" : { "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": number } }, "LocalSecondaryIndexes": { "string" : { "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": number } }, "ReadCapacityUnits": number, "Table": { "CapacityUnits": number, "ReadCapacityUnits": number, "WriteCapacityUnits": number }, "TableName": "string", "WriteCapacityUnits": number }"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY = 'aws.dynamodb.consumed_capacity' as const; - -/** - * The value of the `Count` response parameter. - * - * @example 10 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_COUNT = 'aws.dynamodb.count' as const; - -/** - * The value of the `ExclusiveStartTableName` request parameter. - * - * @example Users - * @example CatsTable - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_EXCLUSIVE_START_TABLE = 'aws.dynamodb.exclusive_start_table' as const; - -/** - * The JSON-serialized value of each item of the `GlobalSecondaryIndexes` request field - * - * @example ["{ "IndexName": "string", "KeySchema": [ { "AttributeName": "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits": number } }"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES = 'aws.dynamodb.global_secondary_indexes' as const; - -/** - * The JSON-serialized value of each item in the `GlobalSecondaryIndexUpdates` request field. - * - * @example ["{ "Create": { "IndexName": "string", "KeySchema": [ { "AttributeName": "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], "ProjectionType": "string" }, "ProvisionedThroughput": { "ReadCapacityUnits": number, "WriteCapacityUnits": number } }"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES = 'aws.dynamodb.global_secondary_index_updates' as const; - -/** - * The value of the `IndexName` request parameter. - * - * @example name_to_group - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_INDEX_NAME = 'aws.dynamodb.index_name' as const; - -/** - * The JSON-serialized value of the `ItemCollectionMetrics` response field. - * - * @example { "string" : [ { "ItemCollectionKey": { "string" : { "B": blob, "BOOL": boolean, "BS": [ blob ], "L": [ "AttributeValue" ], "M": { "string" : "AttributeValue" }, "N": "string", "NS": [ "string" ], "NULL": boolean, "S": "string", "SS": [ "string" ] } }, "SizeEstimateRangeGB": [ number ] } ] } - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS = 'aws.dynamodb.item_collection_metrics' as const; - -/** - * The value of the `Limit` request parameter. - * - * @example 10 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_LIMIT = 'aws.dynamodb.limit' as const; - -/** - * The JSON-serialized value of each item of the `LocalSecondaryIndexes` request field. - * - * @example ["{ "IndexArn": "string", "IndexName": "string", "IndexSizeBytes": number, "ItemCount": number, "KeySchema": [ { "AttributeName": "string", "KeyType": "string" } ], "Projection": { "NonKeyAttributes": [ "string" ], "ProjectionType": "string" } }"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES = 'aws.dynamodb.local_secondary_indexes' as const; - -/** - * The value of the `ProjectionExpression` request parameter. - * - * @example Title - * @example Title, Price, Color - * @example Title, Description, RelatedItems, ProductReviews - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_PROJECTION = 'aws.dynamodb.projection' as const; - -/** - * The value of the `ProvisionedThroughput.ReadCapacityUnits` request parameter. - * - * @example 1.0 - * @example 2.0 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY = 'aws.dynamodb.provisioned_read_capacity' as const; - -/** - * The value of the `ProvisionedThroughput.WriteCapacityUnits` request parameter. - * - * @example 1.0 - * @example 2.0 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY = 'aws.dynamodb.provisioned_write_capacity' as const; - -/** - * The value of the `ScannedCount` response parameter. - * - * @example 50 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_SCANNED_COUNT = 'aws.dynamodb.scanned_count' as const; - -/** - * The value of the `ScanIndexForward` request parameter. - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_SCAN_FORWARD = 'aws.dynamodb.scan_forward' as const; - -/** - * The value of the `Segment` request parameter. - * - * @example 10 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_SEGMENT = 'aws.dynamodb.segment' as const; - -/** - * The value of the `Select` request parameter. - * - * @example ALL_ATTRIBUTES - * @example COUNT - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_SELECT = 'aws.dynamodb.select' as const; - -/** - * The number of items in the `TableNames` response parameter. - * - * @example 20 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_TABLE_COUNT = 'aws.dynamodb.table_count' as const; - -/** - * The keys in the `RequestItems` object field. - * - * @example ["Users", "Cats"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_TABLE_NAMES = 'aws.dynamodb.table_names' as const; - -/** - * The value of the `TotalSegments` request parameter. - * - * @example 100 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_DYNAMODB_TOTAL_SEGMENTS = 'aws.dynamodb.total_segments' as const; - -/** - * The ARN of the Secret stored in the Secrets Mangger - * - * @example arn:aws:secretsmanager:us-east-1:123456789012:secret:SecretName-6RandomCharacters - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_SECRETSMANAGER_SECRET_ARN = 'aws.secretsmanager.secret.arn' as const; - -/** - * The ARN of the AWS SNS Topic. An Amazon SNS [topic](https://docs.aws.amazon.com/sns/latest/dg/sns-create-topic.html) is a logical access point that acts as a communication channel. - * - * @example arn:aws:sns:us-east-1:123456789012:mystack-mytopic-NZJ5JSMVGFIE - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_SNS_TOPIC_ARN = 'aws.sns.topic.arn' as const; - -/** - * The ARN of the AWS Step Functions Activity. - * - * @example arn:aws:states:us-east-1:123456789012:activity:get-greeting - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN = 'aws.step_functions.activity.arn' as const; - -/** - * The ARN of the AWS Step Functions State Machine. - * - * @example arn:aws:states:us-east-1:123456789012:stateMachine:myStateMachine:1 - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN = 'aws.step_functions.state_machine.arn' as const; - -/** - * The name of the invoked function. - * - * @example "my-function" - * - * @note **SHOULD** be equal to the `faas.name` resource attribute of the invoked function. - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_FAAS_INVOKED_NAME = 'faas.invoked_name' as const; - -/** - * The cloud provider of the invoked function. - * - * @note **SHOULD** be equal to the `cloud.provider` resource attribute of the invoked function. - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_FAAS_INVOKED_PROVIDER = 'faas.invoked_provider' as const; - -/** - * The cloud region of the invoked function. - * - * @example "eu-central-1" - * - * @note **SHOULD** be equal to the `cloud.region` resource attribute of the invoked function. - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_FAAS_INVOKED_REGION = 'faas.invoked_region' as const; - -/** - * List of sequences that the model will use to stop generating further tokens. - * - * @example ["forest", "lived"] - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_GEN_AI_REQUEST_STOP_SEQUENCES = 'gen_ai.request.stop_sequences' as const; - -/** - * The type of token being counted. - * - * @example input - * @example output - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_GEN_AI_TOKEN_TYPE = 'gen_ai.token.type' as const; - -/** - * Deprecated, use `messaging.operation.type` instead. - * - * @example publish - * @example create - * @example process - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - * - * @deprecated Replaced by `messaging.operation.type`. - */ -export const ATTR_MESSAGING_OPERATION = 'messaging.operation' as const; - -/** - * A string identifying the remoting system. See below for a list of well-known identifiers. - * - * @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const ATTR_RPC_SYSTEM = 'rpc.system' as const; - -/** - * Enum value "dynamodb" for attribute {@link ATTR_DB_SYSTEM}. - * - * Amazon DynamoDB - * - * @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - * - * @deprecated Replaced by `DB_SYSTEM_NAME_VALUE_DYNAMODB`. - */ -export const DB_SYSTEM_VALUE_DYNAMODB = 'dynamodb' as const; - -/** - * Enum value "dynamodb" for attribute ATTR_DB_SYSTEM_NAME. - * - * Amazon DynamoDB - * - * @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const DB_SYSTEM_NAME_VALUE_DYNAMODB = 'dynamodb' as const; - -/** - * Enum value "chat" for attribute {@link ATTR_GEN_AI_OPERATION_NAME}. - * - * Chat completion operation such as [OpenAI Chat API](https://platform.openai.com/docs/api-reference/chat) - * - * @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const GEN_AI_OPERATION_NAME_VALUE_CHAT = 'chat' as const; - -/** - * Enum value "aws.bedrock" for attribute {@link ATTR_GEN_AI_SYSTEM}. - * - * AWS Bedrock - * - * @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const GEN_AI_SYSTEM_VALUE_AWS_BEDROCK = 'aws.bedrock' as const; - -/** - * Enum value "input" for attribute {@link ATTR_GEN_AI_TOKEN_TYPE}. - * - * Input tokens (prompt, input, etc.) - * - * @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const GEN_AI_TOKEN_TYPE_VALUE_INPUT = 'input' as const; - -/** - * Enum value "output" for attribute {@link ATTR_GEN_AI_TOKEN_TYPE}. - * - * Output tokens (completion, response, etc.) - * - * @experimental This enum value is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const GEN_AI_TOKEN_TYPE_VALUE_OUTPUT = 'output' as const; - -/** - * GenAI operation duration. - * - * @experimental This metric is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const METRIC_GEN_AI_CLIENT_OPERATION_DURATION = 'gen_ai.client.operation.duration' as const; - -/** - * Number of input and output tokens used. - * - * @experimental This metric is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`. - */ -export const METRIC_GEN_AI_CLIENT_TOKEN_USAGE = 'gen_ai.client.token.usage' as const; diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/MessageAttributes.ts b/packages/aws-serverless/src/integration/aws/vendored/services/MessageAttributes.ts deleted file mode 100644 index b891e5880afc..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/MessageAttributes.ts +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { TextMapGetter, TextMapSetter, context, propagation, diag } from '@opentelemetry/api'; -import { uniq } from '@sentry/core'; -import type { SQS, SNS } from '../aws-sdk.types'; - -// https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-quotas.html -export const MAX_MESSAGE_ATTRIBUTES = 10; -class ContextSetter implements TextMapSetter { - set(carrier: SQS.MessageBodyAttributeMap | SNS.MessageAttributeMap, key: string, value: string) { - carrier[key] = { - DataType: 'String', - StringValue: value as string, - }; - } -} -export const contextSetter = new ContextSetter(); - -export interface AwsSdkContextObject { - [key: string]: { - StringValue?: string; - Value?: string; - }; -} - -class ContextGetter implements TextMapGetter { - keys(carrier: SQS.MessageBodyAttributeMap | SNS.MessageAttributeMap): string[] { - if (carrier == null) { - return []; - } - return Object.keys(carrier); - } - - get(carrier: AwsSdkContextObject, key: string): undefined | string | string[] { - return carrier?.[key]?.StringValue || carrier?.[key]?.Value; - } -} -export const contextGetter = new ContextGetter(); - -export const injectPropagationContext = ( - attributesMap?: SQS.MessageBodyAttributeMap | SNS.MessageAttributeMap, -): SQS.MessageBodyAttributeMap | SNS.MessageAttributeMap => { - const attributes = attributesMap ?? {}; - if (Object.keys(attributes).length + propagation.fields().length <= MAX_MESSAGE_ATTRIBUTES) { - propagation.inject(context.active(), attributes, contextSetter); - } else { - diag.warn( - 'aws-sdk instrumentation: cannot set context propagation on SQS/SNS message due to maximum amount of MessageAttributes', - ); - } - return attributes; -}; - -export const extractPropagationContext = (message: SQS.Message): AwsSdkContextObject | undefined => { - const propagationFields = propagation.fields(); - const hasPropagationFields = Object.keys(message.MessageAttributes || []).some(attr => - propagationFields.includes(attr), - ); - if (hasPropagationFields) { - return message.MessageAttributes; - } - return undefined; -}; - -export const addPropagationFieldsToAttributeNames = ( - messageAttributeNames: string[] = [], - propagationFields: string[], -) => { - return messageAttributeNames.length ? uniq([...messageAttributeNames, ...propagationFields]) : propagationFields; -}; diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/ServiceExtension.ts b/packages/aws-serverless/src/integration/aws/vendored/services/ServiceExtension.ts deleted file mode 100644 index ebc79830c19a..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/ServiceExtension.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { DiagLogger, Span, SpanAttributes } from '@opentelemetry/api'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types'; - -export interface RequestMetadata { - // isIncoming - if true, then the operation callback / promise should be bind with the operation's span - isIncoming: boolean; - // isStream - if true, then the response is a stream so the span should not be ended by the middleware. - // the ServiceExtension must end the span itself, generally by wrapping the stream and ending after it is - // consumed. - isStream?: boolean; - // eslint-disable-next-line typescript/no-deprecated - spanAttributes?: SpanAttributes; - spanName?: string; -} - -export interface ServiceExtension { - // called before request is sent, and before span is started - requestPreSpanHook: ( - request: NormalizedRequest, - config: AwsSdkInstrumentationConfig, - diag: DiagLogger, - ) => RequestMetadata; - - // called before request is sent, and after span is started - requestPostSpanHook?: (request: NormalizedRequest) => void; - - // called after response is received. If value is returned, it replaces the response output. - responseHook?: (response: NormalizedResponse, span: Span) => any | undefined; -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/ServicesExtensions.ts b/packages/aws-serverless/src/integration/aws/vendored/services/ServicesExtensions.ts deleted file mode 100644 index 0b6b71c30790..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/ServicesExtensions.ts +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Span, DiagLogger } from '@opentelemetry/api'; -import { ServiceExtension, RequestMetadata } from './ServiceExtension'; -import { SqsServiceExtension } from './sqs'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types'; -import { BedrockRuntimeServiceExtension } from './bedrock-runtime'; -import { DynamodbServiceExtension } from './dynamodb'; -import { SecretsManagerServiceExtension } from './secretsmanager'; -import { SnsServiceExtension } from './sns'; -import { StepFunctionsServiceExtension } from './stepfunctions'; -import { LambdaServiceExtension } from './lambda'; -import { S3ServiceExtension } from './s3'; -import { KinesisServiceExtension } from './kinesis'; - -export class ServicesExtensions implements ServiceExtension { - services: Map = new Map(); - - constructor() { - this.registerServices(); - } - - private registerServices() { - this.services.set('SecretsManager', new SecretsManagerServiceExtension()); - this.services.set('SFN', new StepFunctionsServiceExtension()); - this.services.set('SQS', new SqsServiceExtension()); - this.services.set('SNS', new SnsServiceExtension()); - this.services.set('DynamoDB', new DynamodbServiceExtension()); - this.services.set('Lambda', new LambdaServiceExtension()); - this.services.set('S3', new S3ServiceExtension()); - this.services.set('Kinesis', new KinesisServiceExtension()); - this.services.set('BedrockRuntime', new BedrockRuntimeServiceExtension()); - } - - requestPreSpanHook( - request: NormalizedRequest, - config: AwsSdkInstrumentationConfig, - diag: DiagLogger, - ): RequestMetadata { - const serviceExtension = this.services.get(request.serviceName); - if (!serviceExtension) - return { - isIncoming: false, - }; - return serviceExtension.requestPreSpanHook(request, config, diag); - } - - requestPostSpanHook(request: NormalizedRequest) { - const serviceExtension = this.services.get(request.serviceName); - if (!serviceExtension?.requestPostSpanHook) return; - return serviceExtension.requestPostSpanHook(request); - } - - responseHook(response: NormalizedResponse, span: Span) { - const serviceExtension = this.services.get(response.request.serviceName); - - return serviceExtension?.responseHook?.(response, span); - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/bedrock-runtime.ts b/packages/aws-serverless/src/integration/aws/vendored/services/bedrock-runtime.ts deleted file mode 100644 index 8eb956a66832..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/bedrock-runtime.ts +++ /dev/null @@ -1,547 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes, DiagLogger, diag, Span } from '@opentelemetry/api'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; -import { - GEN_AI_OPERATION_NAME, - GEN_AI_REQUEST_MAX_TOKENS, - GEN_AI_REQUEST_MODEL, - GEN_AI_REQUEST_TEMPERATURE, - GEN_AI_REQUEST_TOP_P, - GEN_AI_RESPONSE_FINISH_REASONS, - GEN_AI_SYSTEM, - GEN_AI_USAGE_INPUT_TOKENS, - GEN_AI_USAGE_OUTPUT_TOKENS, -} from '@sentry/conventions/attributes'; -import { - ATTR_GEN_AI_REQUEST_STOP_SEQUENCES, - GEN_AI_OPERATION_NAME_VALUE_CHAT, - GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, -} from '../semconv'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types'; - -// Simplified types inlined from @aws-sdk/client-bedrock-runtime -// Only the fields accessed by this instrumentation are included -interface TokenUsage { - inputTokens: number | undefined; - outputTokens: number | undefined; - totalTokens: number | undefined; -} - -interface ConverseStreamOutput { - messageStop?: { stopReason?: string }; - metadata?: { usage?: TokenUsage }; - [key: string]: any; -} - -export class BedrockRuntimeServiceExtension implements ServiceExtension { - private _diag: DiagLogger = diag; - - requestPreSpanHook( - request: NormalizedRequest, - config: AwsSdkInstrumentationConfig, - diag: DiagLogger, - ): RequestMetadata { - switch (request.commandName) { - case 'Converse': - return this.requestPreSpanHookConverse(request, config, diag, false); - case 'ConverseStream': - return this.requestPreSpanHookConverse(request, config, diag, true); - case 'InvokeModel': - return this.requestPreSpanHookInvokeModel(request, config, diag, false); - case 'InvokeModelWithResponseStream': - return this.requestPreSpanHookInvokeModel(request, config, diag, true); - } - - return { - isIncoming: false, - }; - } - - private requestPreSpanHookConverse( - request: NormalizedRequest, - config: AwsSdkInstrumentationConfig, - diag: DiagLogger, - isStream: boolean, - ): RequestMetadata { - let spanName = GEN_AI_OPERATION_NAME_VALUE_CHAT; - const spanAttributes: Attributes = { - // oxlint-disable-next-line typescript/no-deprecated - [GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, - [GEN_AI_OPERATION_NAME]: GEN_AI_OPERATION_NAME_VALUE_CHAT, - }; - - const modelId = request.commandInput.modelId; - if (modelId) { - spanAttributes[GEN_AI_REQUEST_MODEL] = modelId; - if (spanName) { - spanName += ` ${modelId}`; - } - } - - const inferenceConfig = request.commandInput.inferenceConfig; - if (inferenceConfig) { - const { maxTokens, temperature, topP, stopSequences } = inferenceConfig; - if (maxTokens !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = maxTokens; - } - if (temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = temperature; - } - if (topP !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = topP; - } - if (stopSequences !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = stopSequences; - } - } - - return { - spanName, - isIncoming: false, - isStream, - spanAttributes, - }; - } - - private requestPreSpanHookInvokeModel( - request: NormalizedRequest, - config: AwsSdkInstrumentationConfig, - diag: DiagLogger, - isStream: boolean, - ): RequestMetadata { - const spanAttributes: Attributes = { - // oxlint-disable-next-line typescript/no-deprecated - [GEN_AI_SYSTEM]: GEN_AI_SYSTEM_VALUE_AWS_BEDROCK, - // add operation name for InvokeModel API - }; - - const modelId = request.commandInput?.modelId; - if (modelId) { - spanAttributes[GEN_AI_REQUEST_MODEL] = modelId; - } - - if (request.commandInput?.body) { - const requestBody = JSON.parse(request.commandInput.body); - if (modelId.includes('amazon.titan')) { - if (requestBody.textGenerationConfig?.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.textGenerationConfig.temperature; - } - if (requestBody.textGenerationConfig?.topP !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.textGenerationConfig.topP; - } - if (requestBody.textGenerationConfig?.maxTokenCount !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.textGenerationConfig.maxTokenCount; - } - if (requestBody.textGenerationConfig?.stopSequences !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = requestBody.textGenerationConfig.stopSequences; - } - } else if (modelId.includes('amazon.nova')) { - if (requestBody.inferenceConfig?.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.inferenceConfig.temperature; - } - if (requestBody.inferenceConfig?.top_p !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.inferenceConfig.top_p; - } - if (requestBody.inferenceConfig?.max_new_tokens !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.inferenceConfig.max_new_tokens; - } - if (requestBody.inferenceConfig?.stopSequences !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = requestBody.inferenceConfig.stopSequences; - } - } else if (modelId.includes('anthropic.claude')) { - if (requestBody.max_tokens !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.max_tokens; - } - if (requestBody.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.temperature; - } - if (requestBody.top_p !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.top_p; - } - if (requestBody.stop_sequences !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = requestBody.stop_sequences; - } - } else if (modelId.includes('meta.llama')) { - if (requestBody.max_gen_len !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.max_gen_len; - } - if (requestBody.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.temperature; - } - if (requestBody.top_p !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.top_p; - } - // request for meta llama models does not contain stop_sequences field - } else if (modelId.includes('cohere.command-r')) { - if (requestBody.max_tokens !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.max_tokens; - } - if (requestBody.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.temperature; - } - if (requestBody.p !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.p; - } - if (requestBody.message !== undefined) { - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - spanAttributes[GEN_AI_USAGE_INPUT_TOKENS] = Math.ceil(requestBody.message.length / 6); - } - if (requestBody.stop_sequences !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = requestBody.stop_sequences; - } - } else if (modelId.includes('cohere.command')) { - if (requestBody.max_tokens !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.max_tokens; - } - if (requestBody.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.temperature; - } - if (requestBody.p !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.p; - } - if (requestBody.prompt !== undefined) { - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - spanAttributes[GEN_AI_USAGE_INPUT_TOKENS] = Math.ceil(requestBody.prompt.length / 6); - } - if (requestBody.stop_sequences !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = requestBody.stop_sequences; - } - } else if (modelId.includes('mistral')) { - if (requestBody.prompt !== undefined) { - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - spanAttributes[GEN_AI_USAGE_INPUT_TOKENS] = Math.ceil(requestBody.prompt.length / 6); - } - if (requestBody.max_tokens !== undefined) { - spanAttributes[GEN_AI_REQUEST_MAX_TOKENS] = requestBody.max_tokens; - } - if (requestBody.temperature !== undefined) { - spanAttributes[GEN_AI_REQUEST_TEMPERATURE] = requestBody.temperature; - } - if (requestBody.top_p !== undefined) { - spanAttributes[GEN_AI_REQUEST_TOP_P] = requestBody.top_p; - } - if (requestBody.stop !== undefined) { - spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES] = requestBody.stop; - } - } - } - - return { - isIncoming: false, - isStream, - spanAttributes, - }; - } - - responseHook(response: NormalizedResponse, span: Span) { - if (!span.isRecording()) { - return; - } - - switch (response.request.commandName) { - case 'Converse': - return this.responseHookConverse(response, span); - case 'ConverseStream': - return this.responseHookConverseStream(response, span); - case 'InvokeModel': - return this.responseHookInvokeModel(response, span); - case 'InvokeModelWithResponseStream': - return this.responseHookInvokeModelWithResponseStream(response, span); - } - } - - private responseHookConverse(response: NormalizedResponse, span: Span) { - const { stopReason, usage } = response.data; - - BedrockRuntimeServiceExtension.setStopReason(span, stopReason); - this.setUsage(response, span, usage); - } - - private responseHookConverseStream(response: NormalizedResponse, span: Span) { - return { - ...response.data, - // Wrap and replace the response stream to allow processing events to telemetry - // before yielding to the user. - stream: this.wrapConverseStreamResponse(response, response.data.stream, span), - }; - } - - private async *wrapConverseStreamResponse( - response: NormalizedResponse, - stream: AsyncIterable, - span: Span, - ) { - try { - let usage: TokenUsage | undefined; - for await (const item of stream) { - BedrockRuntimeServiceExtension.setStopReason(span, item.messageStop?.stopReason); - usage = item.metadata?.usage; - yield item; - } - this.setUsage(response, span, usage); - } finally { - span.end(); - } - } - - private static setStopReason(span: Span, stopReason: string | undefined) { - if (stopReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [stopReason]); - } - } - - private setUsage(response: NormalizedResponse, span: Span, usage: TokenUsage | undefined) { - if (usage) { - const { inputTokens, outputTokens } = usage; - if (inputTokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, inputTokens); - } - if (outputTokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, outputTokens); - } - } - } - - private responseHookInvokeModel(response: NormalizedResponse, span: Span) { - const currentModelId = response.request.commandInput?.modelId; - if (response.data?.body) { - const decodedResponseBody = new TextDecoder().decode(response.data.body); - const responseBody = JSON.parse(decodedResponseBody); - if (currentModelId.includes('amazon.titan')) { - if (responseBody.inputTextTokenCount !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, responseBody.inputTextTokenCount); - } - if (responseBody.results?.[0]?.tokenCount !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.results[0].tokenCount); - } - if (responseBody.results?.[0]?.completionReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.results[0].completionReason]); - } - } else if (currentModelId.includes('amazon.nova')) { - if (responseBody.usage !== undefined) { - if (responseBody.usage.inputTokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, responseBody.usage.inputTokens); - } - if (responseBody.usage.outputTokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.usage.outputTokens); - } - } - if (responseBody.stopReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stopReason]); - } - } else if (currentModelId.includes('anthropic.claude')) { - if (responseBody.usage?.input_tokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, responseBody.usage.input_tokens); - } - if (responseBody.usage?.output_tokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.usage.output_tokens); - } - if (responseBody.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stop_reason]); - } - } else if (currentModelId.includes('meta.llama')) { - if (responseBody.prompt_token_count !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, responseBody.prompt_token_count); - } - if (responseBody.generation_token_count !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.generation_token_count); - } - if (responseBody.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stop_reason]); - } - } else if (currentModelId.includes('cohere.command-r')) { - if (responseBody.text !== undefined) { - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, Math.ceil(responseBody.text.length / 6)); - } - if (responseBody.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.finish_reason]); - } - } else if (currentModelId.includes('cohere.command')) { - if (responseBody.generations?.[0]?.text !== undefined) { - span.setAttribute( - GEN_AI_USAGE_OUTPUT_TOKENS, - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - Math.ceil(responseBody.generations[0].text.length / 6), - ); - } - if (responseBody.generations?.[0]?.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.generations[0].finish_reason]); - } - } else if (currentModelId.includes('mistral')) { - if (responseBody.outputs?.[0]?.text !== undefined) { - span.setAttribute( - GEN_AI_USAGE_OUTPUT_TOKENS, - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - Math.ceil(responseBody.outputs[0].text.length / 6), - ); - } - if (responseBody.outputs?.[0]?.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.outputs[0].stop_reason]); - } - } - } - } - - private async responseHookInvokeModelWithResponseStream(response: NormalizedResponse, span: Span): Promise { - const stream = response.data?.body; - const modelId = response.request.commandInput?.modelId; - if (!stream || !modelId) return; - - // Replace the original response body with our instrumented stream. - // - Defers span.end() until the entire stream is consumed - // This ensures downstream consumers still receive the full stream correctly, - // while OpenTelemetry can record span attributes from streamed data. - response.data.body = async function* (this: BedrockRuntimeServiceExtension) { - try { - for await (const chunk of stream) { - const parsedChunk = this.parseChunk(chunk?.chunk?.bytes); - - if (!parsedChunk) { - // pass through - } else if (modelId.includes('amazon.titan')) { - BedrockRuntimeServiceExtension.recordTitanAttributes(parsedChunk, span); - } else if (modelId.includes('anthropic.claude')) { - BedrockRuntimeServiceExtension.recordClaudeAttributes(parsedChunk, span); - } else if (modelId.includes('amazon.nova')) { - BedrockRuntimeServiceExtension.recordNovaAttributes(parsedChunk, span); - } else if (modelId.includes('meta.llama')) { - BedrockRuntimeServiceExtension.recordLlamaAttributes(parsedChunk, span); - } else if (modelId.includes('cohere.command-r')) { - BedrockRuntimeServiceExtension.recordCohereRAttributes(parsedChunk, span); - } else if (modelId.includes('cohere.command')) { - BedrockRuntimeServiceExtension.recordCohereAttributes(parsedChunk, span); - } else if (modelId.includes('mistral')) { - BedrockRuntimeServiceExtension.recordMistralAttributes(parsedChunk, span); - } - yield chunk; - } - } finally { - span.end(); - } - }.bind(this)(); - return response.data; - } - - private parseChunk(bytes?: Uint8Array): any { - if (!bytes || !(bytes instanceof Uint8Array)) return null; - try { - const str = Buffer.from(bytes).toString('utf-8'); - return JSON.parse(str); - } catch (err) { - this._diag.warn('Failed to parse streamed chunk', err); - return null; - } - } - - private static recordNovaAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.metadata?.usage !== undefined) { - if (parsedChunk.metadata?.usage.inputTokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, parsedChunk.metadata.usage.inputTokens); - } - if (parsedChunk.metadata?.usage.outputTokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.metadata.usage.outputTokens); - } - } - if (parsedChunk.messageStop?.stopReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.messageStop.stopReason]); - } - } - - private static recordClaudeAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.message?.usage?.input_tokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, parsedChunk.message.usage.input_tokens); - } - if (parsedChunk.message?.usage?.output_tokens !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.message.usage.output_tokens); - } - if (parsedChunk.delta?.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.delta.stop_reason]); - } - } - - private static recordTitanAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.inputTextTokenCount !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, parsedChunk.inputTextTokenCount); - } - if (parsedChunk.totalOutputTextTokenCount !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.totalOutputTextTokenCount); - } - if (parsedChunk.completionReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.completionReason]); - } - } - private static recordLlamaAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.prompt_token_count !== undefined) { - span.setAttribute(GEN_AI_USAGE_INPUT_TOKENS, parsedChunk.prompt_token_count); - } - if (parsedChunk.generation_token_count !== undefined) { - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.generation_token_count); - } - if (parsedChunk.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.stop_reason]); - } - } - - private static recordMistralAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.outputs?.[0]?.text !== undefined) { - span.setAttribute( - GEN_AI_USAGE_OUTPUT_TOKENS, - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - Math.ceil(parsedChunk.outputs[0].text.length / 6), - ); - } - if (parsedChunk.outputs?.[0]?.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.outputs[0].stop_reason]); - } - } - - private static recordCohereAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.generations?.[0]?.text !== undefined) { - span.setAttribute( - GEN_AI_USAGE_OUTPUT_TOKENS, - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - Math.ceil(parsedChunk.generations[0].text.length / 6), - ); - } - if (parsedChunk.generations?.[0]?.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.generations[0].finish_reason]); - } - } - - private static recordCohereRAttributes(parsedChunk: any, span: Span) { - if (parsedChunk.text !== undefined) { - // NOTE: We approximate the token count since this value is not directly available in the body - // According to Bedrock docs they use (total_chars / 6) to approximate token count for pricing. - // https://docs.aws.amazon.com/bedrock/latest/userguide/model-customization-prepare.html - span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, Math.ceil(parsedChunk.text.length / 6)); - } - if (parsedChunk.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.finish_reason]); - } - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/dynamodb.ts b/packages/aws-serverless/src/integration/aws/vendored/services/dynamodb.ts deleted file mode 100644 index e75de3f74e0e..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/dynamodb.ts +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes, DiagLogger, Span } from '@opentelemetry/api'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; -import { - ATTR_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS, - ATTR_AWS_DYNAMODB_CONSISTENT_READ, - ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY, - ATTR_AWS_DYNAMODB_COUNT, - ATTR_AWS_DYNAMODB_EXCLUSIVE_START_TABLE, - ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES, - ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES, - ATTR_AWS_DYNAMODB_INDEX_NAME, - ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS, - ATTR_AWS_DYNAMODB_LIMIT, - ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES, - ATTR_AWS_DYNAMODB_PROJECTION, - ATTR_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY, - ATTR_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY, - ATTR_AWS_DYNAMODB_SCAN_FORWARD, - ATTR_AWS_DYNAMODB_SCANNED_COUNT, - ATTR_AWS_DYNAMODB_SEGMENT, - ATTR_AWS_DYNAMODB_SELECT, - ATTR_AWS_DYNAMODB_TABLE_COUNT, - ATTR_AWS_DYNAMODB_TABLE_NAMES, - ATTR_AWS_DYNAMODB_TOTAL_SEGMENTS, - DB_SYSTEM_VALUE_DYNAMODB, -} from '../semconv'; -import { DB_NAME, DB_OPERATION, DB_SYSTEM } from '@sentry/conventions/attributes'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types'; - -export class DynamodbServiceExtension implements ServiceExtension { - toArray(values: T | T[]): T[] { - return Array.isArray(values) ? values : [values]; - } - - requestPreSpanHook( - normalizedRequest: NormalizedRequest, - _config: AwsSdkInstrumentationConfig, - _diag: DiagLogger, - ): RequestMetadata { - const isIncoming = false; - const operation = normalizedRequest.commandName; - const tableName = normalizedRequest.commandInput?.TableName; - - const spanAttributes: Attributes = {}; - - // oxlint-disable-next-line typescript/no-deprecated - spanAttributes[DB_SYSTEM] = DB_SYSTEM_VALUE_DYNAMODB; - // oxlint-disable-next-line typescript/no-deprecated - spanAttributes[DB_NAME] = tableName; - // oxlint-disable-next-line typescript/no-deprecated - spanAttributes[DB_OPERATION] = operation; - - // normalizedRequest.commandInput.RequestItems) is undefined when no table names are returned - // keys in this object are the table names - if (normalizedRequest.commandInput?.TableName) { - // Necessary for commands with only 1 table name (example: CreateTable). Attribute is TableName not keys of RequestItems - // single table name returned for operations like CreateTable - spanAttributes[ATTR_AWS_DYNAMODB_TABLE_NAMES] = [normalizedRequest.commandInput.TableName]; - } else if (normalizedRequest.commandInput?.RequestItems) { - spanAttributes[ATTR_AWS_DYNAMODB_TABLE_NAMES] = Object.keys(normalizedRequest.commandInput.RequestItems); - } - - if (operation === 'CreateTable' || operation === 'UpdateTable') { - // only check for ProvisionedThroughput since ReadCapacityUnits and WriteCapacity units are required attributes - if (normalizedRequest.commandInput?.ProvisionedThroughput) { - spanAttributes[ATTR_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY] = - normalizedRequest.commandInput.ProvisionedThroughput.ReadCapacityUnits; - spanAttributes[ATTR_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY] = - normalizedRequest.commandInput.ProvisionedThroughput.WriteCapacityUnits; - } - } - - if (operation === 'GetItem' || operation === 'Scan' || operation === 'Query') { - if (normalizedRequest.commandInput?.ConsistentRead) { - spanAttributes[ATTR_AWS_DYNAMODB_CONSISTENT_READ] = normalizedRequest.commandInput.ConsistentRead; - } - } - - if (operation === 'Query' || operation === 'Scan') { - if (normalizedRequest.commandInput?.ProjectionExpression) { - spanAttributes[ATTR_AWS_DYNAMODB_PROJECTION] = normalizedRequest.commandInput.ProjectionExpression; - } - } - - if (operation === 'CreateTable') { - if (normalizedRequest.commandInput?.GlobalSecondaryIndexes) { - spanAttributes[ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES] = this.toArray( - normalizedRequest.commandInput.GlobalSecondaryIndexes, - ).map((x: { [DictionaryKey: string]: any }) => JSON.stringify(x)); - } - - if (normalizedRequest.commandInput?.LocalSecondaryIndexes) { - spanAttributes[ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES] = this.toArray( - normalizedRequest.commandInput.LocalSecondaryIndexes, - ).map((x: { [DictionaryKey: string]: any }) => JSON.stringify(x)); - } - } - - if (operation === 'ListTables' || operation === 'Query' || operation === 'Scan') { - if (normalizedRequest.commandInput?.Limit) { - spanAttributes[ATTR_AWS_DYNAMODB_LIMIT] = normalizedRequest.commandInput.Limit; - } - } - - if (operation === 'ListTables') { - if (normalizedRequest.commandInput?.ExclusiveStartTableName) { - spanAttributes[ATTR_AWS_DYNAMODB_EXCLUSIVE_START_TABLE] = - normalizedRequest.commandInput.ExclusiveStartTableName; - } - } - - if (operation === 'Query') { - if (normalizedRequest.commandInput?.ScanIndexForward) { - spanAttributes[ATTR_AWS_DYNAMODB_SCAN_FORWARD] = normalizedRequest.commandInput.ScanIndexForward; - } - - if (normalizedRequest.commandInput?.IndexName) { - spanAttributes[ATTR_AWS_DYNAMODB_INDEX_NAME] = normalizedRequest.commandInput.IndexName; - } - - if (normalizedRequest.commandInput?.Select) { - spanAttributes[ATTR_AWS_DYNAMODB_SELECT] = normalizedRequest.commandInput.Select; - } - } - - if (operation === 'Scan') { - if (normalizedRequest.commandInput?.Segment) { - spanAttributes[ATTR_AWS_DYNAMODB_SEGMENT] = normalizedRequest.commandInput?.Segment; - } - - if (normalizedRequest.commandInput?.TotalSegments) { - spanAttributes[ATTR_AWS_DYNAMODB_TOTAL_SEGMENTS] = normalizedRequest.commandInput?.TotalSegments; - } - - if (normalizedRequest.commandInput?.IndexName) { - spanAttributes[ATTR_AWS_DYNAMODB_INDEX_NAME] = normalizedRequest.commandInput.IndexName; - } - - if (normalizedRequest.commandInput?.Select) { - spanAttributes[ATTR_AWS_DYNAMODB_SELECT] = normalizedRequest.commandInput.Select; - } - } - - if (operation === 'UpdateTable') { - if (normalizedRequest.commandInput?.AttributeDefinitions) { - spanAttributes[ATTR_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS] = this.toArray( - normalizedRequest.commandInput.AttributeDefinitions, - ).map((x: { [DictionaryKey: string]: any }) => JSON.stringify(x)); - } - - if (normalizedRequest.commandInput?.GlobalSecondaryIndexUpdates) { - spanAttributes[ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES] = this.toArray( - normalizedRequest.commandInput.GlobalSecondaryIndexUpdates, - ).map((x: { [DictionaryKey: string]: any }) => JSON.stringify(x)); - } - } - - return { - isIncoming, - spanAttributes, - }; - } - - responseHook(response: NormalizedResponse, span: Span) { - if (response.data?.ConsumedCapacity) { - span.setAttribute( - ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY, - toArray(response.data.ConsumedCapacity).map((x: { [DictionaryKey: string]: any }) => JSON.stringify(x)), - ); - } - - if (response.data?.ItemCollectionMetrics) { - span.setAttribute( - ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS, - this.toArray(response.data.ItemCollectionMetrics).map((x: { [DictionaryKey: string]: any }) => - JSON.stringify(x), - ), - ); - } - - if (response.data?.TableNames) { - span.setAttribute(ATTR_AWS_DYNAMODB_TABLE_COUNT, response.data?.TableNames.length); - } - - if (response.data?.Count) { - span.setAttribute(ATTR_AWS_DYNAMODB_COUNT, response.data?.Count); - } - - if (response.data?.ScannedCount) { - span.setAttribute(ATTR_AWS_DYNAMODB_SCANNED_COUNT, response.data?.ScannedCount); - } - } -} - -function toArray(values: T | T[]): T[] { - return Array.isArray(values) ? values : [values]; -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/index.ts b/packages/aws-serverless/src/integration/aws/vendored/services/index.ts deleted file mode 100644 index ae57f23d25b5..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -export { ServicesExtensions } from './ServicesExtensions'; diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/kinesis.ts b/packages/aws-serverless/src/integration/aws/vendored/services/kinesis.ts deleted file mode 100644 index de60e1e52cee..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/kinesis.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes } from '@opentelemetry/api'; -import { AWS_KINESIS_STREAM_NAME } from '../enums'; -import { AwsSdkInstrumentationConfig, NormalizedRequest } from '../types'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; - -export class KinesisServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - const streamName = request.commandInput?.StreamName; - const spanAttributes: Attributes = {}; - - if (streamName) { - spanAttributes[AWS_KINESIS_STREAM_NAME] = streamName; - } - - const isIncoming = false; - - return { - isIncoming, - spanAttributes, - }; - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/lambda.ts b/packages/aws-serverless/src/integration/aws/vendored/services/lambda.ts deleted file mode 100644 index 87f20c0c107d..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/lambda.ts +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Span, diag, Attributes } from '@opentelemetry/api'; -import { ATTR_FAAS_INVOKED_NAME, ATTR_FAAS_INVOKED_PROVIDER, ATTR_FAAS_INVOKED_REGION } from '../semconv'; -import { ATTR_FAAS_EXECUTION } from '../semconv-obsolete'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; -import { context, propagation } from '@opentelemetry/api'; - -class LambdaCommands { - public static readonly Invoke: string = 'Invoke'; -} - -export class LambdaServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - const functionName = this.extractFunctionName(request.commandInput); - - let spanAttributes: Attributes = {}; - let spanName: string | undefined; - - switch (request.commandName) { - case 'Invoke': - spanAttributes = { - [ATTR_FAAS_INVOKED_NAME]: functionName, - [ATTR_FAAS_INVOKED_PROVIDER]: 'aws', - }; - if (request.region) { - spanAttributes[ATTR_FAAS_INVOKED_REGION] = request.region; - } - spanName = `${functionName} ${LambdaCommands.Invoke}`; - break; - } - return { - isIncoming: false, - spanAttributes, - spanName, - }; - } - - requestPostSpanHook = (request: NormalizedRequest) => { - switch (request.commandName) { - case LambdaCommands.Invoke: - { - if (request.commandInput) { - request.commandInput.ClientContext = injectLambdaPropagationContext(request.commandInput.ClientContext); - } - } - break; - } - }; - - responseHook(response: NormalizedResponse, span: Span) { - switch (response.request.commandName) { - case LambdaCommands.Invoke: - { - // oxlint-disable-next-line typescript/no-deprecated - span.setAttribute(ATTR_FAAS_EXECUTION, response.requestId); - } - break; - } - } - - extractFunctionName = (commandInput: Record): string => { - return commandInput?.FunctionName; - }; -} - -const injectLambdaPropagationContext = (clientContext: string | undefined): string | undefined => { - try { - const propagatedContext = {}; - propagation.inject(context.active(), propagatedContext); - - const parsedClientContext = clientContext ? JSON.parse(Buffer.from(clientContext, 'base64').toString('utf8')) : {}; - - const updatedClientContext = { - ...parsedClientContext, - custom: { - ...parsedClientContext.custom, - ...propagatedContext, - }, - }; - - const encodedClientContext = Buffer.from(JSON.stringify(updatedClientContext)).toString('base64'); - - // The length of client context is capped at 3583 bytes of base64 encoded data - // (https://docs.aws.amazon.com/lambda/latest/dg/API_Invoke.html#API_Invoke_RequestSyntax) - if (encodedClientContext.length > 3583) { - diag.warn( - 'lambda instrumentation: cannot set context propagation on lambda invoke parameters due to ClientContext length limitations.', - ); - return clientContext; - } - - return encodedClientContext; - } catch (e) { - diag.debug('lambda instrumentation: failed to set context propagation on ClientContext', e); - return clientContext; - } -}; diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/s3.ts b/packages/aws-serverless/src/integration/aws/vendored/services/s3.ts deleted file mode 100644 index aa0f74aed78a..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/s3.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes } from '@opentelemetry/api'; -import { AWS_S3_BUCKET } from '../enums'; -import { AwsSdkInstrumentationConfig, NormalizedRequest } from '../types'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; - -export class S3ServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - const bucketName = request.commandInput?.Bucket; - const spanAttributes: Attributes = {}; - - if (bucketName) { - spanAttributes[AWS_S3_BUCKET] = bucketName; - } - - const isIncoming = false; - - return { - isIncoming, - spanAttributes, - }; - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/secretsmanager.ts b/packages/aws-serverless/src/integration/aws/vendored/services/secretsmanager.ts deleted file mode 100644 index 95d11eec30f7..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/secretsmanager.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes, Span } from '@opentelemetry/api'; -import { ATTR_AWS_SECRETSMANAGER_SECRET_ARN } from '../semconv'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; -import { NormalizedRequest, NormalizedResponse, AwsSdkInstrumentationConfig } from '../types'; - -export class SecretsManagerServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - const secretId = request.commandInput?.SecretId; - const spanAttributes: Attributes = {}; - if (typeof secretId === 'string' && secretId.startsWith('arn:aws:secretsmanager:')) { - spanAttributes[ATTR_AWS_SECRETSMANAGER_SECRET_ARN] = secretId; - } - - return { - isIncoming: false, - spanAttributes, - }; - } - - responseHook(response: NormalizedResponse, span: Span): void { - const secretArn = response.data?.ARN; - if (secretArn) { - span.setAttribute(ATTR_AWS_SECRETSMANAGER_SECRET_ARN, secretArn); - } - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/sns.ts b/packages/aws-serverless/src/integration/aws/vendored/services/sns.ts deleted file mode 100644 index b1524a54c7bf..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/sns.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Span, Attributes } from '@opentelemetry/api'; -import { MESSAGING_SYSTEM, SENTRY_KIND } from '@sentry/conventions/attributes'; -import { ATTR_AWS_SNS_TOPIC_ARN } from '../semconv'; -import { - ATTR_MESSAGING_DESTINATION, - ATTR_MESSAGING_DESTINATION_KIND, - MESSAGING_DESTINATION_KIND_VALUE_TOPIC, -} from '../semconv-obsolete'; -import { NormalizedRequest, NormalizedResponse, AwsSdkInstrumentationConfig } from '../types'; -import { injectPropagationContext } from './MessageAttributes'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; - -export class SnsServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - let spanName = `SNS ${request.commandName}`; - const spanAttributes: Attributes = { - [MESSAGING_SYSTEM]: 'aws.sns', - [SENTRY_KIND]: 'client', - }; - - if (request.commandName === 'Publish') { - spanAttributes[SENTRY_KIND] = 'producer'; - - // eslint-disable-next-line typescript/no-deprecated - spanAttributes[ATTR_MESSAGING_DESTINATION_KIND] = MESSAGING_DESTINATION_KIND_VALUE_TOPIC; - const { TopicArn, TargetArn, PhoneNumber } = request.commandInput; - // eslint-disable-next-line typescript/no-deprecated - spanAttributes[ATTR_MESSAGING_DESTINATION] = this.extractDestinationName(TopicArn, TargetArn, PhoneNumber); - // ToDO: Use ATTR_MESSAGING_DESTINATION_NAME when implemented - spanAttributes['messaging.destination.name'] = TopicArn || TargetArn || PhoneNumber || 'unknown'; - - // eslint-disable-next-line typescript/no-deprecated - spanName = `${PhoneNumber ? 'phone_number' : spanAttributes[ATTR_MESSAGING_DESTINATION]} send`; - } - - const topicArn = request.commandInput?.TopicArn; - if (topicArn) { - spanAttributes[ATTR_AWS_SNS_TOPIC_ARN] = topicArn; - } - - return { - isIncoming: false, - spanAttributes, - spanName, - }; - } - - requestPostSpanHook(request: NormalizedRequest): void { - if (request.commandName === 'Publish') { - const origMessageAttributes = request.commandInput['MessageAttributes'] ?? {}; - if (origMessageAttributes) { - request.commandInput['MessageAttributes'] = injectPropagationContext(origMessageAttributes); - } - } - } - - responseHook(response: NormalizedResponse, span: Span): void { - const topicArn = response.data?.TopicArn; - if (topicArn) { - span.setAttribute(ATTR_AWS_SNS_TOPIC_ARN, topicArn); - } - } - - extractDestinationName(topicArn: string, targetArn: string, phoneNumber: string): string { - if (topicArn || targetArn) { - const arn = topicArn ?? targetArn; - try { - return arn.substring(arn.lastIndexOf(':') + 1); - } catch { - return arn; - } - } else if (phoneNumber) { - return phoneNumber; - } else { - return 'unknown'; - } - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/sqs.ts b/packages/aws-serverless/src/integration/aws/vendored/services/sqs.ts deleted file mode 100644 index 6c3e5b7e3a05..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/sqs.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Span, propagation, trace, ROOT_CONTEXT, Attributes } from '@opentelemetry/api'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; -import type { SQS } from '../aws-sdk.types'; -import { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } from '../types'; -import { - MESSAGING_BATCH_MESSAGE_COUNT, - MESSAGING_DESTINATION_NAME, - MESSAGING_MESSAGE_ID, - MESSAGING_OPERATION_TYPE, - MESSAGING_SYSTEM, - SENTRY_KIND, - URL_FULL, -} from '@sentry/conventions/attributes'; -import { - contextGetter, - extractPropagationContext, - injectPropagationContext, - addPropagationFieldsToAttributeNames, -} from './MessageAttributes'; - -export class SqsServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - const queueUrl = this.extractQueueUrl(request.commandInput); - const queueName = this.extractQueueNameFromUrl(queueUrl); - let spanName: string | undefined; - - const spanAttributes: Attributes = { - [MESSAGING_SYSTEM]: 'aws_sqs', - [MESSAGING_DESTINATION_NAME]: queueName, - [URL_FULL]: queueUrl, - [SENTRY_KIND]: 'client', - }; - - let isIncoming = false; - - switch (request.commandName) { - case 'ReceiveMessage': - { - isIncoming = true; - spanAttributes[SENTRY_KIND] = 'consumer'; - spanName = `${queueName} receive`; - spanAttributes[MESSAGING_OPERATION_TYPE] = 'receive'; - - request.commandInput.MessageAttributeNames = addPropagationFieldsToAttributeNames( - request.commandInput.MessageAttributeNames, - propagation.fields(), - ); - } - break; - - case 'SendMessage': - case 'SendMessageBatch': - spanAttributes[SENTRY_KIND] = 'producer'; - spanName = `${queueName} send`; - break; - } - - return { - isIncoming, - spanAttributes, - spanName, - }; - } - - requestPostSpanHook = (request: NormalizedRequest) => { - switch (request.commandName) { - case 'SendMessage': - { - const origMessageAttributes = request.commandInput['MessageAttributes'] ?? {}; - if (origMessageAttributes) { - request.commandInput['MessageAttributes'] = injectPropagationContext(origMessageAttributes); - } - } - break; - - case 'SendMessageBatch': - { - const entries = request.commandInput?.Entries; - if (Array.isArray(entries)) { - entries.forEach((messageParams: { MessageAttributes: SQS.MessageBodyAttributeMap }) => { - messageParams.MessageAttributes = injectPropagationContext(messageParams.MessageAttributes ?? {}); - }); - } - } - break; - } - }; - - responseHook = (response: NormalizedResponse, span: Span) => { - switch (response.request.commandName) { - case 'SendMessage': - span.setAttribute(MESSAGING_MESSAGE_ID, response?.data?.MessageId); - break; - - case 'SendMessageBatch': - // TODO: How should this be handled? - break; - - case 'ReceiveMessage': { - const messages: SQS.Message[] = response?.data?.Messages || []; - - span.setAttribute(MESSAGING_BATCH_MESSAGE_COUNT, messages.length); - - for (const message of messages) { - const propagatedContext = propagation.extract( - ROOT_CONTEXT, - extractPropagationContext(message), - contextGetter, - ); - - const spanContext = trace.getSpanContext(propagatedContext); - - if (spanContext) { - span.addLink({ - context: spanContext, - attributes: { - [MESSAGING_MESSAGE_ID]: message.MessageId, - }, - }); - } - } - break; - } - } - }; - - extractQueueUrl = (commandInput: Record): string => { - return commandInput?.QueueUrl; - }; - - extractQueueNameFromUrl = (queueUrl: string): string | undefined => { - if (!queueUrl) return undefined; - - const segments = queueUrl.split('/'); - if (segments.length === 0) return undefined; - - return segments[segments.length - 1]; - }; -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/services/stepfunctions.ts b/packages/aws-serverless/src/integration/aws/vendored/services/stepfunctions.ts deleted file mode 100644 index e79f785f1ba6..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/services/stepfunctions.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes } from '@opentelemetry/api'; -import { ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN, ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN } from '../semconv'; -import { RequestMetadata, ServiceExtension } from './ServiceExtension'; -import { NormalizedRequest, AwsSdkInstrumentationConfig } from '../types'; - -export class StepFunctionsServiceExtension implements ServiceExtension { - requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata { - const stateMachineArn = request.commandInput?.stateMachineArn; - const activityArn = request.commandInput?.activityArn; - const spanAttributes: Attributes = {}; - - if (stateMachineArn) { - spanAttributes[ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN] = stateMachineArn; - } - - if (activityArn) { - spanAttributes[ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN] = activityArn; - } - - return { - isIncoming: false, - spanAttributes, - }; - } -} diff --git a/packages/aws-serverless/src/integration/aws/vendored/types.ts b/packages/aws-serverless/src/integration/aws/vendored/types.ts deleted file mode 100644 index 6299839a616a..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/types.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { InstrumentationConfig } from '@opentelemetry/instrumentation'; - -export type CommandInput = Record; - -/** - * These are normalized request and response. - * They organize the relevant data in one interface which can be processed in a - * uniform manner in hooks - */ -export interface NormalizedRequest { - serviceName: string; - commandName: string; - commandInput: CommandInput; - region?: string; -} -export interface NormalizedResponse { - data: any; - request: NormalizedRequest; - requestId: string; -} - -export type AwsSdkInstrumentationConfig = InstrumentationConfig; diff --git a/packages/aws-serverless/src/integration/aws/vendored/utils.ts b/packages/aws-serverless/src/integration/aws/vendored/utils.ts deleted file mode 100644 index 8022dba1c68a..000000000000 --- a/packages/aws-serverless/src/integration/aws/vendored/utils.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright The OpenTelemetry Authors - * SPDX-License-Identifier: Apache-2.0 - * - * NOTICE from the Sentry authors: - * - Vendored from: https://github.com/open-telemetry/opentelemetry-js-contrib/tree/15ef7506553f631ea4181391e0c5725a56f0d082/packages/instrumentation-aws-sdk - * - Upstream version: @opentelemetry/instrumentation-aws-sdk@0.73.0 - */ - -import { Attributes, Context, context } from '@opentelemetry/api'; -import { RPC_METHOD, RPC_SERVICE } from '@sentry/conventions/attributes'; -import { ATTR_RPC_SYSTEM } from './semconv'; -import { CLOUD_REGION } from './enums'; -import { NormalizedRequest } from './types'; - -export const removeSuffixFromStringIfExists = (str: string, suffixToRemove: string): string => { - const suffixLength = suffixToRemove.length; - return str?.slice(-suffixLength) === suffixToRemove ? str.slice(0, str.length - suffixLength) : str; -}; - -export const normalizeV3Request = ( - serviceName: string, - commandNameWithSuffix: string, - commandInput: Record, - region: string | undefined, -): NormalizedRequest => { - return { - serviceName: serviceName?.replace(/\s+/g, ''), - commandName: removeSuffixFromStringIfExists(commandNameWithSuffix, 'Command'), - commandInput, - region, - }; -}; - -export const extractAttributesFromNormalizedRequest = (normalizedRequest: NormalizedRequest): Attributes => { - return { - [ATTR_RPC_SYSTEM]: 'aws-api', - [RPC_METHOD]: normalizedRequest.commandName, - [RPC_SERVICE]: normalizedRequest.serviceName, - [CLOUD_REGION]: normalizedRequest.region, - }; -}; - -export const bindPromise = ( - target: Promise, - contextForCallbacks: Context, - rebindCount = 1, -): Promise => { - const origThen = target.then; - type PromiseThenParameters = Parameters['then']>; - target.then = function ( - onFulfilled: PromiseThenParameters[0], - onRejected: PromiseThenParameters[1], - ): Promise { - const newOnFulfilled = context.bind(contextForCallbacks, onFulfilled); - const newOnRejected = context.bind(contextForCallbacks, onRejected); - const patchedPromise = (origThen.call as any)(this, newOnFulfilled, newOnRejected); - return rebindCount > 1 ? bindPromise(patchedPromise, contextForCallbacks, rebindCount - 1) : patchedPromise; - }; - return target; -};