From 017bfae38e3df7f8b20dcd9805efacffc2535a34 Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 15 Jul 2026 20:16:50 +0200 Subject: [PATCH 1/2] feat(server-utils): Port S3, Kinesis, DynamoDB, SecretsManager and StepFunctions aws-sdk extensions --- .oxlintrc.base.json | 10 +- .size-limit.js | 2 +- .../tracing-channel/aws-sdk/constants.ts | 46 ++++- .../aws-sdk/services/ServicesExtensions.ts | 13 +- .../aws-sdk/services/dynamodb.ts | 186 ++++++++++++++++++ .../aws-sdk/services/kinesis.ts | 20 ++ .../tracing-channel/aws-sdk/services/s3.ts | 20 ++ .../aws-sdk/services/secretsmanager.ts | 27 +++ .../aws-sdk/services/stepfunctions.ts | 25 +++ 9 files changed, 343 insertions(+), 6 deletions(-) create mode 100644 packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts create mode 100644 packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts create mode 100644 packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts create mode 100644 packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts create mode 100644 packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts diff --git a/.oxlintrc.base.json b/.oxlintrc.base.json index 5e1a40beb267..57e39bcc20dd 100644 --- a/.oxlintrc.base.json +++ b/.oxlintrc.base.json @@ -150,7 +150,15 @@ { "files": ["**/integrations/tracing-channel/aws-sdk/**/*.ts"], "rules": { - "typescript/no-explicit-any": "off" + "typescript/no-explicit-any": "off", + "typescript/no-unsafe-member-access": "off" + } + }, + { + "files": ["**/integrations/tracing-channel/aws-sdk/services/**/*.ts"], + "rules": { + "max-lines": "off", + "complexity": "off" } }, { diff --git a/.size-limit.js b/.size-limit.js index 53bd15c11bf6..fc6ddeb16c53 100644 --- a/.size-limit.js +++ b/.size-limit.js @@ -400,7 +400,7 @@ module.exports = [ import: createImport('init', 'experimentalUseDiagnosticsChannelInjection'), ignore: [...builtinModules, ...nodePrefixedBuiltinModules], gzip: true, - limit: '142 KB', + limit: '144 KB', disablePlugins: ['@size-limit/esbuild'], }, { diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts index 4d82a9c676c6..9ec240793f12 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts @@ -1,8 +1,48 @@ /** - * AWS-specific span constants used by the aws-sdk channel integration that are NOT covered by - * `@sentry/conventions/attributes` (attribute names that exist there are imported from there - * directly). Per-service files append their own such constants below. + * AWS-specific span attribute names used by the aws-sdk channel integration. + * + * These mirror the constants the OTel `@opentelemetry/instrumentation-aws-sdk` emits (some are + * unstable/obsolete OTel semantic conventions with no `ATTR_*` export in + * `@opentelemetry/semantic-conventions`), inlined here so the integration stays free of OTel deps. + * Attributes that exist in `@sentry/conventions/attributes` are imported from there instead; + * TODO(aws-sdk): the active attributes below are being added to sentry-conventions and should move + * to `@sentry/conventions/attributes` imports once a release containing them ships. */ /** The span origin every aws-sdk channel span carries, mirroring the uniform OTel `auto.otel.aws`. */ export const AWS_SDK_ORIGIN = 'auto.aws.orchestrion.aws_sdk'; + +export const ATTR_RPC_SYSTEM = 'rpc.system'; +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'; + +// DynamoDB +export const ATTR_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS = 'aws.dynamodb.attribute_definitions'; +export const ATTR_AWS_DYNAMODB_CONSISTENT_READ = 'aws.dynamodb.consistent_read'; +export const ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY = 'aws.dynamodb.consumed_capacity'; +export const ATTR_AWS_DYNAMODB_COUNT = 'aws.dynamodb.count'; +export const ATTR_AWS_DYNAMODB_EXCLUSIVE_START_TABLE = 'aws.dynamodb.exclusive_start_table'; +export const ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES = 'aws.dynamodb.global_secondary_indexes'; +export const ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES = 'aws.dynamodb.global_secondary_index_updates'; +export const ATTR_AWS_DYNAMODB_INDEX_NAME = 'aws.dynamodb.index_name'; +export const ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS = 'aws.dynamodb.item_collection_metrics'; +export const ATTR_AWS_DYNAMODB_LIMIT = 'aws.dynamodb.limit'; +export const ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES = 'aws.dynamodb.local_secondary_indexes'; +export const ATTR_AWS_DYNAMODB_PROJECTION = 'aws.dynamodb.projection'; +export const ATTR_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY = 'aws.dynamodb.provisioned_read_capacity'; +export const ATTR_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY = 'aws.dynamodb.provisioned_write_capacity'; +export const ATTR_AWS_DYNAMODB_SCANNED_COUNT = 'aws.dynamodb.scanned_count'; +export const ATTR_AWS_DYNAMODB_SCAN_FORWARD = 'aws.dynamodb.scan_forward'; +export const ATTR_AWS_DYNAMODB_SEGMENT = 'aws.dynamodb.segment'; +export const ATTR_AWS_DYNAMODB_SELECT = 'aws.dynamodb.select'; +export const ATTR_AWS_DYNAMODB_TABLE_COUNT = 'aws.dynamodb.table_count'; +export const ATTR_AWS_DYNAMODB_TABLE_NAMES = 'aws.dynamodb.table_names'; +export const ATTR_AWS_DYNAMODB_TOTAL_SEGMENTS = 'aws.dynamodb.total_segments'; +export const DB_SYSTEM_VALUE_DYNAMODB = 'dynamodb'; + +// SecretsManager / StepFunctions +export const ATTR_AWS_SECRETSMANAGER_SECRET_ARN = 'aws.secretsmanager.secret.arn'; +export const ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN = 'aws.step_functions.activity.arn'; +export const ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN = 'aws.step_functions.state_machine.arn'; diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/ServicesExtensions.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/ServicesExtensions.ts index 83d0573b184e..b98d402c9078 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/ServicesExtensions.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/ServicesExtensions.ts @@ -1,11 +1,22 @@ import type { Span } from '@sentry/core'; import type { NormalizedRequest, NormalizedResponse, RequestMetadata } from '../types'; +import { DynamodbServiceExtension } from './dynamodb'; +import { KinesisServiceExtension } from './kinesis'; +import { S3ServiceExtension } from './s3'; +import { SecretsManagerServiceExtension } from './secretsmanager'; import type { ServiceExtension } from './ServiceExtension'; +import { StepFunctionsServiceExtension } from './stepfunctions'; export class ServicesExtensions implements ServiceExtension { // Per-service extensions, keyed by the client's `serviceId` (e.g. `'S3'`). Services without a // registered extension still get the base rpc span from the subscriber. - private _services: Map = new Map(); + private _services: Map = new Map([ + ['SecretsManager', new SecretsManagerServiceExtension()], + ['SFN', new StepFunctionsServiceExtension()], + ['DynamoDB', new DynamodbServiceExtension()], + ['S3', new S3ServiceExtension()], + ['Kinesis', new KinesisServiceExtension()], + ]); public requestPreSpanHook(request: NormalizedRequest): RequestMetadata { const serviceExtension = this._services.get(request.serviceName); diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts new file mode 100644 index 000000000000..d74d47fc98a2 --- /dev/null +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts @@ -0,0 +1,186 @@ +import type { Span } from '@sentry/core'; +import { SPAN_KIND } from '@sentry/core'; +import { DB_NAME, DB_OPERATION, DB_SYSTEM } from '@sentry/conventions/attributes'; +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 '../constants'; +import type { NormalizedRequest, NormalizedResponse } from '../types'; +import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; + +function toArray(values: T | T[]): T[] { + return Array.isArray(values) ? values : [values]; +} + +export class DynamodbServiceExtension implements ServiceExtension { + public requestPreSpanHook(normalizedRequest: NormalizedRequest): RequestMetadata { + const operation = normalizedRequest.commandName; + const tableName = normalizedRequest.commandInput?.TableName; + + const spanAttributes: Record = {}; + + /* oxlint-disable typescript/no-deprecated -- old-semconv db.* attributes, matched to the OTel aws-sdk integration */ + spanAttributes[DB_SYSTEM] = DB_SYSTEM_VALUE_DYNAMODB; + spanAttributes[DB_NAME] = tableName; + spanAttributes[DB_OPERATION] = operation; + /* oxlint-enable typescript/no-deprecated */ + + // `RequestItems` is undefined when no table names are returned; its keys are the table names. + if (normalizedRequest.commandInput?.TableName) { + // Necessary for commands with only 1 table name (e.g. CreateTable). Attribute is `TableName`, not keys of `RequestItems`. + 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 WriteCapacityUnits 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] = toArray( + normalizedRequest.commandInput.GlobalSecondaryIndexes, + ).map((x: unknown) => JSON.stringify(x)); + } + + if (normalizedRequest.commandInput?.LocalSecondaryIndexes) { + spanAttributes[ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES] = toArray( + normalizedRequest.commandInput.LocalSecondaryIndexes, + ).map((x: unknown) => 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] = toArray( + normalizedRequest.commandInput.AttributeDefinitions, + ).map((x: unknown) => JSON.stringify(x)); + } + + if (normalizedRequest.commandInput?.GlobalSecondaryIndexUpdates) { + spanAttributes[ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES] = toArray( + normalizedRequest.commandInput.GlobalSecondaryIndexUpdates, + ).map((x: unknown) => JSON.stringify(x)); + } + } + + return { + spanAttributes, + spanKind: SPAN_KIND.CLIENT, + // Matches what the exporter infers from `db.system` for the OTel DynamoDB spans. + spanOp: 'db', + }; + } + + public responseHook(response: NormalizedResponse, span: Span): void { + if (response.data?.ConsumedCapacity) { + span.setAttribute( + ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY, + toArray(response.data.ConsumedCapacity).map((x: unknown) => JSON.stringify(x)), + ); + } + + if (response.data?.ItemCollectionMetrics) { + span.setAttribute( + ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS, + toArray(response.data.ItemCollectionMetrics).map((x: unknown) => 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); + } + } +} diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts new file mode 100644 index 000000000000..aee76d924bdb --- /dev/null +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts @@ -0,0 +1,20 @@ +import { SPAN_KIND } from '@sentry/core'; +import { AWS_KINESIS_STREAM_NAME } from '../constants'; +import type { NormalizedRequest } from '../types'; +import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; + +export class KinesisServiceExtension implements ServiceExtension { + public requestPreSpanHook(request: NormalizedRequest): RequestMetadata { + const streamName = request.commandInput?.StreamName; + const spanAttributes: Record = {}; + + if (streamName) { + spanAttributes[AWS_KINESIS_STREAM_NAME] = streamName; + } + + return { + spanAttributes, + spanKind: SPAN_KIND.CLIENT, + }; + } +} diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts new file mode 100644 index 000000000000..1719c8e77d62 --- /dev/null +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts @@ -0,0 +1,20 @@ +import { SPAN_KIND } from '@sentry/core'; +import { AWS_S3_BUCKET } from '../constants'; +import type { NormalizedRequest } from '../types'; +import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; + +export class S3ServiceExtension implements ServiceExtension { + public requestPreSpanHook(request: NormalizedRequest): RequestMetadata { + const bucketName = request.commandInput?.Bucket; + const spanAttributes: Record = {}; + + if (bucketName) { + spanAttributes[AWS_S3_BUCKET] = bucketName; + } + + return { + spanAttributes, + spanKind: SPAN_KIND.CLIENT, + }; + } +} diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts new file mode 100644 index 000000000000..e10378815ffe --- /dev/null +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts @@ -0,0 +1,27 @@ +import type { Span } from '@sentry/core'; +import { SPAN_KIND } from '@sentry/core'; +import { ATTR_AWS_SECRETSMANAGER_SECRET_ARN } from '../constants'; +import type { NormalizedRequest, NormalizedResponse } from '../types'; +import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; + +export class SecretsManagerServiceExtension implements ServiceExtension { + public requestPreSpanHook(request: NormalizedRequest): RequestMetadata { + const secretId = request.commandInput?.SecretId; + const spanAttributes: Record = {}; + if (typeof secretId === 'string' && secretId.startsWith('arn:aws:secretsmanager:')) { + spanAttributes[ATTR_AWS_SECRETSMANAGER_SECRET_ARN] = secretId; + } + + return { + spanAttributes, + spanKind: SPAN_KIND.CLIENT, + }; + } + + public 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/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts new file mode 100644 index 000000000000..b08f452288b7 --- /dev/null +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts @@ -0,0 +1,25 @@ +import { SPAN_KIND } from '@sentry/core'; +import { ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN, ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN } from '../constants'; +import type { NormalizedRequest } from '../types'; +import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; + +export class StepFunctionsServiceExtension implements ServiceExtension { + public requestPreSpanHook(request: NormalizedRequest): RequestMetadata { + const stateMachineArn = request.commandInput?.stateMachineArn; + const activityArn = request.commandInput?.activityArn; + const spanAttributes: Record = {}; + + if (stateMachineArn) { + spanAttributes[ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN] = stateMachineArn; + } + + if (activityArn) { + spanAttributes[ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN] = activityArn; + } + + return { + spanAttributes, + spanKind: SPAN_KIND.CLIENT, + }; + } +} From 40bde8d7623083f79ade0b145690853606ccdd4f Mon Sep 17 00:00:00 2001 From: Andrei Borza Date: Wed, 15 Jul 2026 18:58:09 +0200 Subject: [PATCH 2/2] Import S3/Kinesis/DynamoDB/SecretsManager/StepFunctions attributes from @sentry/conventions --- .../tracing-channel/aws-sdk/constants.ts | 45 ++--------------- .../aws-sdk/services/dynamodb.ts | 50 ++++++++++--------- .../aws-sdk/services/kinesis.ts | 3 +- .../tracing-channel/aws-sdk/services/s3.ts | 2 +- .../aws-sdk/services/secretsmanager.ts | 2 +- .../aws-sdk/services/stepfunctions.ts | 5 +- 6 files changed, 38 insertions(+), 69 deletions(-) diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts index 9ec240793f12..320c24540f0a 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/constants.ts @@ -1,48 +1,11 @@ /** - * AWS-specific span attribute names used by the aws-sdk channel integration. - * - * These mirror the constants the OTel `@opentelemetry/instrumentation-aws-sdk` emits (some are - * unstable/obsolete OTel semantic conventions with no `ATTR_*` export in - * `@opentelemetry/semantic-conventions`), inlined here so the integration stays free of OTel deps. - * Attributes that exist in `@sentry/conventions/attributes` are imported from there instead; - * TODO(aws-sdk): the active attributes below are being added to sentry-conventions and should move - * to `@sentry/conventions/attributes` imports once a release containing them ships. + * AWS-specific span constants used by the aws-sdk channel integration that are NOT covered by + * `@sentry/conventions/attributes` (attribute names that exist there are imported from there + * directly). Per-service files append their own such constants below. */ /** The span origin every aws-sdk channel span carries, mirroring the uniform OTel `auto.otel.aws`. */ export const AWS_SDK_ORIGIN = 'auto.aws.orchestrion.aws_sdk'; -export const ATTR_RPC_SYSTEM = 'rpc.system'; -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'; - -// DynamoDB -export const ATTR_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS = 'aws.dynamodb.attribute_definitions'; -export const ATTR_AWS_DYNAMODB_CONSISTENT_READ = 'aws.dynamodb.consistent_read'; -export const ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY = 'aws.dynamodb.consumed_capacity'; -export const ATTR_AWS_DYNAMODB_COUNT = 'aws.dynamodb.count'; -export const ATTR_AWS_DYNAMODB_EXCLUSIVE_START_TABLE = 'aws.dynamodb.exclusive_start_table'; -export const ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES = 'aws.dynamodb.global_secondary_indexes'; -export const ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES = 'aws.dynamodb.global_secondary_index_updates'; -export const ATTR_AWS_DYNAMODB_INDEX_NAME = 'aws.dynamodb.index_name'; -export const ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS = 'aws.dynamodb.item_collection_metrics'; -export const ATTR_AWS_DYNAMODB_LIMIT = 'aws.dynamodb.limit'; -export const ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES = 'aws.dynamodb.local_secondary_indexes'; -export const ATTR_AWS_DYNAMODB_PROJECTION = 'aws.dynamodb.projection'; -export const ATTR_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY = 'aws.dynamodb.provisioned_read_capacity'; -export const ATTR_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY = 'aws.dynamodb.provisioned_write_capacity'; -export const ATTR_AWS_DYNAMODB_SCANNED_COUNT = 'aws.dynamodb.scanned_count'; -export const ATTR_AWS_DYNAMODB_SCAN_FORWARD = 'aws.dynamodb.scan_forward'; -export const ATTR_AWS_DYNAMODB_SEGMENT = 'aws.dynamodb.segment'; -export const ATTR_AWS_DYNAMODB_SELECT = 'aws.dynamodb.select'; -export const ATTR_AWS_DYNAMODB_TABLE_COUNT = 'aws.dynamodb.table_count'; -export const ATTR_AWS_DYNAMODB_TABLE_NAMES = 'aws.dynamodb.table_names'; -export const ATTR_AWS_DYNAMODB_TOTAL_SEGMENTS = 'aws.dynamodb.total_segments'; +/** DynamoDB `db.system` value (an attribute value, not a key, so not covered by conventions). */ export const DB_SYSTEM_VALUE_DYNAMODB = 'dynamodb'; - -// SecretsManager / StepFunctions -export const ATTR_AWS_SECRETSMANAGER_SECRET_ARN = 'aws.secretsmanager.secret.arn'; -export const ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN = 'aws.step_functions.activity.arn'; -export const ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN = 'aws.step_functions.state_machine.arn'; diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts index d74d47fc98a2..f9276fc20d96 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/dynamodb.ts @@ -1,30 +1,32 @@ import type { Span } from '@sentry/core'; import { SPAN_KIND } from '@sentry/core'; -import { DB_NAME, DB_OPERATION, DB_SYSTEM } from '@sentry/conventions/attributes'; 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 '../constants'; + AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS as ATTR_AWS_DYNAMODB_ATTRIBUTE_DEFINITIONS, + AWS_DYNAMODB_CONSISTENT_READ as ATTR_AWS_DYNAMODB_CONSISTENT_READ, + AWS_DYNAMODB_CONSUMED_CAPACITY as ATTR_AWS_DYNAMODB_CONSUMED_CAPACITY, + AWS_DYNAMODB_COUNT as ATTR_AWS_DYNAMODB_COUNT, + AWS_DYNAMODB_EXCLUSIVE_START_TABLE as ATTR_AWS_DYNAMODB_EXCLUSIVE_START_TABLE, + AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES as ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEX_UPDATES, + AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES as ATTR_AWS_DYNAMODB_GLOBAL_SECONDARY_INDEXES, + AWS_DYNAMODB_INDEX_NAME as ATTR_AWS_DYNAMODB_INDEX_NAME, + AWS_DYNAMODB_ITEM_COLLECTION_METRICS as ATTR_AWS_DYNAMODB_ITEM_COLLECTION_METRICS, + AWS_DYNAMODB_LIMIT as ATTR_AWS_DYNAMODB_LIMIT, + AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES as ATTR_AWS_DYNAMODB_LOCAL_SECONDARY_INDEXES, + AWS_DYNAMODB_PROJECTION as ATTR_AWS_DYNAMODB_PROJECTION, + AWS_DYNAMODB_PROVISIONED_READ_CAPACITY as ATTR_AWS_DYNAMODB_PROVISIONED_READ_CAPACITY, + AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY as ATTR_AWS_DYNAMODB_PROVISIONED_WRITE_CAPACITY, + AWS_DYNAMODB_SCAN_FORWARD as ATTR_AWS_DYNAMODB_SCAN_FORWARD, + AWS_DYNAMODB_SCANNED_COUNT as ATTR_AWS_DYNAMODB_SCANNED_COUNT, + AWS_DYNAMODB_SEGMENT as ATTR_AWS_DYNAMODB_SEGMENT, + AWS_DYNAMODB_SELECT as ATTR_AWS_DYNAMODB_SELECT, + AWS_DYNAMODB_TABLE_COUNT as ATTR_AWS_DYNAMODB_TABLE_COUNT, + AWS_DYNAMODB_TABLE_NAMES as ATTR_AWS_DYNAMODB_TABLE_NAMES, + AWS_DYNAMODB_TOTAL_SEGMENTS as ATTR_AWS_DYNAMODB_TOTAL_SEGMENTS, + DB_NAME, + DB_OPERATION, + DB_SYSTEM, +} from '@sentry/conventions/attributes'; +import { DB_SYSTEM_VALUE_DYNAMODB } from '../constants'; import type { NormalizedRequest, NormalizedResponse } from '../types'; import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts index aee76d924bdb..22599882d443 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/kinesis.ts @@ -1,5 +1,5 @@ import { SPAN_KIND } from '@sentry/core'; -import { AWS_KINESIS_STREAM_NAME } from '../constants'; +import { _AWS_KINESIS_STREAM_NAME as AWS_KINESIS_STREAM_NAME } from '@sentry/conventions/attributes'; import type { NormalizedRequest } from '../types'; import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; @@ -9,6 +9,7 @@ export class KinesisServiceExtension implements ServiceExtension { const spanAttributes: Record = {}; if (streamName) { + // oxlint-disable-next-line typescript/no-deprecated -- old-semconv aws.kinesis.stream.name, matched to the OTel aws-sdk integration spanAttributes[AWS_KINESIS_STREAM_NAME] = streamName; } diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts index 1719c8e77d62..24062efe3cd8 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/s3.ts @@ -1,5 +1,5 @@ import { SPAN_KIND } from '@sentry/core'; -import { AWS_S3_BUCKET } from '../constants'; +import { AWS_S3_BUCKET } from '@sentry/conventions/attributes'; import type { NormalizedRequest } from '../types'; import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts index e10378815ffe..b73318ef23b8 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/secretsmanager.ts @@ -1,6 +1,6 @@ import type { Span } from '@sentry/core'; import { SPAN_KIND } from '@sentry/core'; -import { ATTR_AWS_SECRETSMANAGER_SECRET_ARN } from '../constants'; +import { AWS_SECRETSMANAGER_SECRET_ARN as ATTR_AWS_SECRETSMANAGER_SECRET_ARN } from '@sentry/conventions/attributes'; import type { NormalizedRequest, NormalizedResponse } from '../types'; import type { RequestMetadata, ServiceExtension } from './ServiceExtension'; diff --git a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts index b08f452288b7..05afa34d6a39 100644 --- a/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts +++ b/packages/server-utils/src/integrations/tracing-channel/aws-sdk/services/stepfunctions.ts @@ -1,5 +1,8 @@ import { SPAN_KIND } from '@sentry/core'; -import { ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN, ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN } from '../constants'; +import { + AWS_STEP_FUNCTIONS_ACTIVITY_ARN as ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN, + AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN as ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN, +} from '@sentry/conventions/attributes'; import type { NormalizedRequest } from '../types'; import type { RequestMetadata, ServiceExtension } from './ServiceExtension';