Skip to content

Commit 87ec407

Browse files
authored
Merge branch 'aws-observability:main' into main
2 parents 04a5ffc + fec9390 commit 87ec407

26 files changed

+2715
-281
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ RUN npm install aws-aws-distro-opentelemetry-node-autoinstrumentation-$(node -p
1818
RUN npm install
1919

2020
# Stage 2: Build the cp-utility binary
21-
FROM public.ecr.aws/docker/library/rust:1.75 as builder
21+
FROM public.ecr.aws/docker/library/rust:1.81 as builder
2222

2323
WORKDIR /usr/src/cp-utility
2424
COPY ./tools/cp-utility .
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
build
22
node_modules
33
.eslintrc.js
4-
version.ts
4+
version.ts
5+
src/third-party

aws-distro-opentelemetry-node-autoinstrumentation/package.json

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,18 @@
3131
"prepublishOnly": "npm run compile",
3232
"tdd": "yarn test -- --watch-extensions ts --watch",
3333
"test": "nyc ts-mocha --timeout 10000 -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/*.ts'",
34-
"test:coverage": "nyc --all --check-coverage --functions 95 --lines 95 ts-mocha --timeout 10000 -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/*.ts'",
34+
"test:coverage": "nyc --check-coverage --functions 95 --lines 95 ts-mocha --timeout 10000 -p tsconfig.json --require '@opentelemetry/contrib-test-utils' 'test/**/*.ts'",
3535
"watch": "tsc -w"
3636
},
37+
"nyc": {
38+
"all": true,
39+
"include": [
40+
"src/**/*.ts"
41+
],
42+
"exclude": [
43+
"src/third-party/**/*.ts"
44+
]
45+
},
3746
"bugs": {
3847
"url": "https://github.com/aws-observability/aws-otel-js-instrumentation/issues"
3948
},
@@ -64,7 +73,11 @@
6473
"@aws-sdk/client-bedrock-agent-runtime": "3.632.0",
6574
"@aws-sdk/client-bedrock-runtime": "3.632.0",
6675
"@aws-sdk/client-kinesis": "3.632.0",
76+
"@aws-sdk/client-lambda": "^3.632.0",
6777
"@aws-sdk/client-s3": "3.632.0",
78+
"@aws-sdk/client-secrets-manager": "^3.632.0",
79+
"@aws-sdk/client-sfn": "^3.632.0",
80+
"@aws-sdk/client-sns": "^3.632.0",
6881
"@opentelemetry/contrib-test-utils": "0.41.0",
6982
"@types/mocha": "7.0.2",
7083
"@types/node": "18.6.5",

aws-distro-opentelemetry-node-autoinstrumentation/src/aws-attribute-keys.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export const AWS_ATTRIBUTE_KEYS: { [key: string]: string } = {
1414
AWS_REMOTE_RESOURCE_IDENTIFIER: 'aws.remote.resource.identifier',
1515
AWS_SDK_DESCENDANT: 'aws.sdk.descendant',
1616
AWS_CONSUMER_PARENT_SPAN_KIND: 'aws.consumer.parent.span.kind',
17+
AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER: 'aws.remote.resource.cfn.primary.identifier',
1718

1819
AWS_REMOTE_TARGET: 'aws.remote.target',
1920
AWS_REMOTE_DB_USER: 'aws.remote.db.user',
@@ -35,4 +36,12 @@ export const AWS_ATTRIBUTE_KEYS: { [key: string]: string } = {
3536
AWS_BEDROCK_KNOWLEDGE_BASE_ID: 'aws.bedrock.knowledge_base.id',
3637
AWS_BEDROCK_AGENT_ID: 'aws.bedrock.agent.id',
3738
AWS_BEDROCK_GUARDRAIL_ID: 'aws.bedrock.guardrail.id',
39+
AWS_BEDROCK_GUARDRAIL_ARN: 'aws.bedrock.guardrail.arn',
40+
AWS_SNS_TOPIC_ARN: 'aws.sns.topic.arn',
41+
AWS_SECRETSMANAGER_SECRET_ARN: 'aws.secretsmanager.secret.arn',
42+
AWS_STEPFUNCTIONS_STATEMACHINE_ARN: 'aws.stepfunctions.state_machine.arn',
43+
AWS_STEPFUNCTIONS_ACTIVITY_ARN: 'aws.stepfunctions.activity.arn',
44+
AWS_LAMBDA_FUNCTION_NAME: 'aws.lambda.function.name',
45+
AWS_LAMBDA_RESOURCE_MAPPING_ID: 'aws.lambda.resource_mapping.id',
46+
AWS_LAMBDA_FUNCTION_ARN: 'aws.lambda.function.arn',
3847
};

aws-distro-opentelemetry-node-autoinstrumentation/src/aws-metric-attribute-generator.ts

Lines changed: 74 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ const NORMALIZED_DYNAMO_DB_SERVICE_NAME: string = 'AWS::DynamoDB';
5555
const NORMALIZED_KINESIS_SERVICE_NAME: string = 'AWS::Kinesis';
5656
const NORMALIZED_S3_SERVICE_NAME: string = 'AWS::S3';
5757
const NORMALIZED_SQS_SERVICE_NAME: string = 'AWS::SQS';
58+
const NORMALIZED_SNS_SERVICE_NAME: string = 'AWS::SNS';
59+
const NORMALIZED_SECRETSMANAGER_SERVICE_NAME = 'AWS::SecretsManager';
60+
const NORMALIZED_STEPFUNCTIONS_SERVICE_NAME = 'AWS::StepFunctions';
61+
const NORMALIZED_LAMBDA_SERVICE_NAME = 'AWS::Lambda';
5862
const NORMALIZED_BEDROCK_SERVICE_NAME: string = 'AWS::Bedrock';
5963
const NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME: string = 'AWS::BedrockRuntime';
6064

@@ -330,6 +334,8 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
330334
BedrockAgent: NORMALIZED_BEDROCK_SERVICE_NAME,
331335
BedrockAgentRuntime: NORMALIZED_BEDROCK_SERVICE_NAME,
332336
BedrockRuntime: NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME,
337+
SecretsManager: NORMALIZED_SECRETSMANAGER_SERVICE_NAME,
338+
SFN: NORMALIZED_STEPFUNCTIONS_SERVICE_NAME,
333339
};
334340
return awsSdkServiceMapping[serviceName] || 'AWS::' + serviceName;
335341
}
@@ -350,6 +356,7 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
350356
private static setRemoteResourceTypeAndIdentifier(span: ReadableSpan, attributes: Attributes): void {
351357
let remoteResourceType: AttributeValue | undefined;
352358
let remoteResourceIdentifier: AttributeValue | undefined;
359+
let cloudFormationIdentifier: AttributeValue | undefined;
353360

354361
if (AwsSpanProcessingUtil.isAwsSDKSpan(span)) {
355362
const awsTableNames: AttributeValue | undefined = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES];
@@ -370,16 +377,56 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
370377
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
371378
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_S3_BUCKET]
372379
);
380+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN)) {
381+
const snsArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN];
382+
383+
remoteResourceType = NORMALIZED_SNS_SERVICE_NAME + '::Topic';
384+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
385+
this.extractResourceNameFromArn(snsArn)
386+
);
387+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(snsArn);
388+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN)) {
389+
const secretsArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN];
390+
391+
remoteResourceType = NORMALIZED_SECRETSMANAGER_SERVICE_NAME + '::Secret';
392+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
393+
this.extractResourceNameFromArn(secretsArn)
394+
);
395+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(secretsArn);
396+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN)) {
397+
const stateMachineArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN];
398+
399+
remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::StateMachine';
400+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
401+
this.extractResourceNameFromArn(stateMachineArn)
402+
);
403+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(stateMachineArn);
404+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN)) {
405+
const activityArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN];
406+
407+
remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::Activity';
408+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
409+
this.extractResourceNameFromArn(activityArn)
410+
);
411+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(activityArn);
412+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_RESOURCE_MAPPING_ID)) {
413+
remoteResourceType = NORMALIZED_LAMBDA_SERVICE_NAME + '::EventSourceMapping';
414+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
415+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_RESOURCE_MAPPING_ID]
416+
);
373417
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME)) {
374418
remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue';
375419
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
376420
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME]
377421
);
378422
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL)) {
379-
remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue';
380-
remoteResourceIdentifier = SqsUrlParser.getQueueName(
381-
AwsMetricAttributeGenerator.escapeDelimiters(span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL])
423+
const sqsQueueUrl = AwsMetricAttributeGenerator.escapeDelimiters(
424+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_URL]
382425
);
426+
427+
remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue';
428+
remoteResourceIdentifier = SqsUrlParser.getQueueName(sqsQueueUrl);
429+
cloudFormationIdentifier = sqsQueueUrl;
383430
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_AGENT_ID)) {
384431
remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Agent';
385432
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
@@ -390,11 +437,17 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
390437
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
391438
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]
392439
);
440+
cloudFormationIdentifier = `${AwsMetricAttributeGenerator.escapeDelimiters(
441+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]
442+
)}|${remoteResourceIdentifier}`;
393443
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID)) {
394444
remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::Guardrail';
395445
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
396446
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID]
397447
);
448+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
449+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN]
450+
);
398451
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID)) {
399452
remoteResourceType = NORMALIZED_BEDROCK_SERVICE_NAME + '::KnowledgeBase';
400453
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
@@ -414,6 +467,14 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
414467
if (remoteResourceType !== undefined && remoteResourceIdentifier !== undefined) {
415468
attributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_RESOURCE_TYPE] = remoteResourceType;
416469
attributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_RESOURCE_IDENTIFIER] = remoteResourceIdentifier;
470+
471+
if (AwsSpanProcessingUtil.isAwsSDKSpan(span)) {
472+
if (cloudFormationIdentifier === undefined) {
473+
cloudFormationIdentifier = remoteResourceIdentifier;
474+
}
475+
476+
attributes[AWS_ATTRIBUTE_KEYS.AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER] = cloudFormationIdentifier;
477+
}
417478
}
418479
}
419480

@@ -532,6 +593,16 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
532593
return input.split('^').join('^^').split('|').join('^|');
533594
}
534595

596+
// Extracts the name of the resource from an arn
597+
private static extractResourceNameFromArn(attribute: AttributeValue | undefined): string | undefined {
598+
if (typeof attribute === 'string' && attribute.startsWith('arn:aws:')) {
599+
const split = attribute.split(':');
600+
return split[split.length - 1];
601+
}
602+
603+
return undefined;
604+
}
605+
535606
/** Span kind is needed for differentiating metrics in the EMF exporter */
536607
private static setSpanKindForService(span: ReadableSpan, attributes: Attributes): void {
537608
let spanKind: string = SpanKind[span.kind];

aws-distro-opentelemetry-node-autoinstrumentation/src/patches/aws/services/bedrock.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ const AGENT_ID: string = 'agentId';
1515
const KNOWLEDGE_BASE_ID: string = 'knowledgeBaseId';
1616
const DATA_SOURCE_ID: string = 'dataSourceId';
1717
const GUARDRAIL_ID: string = 'guardrailId';
18+
const GUARDRAIL_ARN: string = 'guardrailArn';
1819
const MODEL_ID: string = 'modelId';
19-
const AWS_BEDROCK_SYSTEM: string = 'aws_bedrock';
20+
const AWS_BEDROCK_SYSTEM: string = 'aws.bedrock';
2021

2122
const AGENT_OPERATIONS = [
2223
'CreateAgentActionGroup',
@@ -60,6 +61,7 @@ const knowledgeBaseOperationAttributeKeyMapping = {
6061
};
6162
const dataSourceOperationAttributeKeyMapping = {
6263
[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_DATA_SOURCE_ID]: DATA_SOURCE_ID,
64+
[AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_KNOWLEDGE_BASE_ID]: KNOWLEDGE_BASE_ID,
6365
};
6466

6567
// This map allows us to get all relevant attribute key mappings for a given operation
@@ -182,10 +184,15 @@ export class BedrockServiceExtension implements ServiceExtension {
182184
};
183185
}
184186
responseHook(response: NormalizedResponse, span: Span, tracer: Tracer, config: AwsSdkInstrumentationConfig): void {
185-
const guardrail_id = response.data[GUARDRAIL_ID];
187+
const guardrailId = response.data[GUARDRAIL_ID];
188+
const guardrailArn = response.data[GUARDRAIL_ARN];
189+
190+
if (guardrailId) {
191+
span.setAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, guardrailId);
192+
}
186193

187-
if (guardrail_id) {
188-
span.setAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ID, guardrail_id);
194+
if (guardrailArn) {
195+
span.setAttribute(AWS_ATTRIBUTE_KEYS.AWS_BEDROCK_GUARDRAIL_ARN, guardrailArn);
189196
}
190197
}
191198
}
@@ -225,6 +232,16 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
225232
spanAttributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_MAX_TOKENS] =
226233
requestBody.textGenerationConfig.maxTokenCount;
227234
}
235+
} else if (modelId.includes('amazon.nova')) {
236+
if (requestBody.inferenceConfig?.temperature !== undefined) {
237+
spanAttributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_TEMPERATURE] = requestBody.inferenceConfig.temperature;
238+
}
239+
if (requestBody.inferenceConfig?.top_p !== undefined) {
240+
spanAttributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_TOP_P] = requestBody.inferenceConfig.top_p;
241+
}
242+
if (requestBody.inferenceConfig?.max_new_tokens !== undefined) {
243+
spanAttributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_MAX_TOKENS] = requestBody.inferenceConfig.max_new_tokens;
244+
}
228245
} else if (modelId.includes('anthropic.claude')) {
229246
if (requestBody.max_tokens !== undefined) {
230247
spanAttributes[AwsSpanProcessingUtil.GEN_AI_REQUEST_MAX_TOKENS] = requestBody.max_tokens;
@@ -328,6 +345,18 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension {
328345
responseBody.results[0].completionReason,
329346
]);
330347
}
348+
} else if (currentModelId.includes('amazon.nova')) {
349+
if (responseBody.usage !== undefined) {
350+
if (responseBody.usage.inputTokens !== undefined) {
351+
span.setAttribute(AwsSpanProcessingUtil.GEN_AI_USAGE_INPUT_TOKENS, responseBody.usage.inputTokens);
352+
}
353+
if (responseBody.usage.outputTokens !== undefined) {
354+
span.setAttribute(AwsSpanProcessingUtil.GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.usage.outputTokens);
355+
}
356+
}
357+
if (responseBody.stopReason !== undefined) {
358+
span.setAttribute(AwsSpanProcessingUtil.GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stopReason]);
359+
}
331360
} else if (currentModelId.includes('anthropic.claude')) {
332361
if (responseBody.usage?.input_tokens !== undefined) {
333362
span.setAttribute(AwsSpanProcessingUtil.GEN_AI_USAGE_INPUT_TOKENS, responseBody.usage.input_tokens);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { Attributes, Span, SpanKind, Tracer } from '@opentelemetry/api';
5+
import {
6+
AwsSdkInstrumentationConfig,
7+
NormalizedRequest,
8+
NormalizedResponse,
9+
} from '@opentelemetry/instrumentation-aws-sdk';
10+
import { AWS_ATTRIBUTE_KEYS } from '../../../aws-attribute-keys';
11+
import { RequestMetadata, ServiceExtension } from '../../../third-party/otel/aws/services/ServiceExtension';
12+
13+
export class SecretsManagerServiceExtension implements ServiceExtension {
14+
requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata {
15+
const secretId = request.commandInput?.SecretId;
16+
17+
const spanKind: SpanKind = SpanKind.CLIENT;
18+
let spanName: string | undefined;
19+
20+
const spanAttributes: Attributes = {};
21+
22+
if (typeof secretId === 'string' && secretId.startsWith('arn:aws:secretsmanager:')) {
23+
spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN] = secretId;
24+
}
25+
26+
const isIncoming = false;
27+
28+
return {
29+
isIncoming,
30+
spanAttributes,
31+
spanKind,
32+
spanName,
33+
};
34+
}
35+
36+
responseHook(response: NormalizedResponse, span: Span, tracer: Tracer, config: AwsSdkInstrumentationConfig): void {
37+
const secretArn = response.data.ARN;
38+
39+
if (secretArn) {
40+
span.setAttribute(AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN, secretArn);
41+
}
42+
}
43+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { Attributes, SpanKind } from '@opentelemetry/api';
5+
import { AwsSdkInstrumentationConfig, NormalizedRequest } from '@opentelemetry/instrumentation-aws-sdk';
6+
import { AWS_ATTRIBUTE_KEYS } from '../../../aws-attribute-keys';
7+
import { RequestMetadata, ServiceExtension } from '../../../third-party/otel/aws/services/ServiceExtension';
8+
9+
export class StepFunctionsServiceExtension implements ServiceExtension {
10+
requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata {
11+
const stateMachineArn = request.commandInput?.stateMachineArn;
12+
const activityArn = request.commandInput?.activityArn;
13+
14+
const spanKind: SpanKind = SpanKind.CLIENT;
15+
let spanName: string | undefined;
16+
17+
const spanAttributes: Attributes = {};
18+
19+
if (stateMachineArn) {
20+
spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN] = stateMachineArn;
21+
}
22+
23+
if (activityArn) {
24+
spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN] = activityArn;
25+
}
26+
27+
const isIncoming = false;
28+
29+
return {
30+
isIncoming,
31+
spanAttributes,
32+
spanKind,
33+
spanName,
34+
};
35+
}
36+
}

0 commit comments

Comments
 (0)