Skip to content

Commit 68989f3

Browse files
authored
feat(instrumentation-aws-sdk): support migration to stable HTTP semconv (#3077)
1 parent e5adbf1 commit 68989f3

File tree

5 files changed

+79
-6
lines changed

5 files changed

+79
-6
lines changed

packages/instrumentation-aws-sdk/README.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,13 +102,16 @@ The instrumentation is doing best effort to support the trace specification of O
102102

103103
## Semantic Conventions
104104

105-
This package uses `@opentelemetry/semantic-conventions` version `1.22+`, which implements Semantic Convention [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md)
105+
This package emits telemetry using a mix of Semantic Convention versions. While not ideal, this is a result of there being a number of separate AWS services instrumented with independent maintenance.
106106

107-
Attributes collected:
107+
- As a baseline, initial implementations follow [Version 1.7.0](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.7.0/semantic_conventions/README.md).
108+
- SQS instrumentation was [updated](https://github.com/open-telemetry/opentelemetry-js-contrib/pull/2345) to follow v1.36.0.
109+
110+
Attributes collected (this list is currently not exhaustive):
108111

109112
| Attribute | Short Description | Service |
110113
| --------------------------------------------- | ---------------------------------------------------------------------------------------------- | -------- |
111-
| `http.status_code` | (aws-sdk) HTTP response status code. | |
114+
| `http.status_code` / `http.response.status_code` | (aws-sdk) HTTP response status code. See "HTTP Semantic Convention migration" note below. | |
112115
| `rpc.method` | The name of the (logical) method being called. | |
113116
| `rpc.service` | The full (logical) name of the service being called. | |
114117
| `rpc.system` | A string identifying the remoting system. | |
@@ -149,6 +152,31 @@ Attributes collected:
149152
| `messaging.message_id` | A value used by the messaging system as an identifier for the message. | sqs |
150153
| `messaging.url` | The connection string. | sqs |
151154

155+
### HTTP Semantic Convention migration
156+
157+
HTTP semantic conventions (semconv) were stabilized in v1.23.0, and a [migration process](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/non-normative/http-migration.md#http-semantic-convention-stability-migration)
158+
was defined. `instrumentation-aws-sdk` adds some minimal HTTP-related
159+
attributes on created spans. Starting with `instrumentation-aws-sdk` version
160+
0.61.0, the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable can be used to
161+
customize which HTTP semantic conventions are used for those HTTP-related
162+
attributes.
163+
164+
To select which semconv version(s) is emitted from this instrumentation, use the
165+
`OTEL_SEMCONV_STABILITY_OPT_IN` environment variable.
166+
167+
- `http`: emit the new (stable) v1.23.0+ semantics
168+
- `http/dup`: emit **both** the old v1.7.0 and the new (stable) v1.23.0+ semantics
169+
- By default, if `OTEL_SEMCONV_STABILITY_OPT_IN` includes neither of the above tokens, the old v1.7.0 semconv is used.
170+
171+
For this instrumentation, the only impacted attributes are as follows:
172+
173+
| v1.7.0 semconv | v1.23.0 semconv | Short Description |
174+
| ------------------ | --------------------------- | ------------------------- |
175+
| `http.status_code` | `http.response.status_code` | HTTP response status code |
176+
177+
See the [HTTP semconv migration plan for OpenTelemetry JS instrumentations](https://github.com/open-telemetry/opentelemetry-js/issues/5646) for more details.
178+
179+
152180
## Useful links
153181

154182
- For more information on OpenTelemetry, visit: <https://opentelemetry.io/>

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

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ import {
4040
InstrumentationNodeModuleFile,
4141
isWrapped,
4242
safeExecuteInTheMiddle,
43+
SemconvStability,
44+
semconvStabilityFromStr,
4345
} from '@opentelemetry/instrumentation';
4446
import type {
4547
MiddlewareStack,
@@ -57,6 +59,7 @@ import {
5759
import { propwrap } from './propwrap';
5860
import { RequestMetadata } from './services/ServiceExtension';
5961
import { ATTR_HTTP_STATUS_CODE } from './semconv';
62+
import { ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
6063

6164
const V3_CLIENT_CONFIG_KEY = Symbol(
6265
'opentelemetry.instrumentation.aws-sdk.client.config'
@@ -70,8 +73,14 @@ export class AwsInstrumentation extends InstrumentationBase<AwsSdkInstrumentatio
7073
// need declare since initialized in callbacks from super constructor
7174
private declare servicesExtensions: ServicesExtensions;
7275

76+
private _semconvStability: SemconvStability;
77+
7378
constructor(config: AwsSdkInstrumentationConfig = {}) {
7479
super(PACKAGE_NAME, PACKAGE_VERSION, config);
80+
this._semconvStability = semconvStabilityFromStr(
81+
'http',
82+
process.env.OTEL_SEMCONV_STABILITY_OPT_IN
83+
);
7584
}
7685

7786
protected init(): InstrumentationModuleDefinition[] {
@@ -406,7 +415,15 @@ export class AwsInstrumentation extends InstrumentationBase<AwsSdkInstrumentatio
406415
const httpStatusCode =
407416
response.output?.$metadata?.httpStatusCode;
408417
if (httpStatusCode) {
409-
span.setAttribute(ATTR_HTTP_STATUS_CODE, httpStatusCode);
418+
if (self._semconvStability & SemconvStability.OLD) {
419+
span.setAttribute(ATTR_HTTP_STATUS_CODE, httpStatusCode);
420+
}
421+
if (self._semconvStability & SemconvStability.STABLE) {
422+
span.setAttribute(
423+
ATTR_HTTP_RESPONSE_STATUS_CODE,
424+
httpStatusCode
425+
);
426+
}
410427
}
411428

412429
const extendedRequestId =
@@ -445,7 +462,15 @@ export class AwsInstrumentation extends InstrumentationBase<AwsSdkInstrumentatio
445462

446463
const httpStatusCode = err?.$metadata?.httpStatusCode;
447464
if (httpStatusCode) {
448-
span.setAttribute(ATTR_HTTP_STATUS_CODE, httpStatusCode);
465+
if (self._semconvStability & SemconvStability.OLD) {
466+
span.setAttribute(ATTR_HTTP_STATUS_CODE, httpStatusCode);
467+
}
468+
if (self._semconvStability & SemconvStability.STABLE) {
469+
span.setAttribute(
470+
ATTR_HTTP_RESPONSE_STATUS_CODE,
471+
httpStatusCode
472+
);
473+
}
449474
}
450475

451476
const extendedRequestId = err?.extendedRequestId;

packages/instrumentation-aws-sdk/test/aws-sdk-v3-s3.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { AttributeNames } from '../src/enums';
4545
import { expect } from 'expect';
4646
import * as fs from 'fs';
4747
import * as nock from 'nock';
48+
import { ATTR_HTTP_RESPONSE_STATUS_CODE } from '@opentelemetry/semantic-conventions';
4849

4950
const region = 'us-east-1';
5051

@@ -77,6 +78,11 @@ describe('instrumentation-aws-sdk-v3 (client-s3)', () => {
7778
expect(span.name).toEqual('S3.PutObject');
7879
expect(span.kind).toEqual(SpanKind.CLIENT);
7980
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(200);
81+
82+
// We also expect the stable `http.response.status_code` because
83+
// `OTEL_SEMCONV_STABILITY_OPT_IN=http/dup` has been set before creating
84+
// the instrumentation.
85+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(200);
8086
});
8187

8288
it('callback interface', done => {
@@ -103,6 +109,7 @@ describe('instrumentation-aws-sdk-v3 (client-s3)', () => {
103109
expect(span.attributes[AttributeNames.CLOUD_REGION]).toEqual(region);
104110
expect(span.name).toEqual('S3.PutObject');
105111
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(200);
112+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(200);
106113
done();
107114
});
108115
});
@@ -132,6 +139,7 @@ describe('instrumentation-aws-sdk-v3 (client-s3)', () => {
132139
expect(span.attributes[AttributeNames.CLOUD_REGION]).toEqual(region);
133140
expect(span.name).toEqual('S3.PutObject');
134141
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(200);
142+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(200);
135143
});
136144

137145
it('aws error', async () => {
@@ -166,6 +174,7 @@ describe('instrumentation-aws-sdk-v3 (client-s3)', () => {
166174
'invalid-bucket-name'
167175
);
168176
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(403);
177+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(403);
169178
expect(span.attributes[AttributeNames.CLOUD_REGION]).toEqual(region);
170179
expect(span.attributes[AttributeNames.AWS_REQUEST_ID]).toEqual(
171180
'MS95GTS7KXQ34X2S'

packages/instrumentation-aws-sdk/test/aws-sdk-v3-sqs.test.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ process.env.AWS_SECRET_ACCESS_KEY = 'testing';
3030
import 'mocha';
3131
import { ReadableSpan } from '@opentelemetry/sdk-trace-base';
3232
import { context, trace } from '@opentelemetry/api';
33-
import { ATTR_URL_FULL } from '@opentelemetry/semantic-conventions';
33+
import {
34+
ATTR_HTTP_RESPONSE_STATUS_CODE,
35+
ATTR_URL_FULL,
36+
} from '@opentelemetry/semantic-conventions';
3437
import {
3538
ATTR_HTTP_STATUS_CODE,
3639
ATTR_MESSAGING_BATCH_MESSAGE_COUNT,
@@ -95,6 +98,7 @@ describe('instrumentation-aws-sdk-v3 (client-sqs)', () => {
9598
response.MessageId
9699
);
97100
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(200);
101+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(200);
98102
});
99103

100104
it('sqs send message batch attributes', async () => {
@@ -145,6 +149,7 @@ describe('instrumentation-aws-sdk-v3 (client-sqs)', () => {
145149
);
146150
expect(span.attributes[ATTR_URL_FULL]).toEqual(params.QueueUrl);
147151
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(200);
152+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(200);
148153
});
149154

150155
it('sqs receive add messaging attributes', done => {
@@ -178,6 +183,7 @@ describe('instrumentation-aws-sdk-v3 (client-sqs)', () => {
178183
expect(span.attributes[ATTR_RPC_SERVICE]).toEqual('SQS');
179184
expect(span.attributes[AttributeNames.CLOUD_REGION]).toEqual(region);
180185
expect(span.attributes[ATTR_HTTP_STATUS_CODE]).toEqual(200);
186+
expect(span.attributes[ATTR_HTTP_RESPONSE_STATUS_CODE]).toEqual(200);
181187
expect(span.attributes[ATTR_MESSAGING_BATCH_MESSAGE_COUNT]).toEqual(2);
182188
expect(span.links.length).toBe(2);
183189

packages/instrumentation-aws-sdk/test/load-instrumentation.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ import {
3030
} from '@opentelemetry/sdk-metrics';
3131
import { AwsInstrumentation } from '../src';
3232

33+
// This is a meagre testing of just a single value of
34+
// OTEL_SEMCONV_STABILITY_OPT_IN, because testing multiple configurations of
35+
// `AwsInstrumentation` in this all-in-one-process test setup is difficult.
36+
process.env.OTEL_SEMCONV_STABILITY_OPT_IN = 'http/dup';
37+
3338
export const instrumentation = new AwsInstrumentation();
3439
export const metricExporter = new InMemoryMetricExporter(
3540
AggregationTemporality.DELTA

0 commit comments

Comments
 (0)