Skip to content

Commit 7ab675f

Browse files
committed
added step functions and lambda
1 parent 85747f2 commit 7ab675f

File tree

9 files changed

+350
-16
lines changed

9 files changed

+350
-16
lines changed

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

Lines changed: 7 additions & 1 deletion
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',
@@ -36,5 +37,10 @@ export const AWS_ATTRIBUTE_KEYS: { [key: string]: string } = {
3637
AWS_BEDROCK_AGENT_ID: 'aws.bedrock.agent.id',
3738
AWS_BEDROCK_GUARDRAIL_ID: 'aws.bedrock.guardrail.id',
3839
AWS_SNS_TOPIC_ARN: 'aws.sns.topic.arn',
39-
AWS_SECRETSMANAGER_SECRET_ARN: "aws.secretsmanager.secret.arn"
40+
AWS_SECRETSMANAGER_SECRET_ARN: "aws.secretsmanager.secret.arn",
41+
AWS_STEPFUNCTIONS_STATEMACHINE_ARN: "aws.stepfunctions.state_machine.arn",
42+
AWS_STEPFUNCTIONS_ACTIVITY_ARN: "aws.stepfunctions.activity.arn",
43+
AWS_LAMBDA_FUNCTION_NAME: "aws.lambda.function.name",
44+
AWS_LAMBDA_RESOURCE_MAPPING_ID: "aws.lambda.resource_mapping.id",
45+
AWS_LAMBDA_FUNCTION_ARN: "aws.lambda.function.arn",
4046
};

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

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ 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';
5858
const NORMALIZED_SNS_SERVICE_NAME: string = 'AWS::SNS';
59-
const NORMALIZED_SECRETSMANAGER_SERVICE_NAME = "AWS::SecretsManager"
59+
const NORMALIZED_SECRETSMANAGER_SERVICE_NAME = "AWS::SecretsManager";
60+
const NORMALIZED_STEPFUNCTIONS_SERVICE_NAME = "AWS::StepFunctions";
61+
const NORMALIZED_LAMBDA_SERVICE_NAME = "AWS::Lambda"
6062
const NORMALIZED_BEDROCK_SERVICE_NAME: string = 'AWS::Bedrock';
6163
const NORMALIZED_BEDROCK_RUNTIME_SERVICE_NAME: string = 'AWS::BedrockRuntime';
6264

@@ -352,6 +354,7 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
352354
private static setRemoteResourceTypeAndIdentifier(span: ReadableSpan, attributes: Attributes): void {
353355
let remoteResourceType: AttributeValue | undefined;
354356
let remoteResourceIdentifier: AttributeValue | undefined;
357+
let cloudFormationIdentifier: AttributeValue | undefined;
355358

356359
if (AwsSpanProcessingUtil.isAwsSDKSpan(span)) {
357360
const awsTableNames: AttributeValue | undefined = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_DYNAMODB_TABLE_NAMES];
@@ -373,14 +376,47 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
373376
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_S3_BUCKET]
374377
);
375378
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN)) {
379+
const snsArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN]
380+
376381
remoteResourceType = NORMALIZED_SNS_SERVICE_NAME + '::Topic';
377382
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
378-
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN]
383+
this.simplifyARNAttribute(snsArn)
379384
);
385+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(snsArn);
380386
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN)) {
387+
const secretsArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]
388+
381389
remoteResourceType = NORMALIZED_SECRETSMANAGER_SERVICE_NAME + '::Secret';
382390
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
383-
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]
391+
this.simplifyARNAttribute(secretsArn)
392+
);
393+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(secretsArn)
394+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN)) {
395+
const stateMachineArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_STATEMACHINE_ARN]
396+
397+
remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::StateMachine';
398+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
399+
this.simplifyARNAttribute(stateMachineArn)
400+
);
401+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(stateMachineArn);
402+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN)) {
403+
const activityArn = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_STEPFUNCTIONS_ACTIVITY_ARN]
404+
405+
remoteResourceType = NORMALIZED_STEPFUNCTIONS_SERVICE_NAME + '::Activity';
406+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
407+
this.simplifyARNAttribute(activityArn)
408+
);
409+
cloudFormationIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(activityArn);
410+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME)) {
411+
remoteResourceType = NORMALIZED_LAMBDA_SERVICE_NAME + '::Function';
412+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
413+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME]
414+
);
415+
cloudFormationIdentifier = span.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_ARN]
416+
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_RESOURCEMAPPING_ID)) {
417+
remoteResourceType = NORMALIZED_LAMBDA_SERVICE_NAME + '::EventSourceMapping';
418+
remoteResourceIdentifier = AwsMetricAttributeGenerator.escapeDelimiters(
419+
span.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_RESOURCEMAPPING_ID]
384420
);
385421
} else if (AwsSpanProcessingUtil.isKeyPresent(span, AWS_ATTRIBUTE_KEYS.AWS_SQS_QUEUE_NAME)) {
386422
remoteResourceType = NORMALIZED_SQS_SERVICE_NAME + '::Queue';
@@ -427,6 +463,10 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
427463
attributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_RESOURCE_TYPE] = remoteResourceType;
428464
attributes[AWS_ATTRIBUTE_KEYS.AWS_REMOTE_RESOURCE_IDENTIFIER] = remoteResourceIdentifier;
429465
}
466+
467+
if (cloudFormationIdentifier !== undefined) {
468+
attributes[AWS_ATTRIBUTE_KEYS.AWS_CLOUDFORMATION_PRIMARY_IDENTIFIER] = cloudFormationIdentifier;
469+
}
430470
}
431471

432472
/**
@@ -544,6 +584,15 @@ export class AwsMetricAttributeGenerator implements MetricAttributeGenerator {
544584
return input.split('^').join('^^').split('|').join('^|');
545585
}
546586

587+
private static simplifyARNAttribute(attribute: AttributeValue | undefined) {
588+
if (typeof attribute == 'string' && attribute.startsWith("arn:aws:")) {
589+
const split = attribute.split(":");
590+
return split[split.length - 1];
591+
}
592+
593+
return ''
594+
}
595+
547596
/** Span kind is needed for differentiating metrics in the EMF exporter */
548597
private static setSpanKindForService(span: ReadableSpan, attributes: Attributes): void {
549598
let spanKind: string = SpanKind[span.kind];
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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 { AwsSdkInstrumentationConfig, NormalizedRequest, NormalizedResponse } 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 LambdaServiceExtension implements ServiceExtension {
10+
requestPreSpanHook(request: NormalizedRequest, _config: AwsSdkInstrumentationConfig): RequestMetadata {
11+
const requestFunctionName = request.commandInput?.FunctionName;
12+
const resourceMappingId = request.commandInput?.UUID;
13+
14+
const spanKind: SpanKind = SpanKind.CLIENT;
15+
let spanName: string | undefined;
16+
17+
const spanAttributes: Attributes = {};
18+
19+
let functionName = requestFunctionName;
20+
21+
if (requestFunctionName) {
22+
if (requestFunctionName.startsWith("arn:aws:lambda:")) {
23+
const split = requestFunctionName.split(":")
24+
functionName = split[split.length - 1];
25+
}
26+
27+
spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME] = functionName;
28+
}
29+
30+
if (resourceMappingId) {
31+
spanAttributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_RESOURCE_MAPPING_ID] = resourceMappingId;
32+
}
33+
34+
const isIncoming = false;
35+
36+
return {
37+
isIncoming,
38+
spanAttributes,
39+
spanKind,
40+
spanName,
41+
};
42+
}
43+
44+
responseHook(response: NormalizedResponse, span: Span, tracer: Tracer, config: AwsSdkInstrumentationConfig): void {
45+
46+
if (response.data.Configuration) {
47+
48+
const functionArn = response.data.Configuration.FunctionArn;
49+
50+
if (functionArn) {
51+
span.setAttribute(AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_ARN, functionArn);
52+
}
53+
}
54+
}
55+
56+
}
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+
}

aws-distro-opentelemetry-node-autoinstrumentation/src/patches/instrumentation-patch.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ import { S3ServiceExtension } from './aws/services/s3';
2828
import { AwsLambdaInstrumentationPatch } from './aws/services/aws-lambda';
2929
import { SNSServiceExtension } from './aws/services/sns';
3030
import { SecretsManagerServiceExtension } from './aws/services/secretsmanager';
31+
import { StepFunctionsServiceExtension } from './aws/services/step-functions';
32+
import { LambdaServiceExtension } from './aws/services/lambda';
3133

3234
export const traceContextEnvironmentKey = '_X_AMZN_TRACE_ID';
3335
const awsPropagator = new AWSXRayPropagator();
@@ -59,8 +61,10 @@ export function applyInstrumentationPatches(instrumentations: Instrumentation[])
5961
if (services) {
6062
services.set('S3', new S3ServiceExtension());
6163
services.set('Kinesis', new KinesisServiceExtension());
64+
services.set('Lambda', new LambdaServiceExtension());
6265
services.set('SNS', new SNSServiceExtension());
6366
services.set('SecretsManager', new SecretsManagerServiceExtension());
67+
services.set('SFN', new StepFunctionsServiceExtension());
6468
services.set('Bedrock', new BedrockServiceExtension());
6569
services.set('BedrockAgent', new BedrockAgentServiceExtension());
6670
services.set('BedrockAgentRuntime', new BedrockAgentRuntimeServiceExtension());
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
import { getTestSpans, registerInstrumentationTesting } from '@opentelemetry/contrib-test-utils';
5+
import { AwsInstrumentation } from '@opentelemetry/instrumentation-aws-sdk';
6+
import { applyInstrumentationPatches } from './../../../../src/patches/instrumentation-patch';
7+
8+
const instrumentations: AwsInstrumentation[] = [new AwsInstrumentation()];
9+
applyInstrumentationPatches(instrumentations);
10+
registerInstrumentationTesting(instrumentations[0]);
11+
12+
import { Lambda } from '@aws-sdk/client-lambda';
13+
import * as nock from 'nock';
14+
15+
import { SpanKind } from '@opentelemetry/api';
16+
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
17+
import { expect } from 'expect';
18+
import { AWS_ATTRIBUTE_KEYS } from '../../../../src/aws-attribute-keys';
19+
20+
const region = 'us-east-1';
21+
22+
describe('Lambda', () => {
23+
let lambda: Lambda;
24+
beforeEach(() => {
25+
lambda = new Lambda({
26+
region: region,
27+
credentials: {
28+
accessKeyId: 'abcde',
29+
secretAccessKey: 'abcde',
30+
},
31+
});
32+
});
33+
34+
describe('GetFunction', () => {
35+
{
36+
it(`span has lambda functionName and function ARN in its attributes`, async () => {
37+
const funcName = 'testFunction'
38+
const arn = 'arn:aws:lambda:us-east-1:123456789012:function:testFunction'
39+
40+
nock(`https://lambda.${region}.amazonaws.com/`).get(/.*/).reply(200, {
41+
Configuration: {
42+
FunctionArn: arn
43+
}
44+
});
45+
46+
await lambda.getFunction({
47+
FunctionName: funcName,
48+
}).catch((err: any) => {});
49+
50+
const testSpans: ReadableSpan[] = getTestSpans();
51+
const getFunctionNameSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
52+
return s.name === 'Lambda.GetFunction';
53+
});
54+
55+
expect(getFunctionNameSpans.length).toBe(1);
56+
57+
const functionAttributeSpan = getFunctionNameSpans[0];
58+
59+
expect(functionAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_NAME]).toBe(funcName);
60+
expect(functionAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_FUNCTION_ARN]).toBe(arn);
61+
expect(functionAttributeSpan.kind).toBe(SpanKind.CLIENT);
62+
});
63+
}
64+
});
65+
66+
describe('GetEventSourceMapping', () => {
67+
68+
it(`span has eventSourceMapping attribute in its attributes`, async () => {
69+
const uuid = '14e0db71-abcd-4eb5-b481-8945cf9d10c2'
70+
71+
nock(`https://lambda.${region}.amazonaws.com/`).post('/').reply(200, {});
72+
73+
await lambda.getEventSourceMapping({
74+
UUID: uuid,
75+
}).catch((err: any) => {});
76+
77+
const testSpans: ReadableSpan[] = getTestSpans();
78+
const getEventSourceMappingSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
79+
return s.name === 'Lambda.GetEventSourceMapping';
80+
});
81+
82+
expect(getEventSourceMappingSpans.length).toBe(1);
83+
84+
const eventSourceMappingSpan = getEventSourceMappingSpans[0];
85+
86+
expect(eventSourceMappingSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_LAMBDA_RESOURCE_MAPPING_ID]).toBe(uuid);
87+
expect(eventSourceMappingSpan.kind).toBe(SpanKind.CLIENT);
88+
});
89+
});
90+
});

aws-distro-opentelemetry-node-autoinstrumentation/test/patches/aws/services/secretsmanager.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ describe('SecretsManager', () => {
5454
});
5555

5656
expect(getDescribeSecretSpans.length).toBe(1);
57-
const getTopicAttributeSpan = getDescribeSecretSpans[0];
57+
const describeSecretSpan = getDescribeSecretSpans[0];
5858

5959
if (secretId.startsWith('arn:aws:secretsmanager:')) {
60-
expect(getTopicAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]).toBe(secretId);
60+
expect(describeSecretSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]).toBe(secretId);
6161
} else {
62-
expect(getTopicAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]).toBeUndefined();
62+
expect(describeSecretSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]).toBeUndefined();
6363
}
6464

65-
expect(getTopicAttributeSpan.kind).toBe(SpanKind.CLIENT);
65+
expect(describeSecretSpan.kind).toBe(SpanKind.CLIENT);
6666
});
6767
}
6868
)
@@ -84,14 +84,16 @@ describe('SecretsManager', () => {
8484
});
8585

8686
const testSpans: ReadableSpan[] = getTestSpans();
87-
const getDescribeSecretSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
87+
const getSecretValueSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
8888
return s.name === 'SecretsManager.GetSecretValue';
8989
});
9090

91-
expect(getDescribeSecretSpans.length).toBe(1);
92-
const getTopicAttributeSpan = getDescribeSecretSpans[0];
93-
expect(getTopicAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]).toBe(secretIdArn);
94-
expect(getTopicAttributeSpan.kind).toBe(SpanKind.CLIENT);
91+
expect(getSecretValueSpans.length).toBe(1);
92+
93+
const secretValueSpan = getSecretValueSpans[0];
94+
95+
expect(secretValueSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SECRETSMANAGER_SECRET_ARN]).toBe(secretIdArn);
96+
expect(secretValueSpan.kind).toBe(SpanKind.CLIENT);
9597
});
9698
})
9799
});

aws-distro-opentelemetry-node-autoinstrumentation/test/patches/aws/services/sns.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ describe('SNS', () => {
3030
},
3131
});
3232
});
33+
3334
describe('GetTopicAttributes', () => {
3435
it('span has sns topic.arn in its attributes', async () => {
3536
const topicArn: string = "arn:aws:sns:us-east-1:123456789012:mystack-mytopic-NZJ5JSMVGFIE";
@@ -44,10 +45,13 @@ describe('SNS', () => {
4445
const getTopicAttributeSpans: ReadableSpan[] = testSpans.filter((s: ReadableSpan) => {
4546
return s.name === 'SNS.GetTopicAttributes';
4647
});
48+
4749
expect(getTopicAttributeSpans.length).toBe(1);
48-
const getTopicAttributeSpan = getTopicAttributeSpans[0];
49-
expect(getTopicAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN]).toBe(topicArn);
50-
expect(getTopicAttributeSpan.kind).toBe(SpanKind.CLIENT);
50+
51+
const topicAttributeSpan = getTopicAttributeSpans[0];
52+
53+
expect(topicAttributeSpan.attributes[AWS_ATTRIBUTE_KEYS.AWS_SNS_TOPIC_ARN]).toBe(topicArn);
54+
expect(topicAttributeSpan.kind).toBe(SpanKind.CLIENT);
5155
});
5256
});
5357
});

0 commit comments

Comments
 (0)