Skip to content

Commit 0d2e856

Browse files
committed
feat(instrumentation-aws-sdk): Add semconv attributes for AWS Step Functions
This PR adds the aws.step_functions.activity.arn and aws.step_functions.state_machine.arn semantic convention attributes for the following AWS resources: AWS Step Functions SDK The ARNs are extracted from request objects, and this behavior is covered by unit tests. Tests Run: npm run compile npm run lint npm run test All newly added tests pass, and no regressions were found. Backward Compatibility: This change is fully backward compatible. It introduces instrumentation for an additional AWS resource without modifying existing behavior in the auto-instrumentation library.
1 parent 4723a55 commit 0d2e856

File tree

5 files changed

+188
-0
lines changed

5 files changed

+188
-0
lines changed

packages/instrumentation-aws-sdk/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"@aws-sdk/client-lambda": "^3.85.0",
6161
"@aws-sdk/client-s3": "^3.85.0",
6262
"@aws-sdk/client-secrets-manager": "^3.85.0",
63+
"@aws-sdk/client-sfn": "^3.85.0",
6364
"@aws-sdk/client-sns": "^3.85.0",
6465
"@aws-sdk/client-sqs": "^3.85.0",
6566
"@aws-sdk/types": "^3.370.0",

packages/instrumentation-aws-sdk/src/semconv.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,23 @@ export const ATTR_AWS_SECRETSMANAGER_SECRET_ARN =
178178
* @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
179179
*/
180180
export const ATTR_AWS_SNS_TOPIC_ARN = 'aws.sns.topic.arn' as const;
181+
182+
/**
183+
* The ARN of the AWS Step Functions Activity.
184+
* Originally from '@opentelemetry/semantic-conventions/incubating'
185+
* https://github.com/open-telemetry/semantic-conventions/blob/main/docs/registry/attributes/aws.md#amazon-step-functions-attributes
186+
* @example arn:aws:states:us-east-1:123456789012:activity:get-greeting
187+
* @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
188+
*/
189+
export const ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN =
190+
'aws.step_functions.activity.arn' as const;
191+
192+
/**
193+
* The ARN of the AWS Step Functions State Machine.
194+
* Originally from '@opentelemetry/semantic-conventions/incubating'
195+
* https://github.com/open-telemetry/semantic-conventions/blob/main/docs/registry/attributes/aws.md#amazon-step-functions-attributes
196+
* @example arn:aws:states:us-east-1:123456789012:stateMachine:myStateMachine:1
197+
* @experimental This attribute is experimental and is subject to breaking changes in minor releases of `@opentelemetry/semantic-conventions`.
198+
*/
199+
export const ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN =
200+
'aws.step_functions.state_machine.arn' as const;

packages/instrumentation-aws-sdk/src/services/ServicesExtensions.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { BedrockRuntimeServiceExtension } from './bedrock-runtime';
2525
import { DynamodbServiceExtension } from './dynamodb';
2626
import { SecretsManagerServiceExtension } from './secretsmanager';
2727
import { SnsServiceExtension } from './sns';
28+
import { StepFunctionsServiceExtension } from './stepfunctions';
2829
import { LambdaServiceExtension } from './lambda';
2930
import { S3ServiceExtension } from './s3';
3031
import { KinesisServiceExtension } from './kinesis';
@@ -33,7 +34,12 @@ export class ServicesExtensions implements ServiceExtension {
3334
services: Map<string, ServiceExtension> = new Map();
3435

3536
constructor() {
37+
this.registerServices();
38+
}
39+
40+
private registerServices() {
3641
this.services.set('SecretsManager', new SecretsManagerServiceExtension());
42+
this.services.set('SFN', new StepFunctionsServiceExtension());
3743
this.services.set('SQS', new SqsServiceExtension());
3844
this.services.set('SNS', new SnsServiceExtension());
3945
this.services.set('DynamoDB', new DynamodbServiceExtension());
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
import { Attributes, SpanKind } from '@opentelemetry/api';
17+
import {
18+
ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN,
19+
ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN,
20+
} from '../semconv';
21+
import { RequestMetadata, ServiceExtension } from './ServiceExtension';
22+
import { NormalizedRequest, AwsSdkInstrumentationConfig } from '../types';
23+
24+
export class StepFunctionsServiceExtension implements ServiceExtension {
25+
requestPreSpanHook(
26+
request: NormalizedRequest,
27+
_config: AwsSdkInstrumentationConfig
28+
): RequestMetadata {
29+
const stateMachineArn = request.commandInput?.stateMachineArn;
30+
const activityArn = request.commandInput?.activityArn;
31+
const spanKind: SpanKind = SpanKind.CLIENT;
32+
const spanAttributes: Attributes = {};
33+
34+
if (stateMachineArn) {
35+
spanAttributes[ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN] =
36+
stateMachineArn;
37+
}
38+
39+
if (activityArn) {
40+
spanAttributes[ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN] = activityArn;
41+
}
42+
43+
return {
44+
isIncoming: false,
45+
spanAttributes,
46+
spanKind,
47+
};
48+
}
49+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright The OpenTelemetry Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { getTestSpans } from '@opentelemetry/contrib-test-utils';
18+
import { SpanKind } from '@opentelemetry/api';
19+
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
20+
import {
21+
ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN,
22+
ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN,
23+
} from '@opentelemetry/semantic-conventions/incubating';
24+
25+
import { SFN } from '@aws-sdk/client-sfn';
26+
27+
import { expect } from 'expect';
28+
import * as nock from 'nock';
29+
30+
const region = 'us-east-1';
31+
32+
describe('SFN', () => {
33+
let sfn: SFN;
34+
beforeEach(() => {
35+
sfn = new SFN({
36+
region: region,
37+
credentials: {
38+
accessKeyId: 'abcde',
39+
secretAccessKey: 'abcde',
40+
},
41+
});
42+
});
43+
44+
describe('DescribeStateMachine', () => {
45+
it('span has stateMachineArn in its attributes', async () => {
46+
const stateMachineArn =
47+
'arn:aws:states:us-east-1:123456789123:stateMachine:testStateMachine';
48+
49+
nock(`https://states.${region}.amazonaws.com/`)
50+
.post('/')
51+
.reply(200, '{}');
52+
53+
await sfn.describeStateMachine({
54+
stateMachineArn: stateMachineArn,
55+
});
56+
57+
const testSpans: ReadableSpan[] = getTestSpans();
58+
const getStateMachineAttributeSpans: ReadableSpan[] = testSpans.filter(
59+
(s: ReadableSpan) => {
60+
return s.name === 'SFN.DescribeStateMachine';
61+
}
62+
);
63+
64+
expect(getStateMachineAttributeSpans.length).toBe(1);
65+
66+
const stateMachineAttributeSpan = getStateMachineAttributeSpans[0];
67+
expect(
68+
ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN in
69+
stateMachineAttributeSpan.attributes
70+
);
71+
expect(
72+
stateMachineAttributeSpan.attributes[
73+
ATTR_AWS_STEP_FUNCTIONS_STATE_MACHINE_ARN
74+
]
75+
).toBe(stateMachineArn);
76+
expect(stateMachineAttributeSpan.kind).toBe(SpanKind.CLIENT);
77+
});
78+
});
79+
80+
describe('DescribeActivity', () => {
81+
it('span has activityArn in its attributes', async () => {
82+
const activityArn =
83+
'arn:aws:states:us-east-1:123456789123:activity:testActivity';
84+
85+
nock(`https://states.${region}.amazonaws.com/`)
86+
.post('/')
87+
.reply(200, '{}');
88+
89+
await sfn.describeActivity({
90+
activityArn: activityArn,
91+
});
92+
93+
const testSpans: ReadableSpan[] = getTestSpans();
94+
const getActivityAttributeSpans: ReadableSpan[] = testSpans.filter(
95+
(s: ReadableSpan) => {
96+
return s.name === 'SFN.DescribeActivity';
97+
}
98+
);
99+
100+
expect(getActivityAttributeSpans.length).toBe(1);
101+
102+
const activityAttributeSpan = getActivityAttributeSpans[0];
103+
expect(
104+
ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN in activityAttributeSpan.attributes
105+
);
106+
expect(
107+
activityAttributeSpan.attributes[ATTR_AWS_STEP_FUNCTIONS_ACTIVITY_ARN]
108+
).toBe(activityArn);
109+
expect(activityAttributeSpan.kind).toBe(SpanKind.CLIENT);
110+
});
111+
});
112+
});

0 commit comments

Comments
 (0)