Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

feat: upgrade to otel 17 #66

Merged
merged 11 commits into from
Feb 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,21 @@

js extensions for the [open-telemetry](https://opentelemetry.io/) project, from [Aspecto](https://www.aspecto.io/) with :heart:

**Compatible with [otel v0.16.0](https://github.com/open-telemetry/opentelemetry-js/releases/tag/v0.16.0)**
**Compatible with [otel v0.17.0](https://github.com/open-telemetry/opentelemetry-js/releases/tag/v0.17.0)**
## Instrumentations
- [opentelemetry-instrumentation-kafkajs](./packages/instrumentation-kafkajs) - auto instrumentation for [`kafkajs`](https://kafka.js.org) [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-kafkajs.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-kafkajs)
- [opentelemetry-instrumentation-aws-sdk](./packages/instrumentation-aws-sdk) - auto instrumentation for [`aws-sdk`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/) [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-aws-sdk.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-aws-sdk)
- [opentelemetry-instrumentation-typeorm](./packages/instrumentation-typeorm) - auto instrumentation for [`TypeORM`](https://typeorm.io/) [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-typeorm.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-typeorm)
- [opentelemetry-instrumentation-sequelize](./packages/instrumentation-sequelize) - auto instrumentation for [`Sequelize`](https://sequelize.org/)
[![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-sequelize.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-sequelize)
- [opentelemetry-instrumentation-mongoose](./packages/instrumentation-mongoose) - auto instrumentation for [`mongoose`](https://mongoosejs.com/)
[![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-mongoose.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-mongoose)
| Instrumentation Package | Instrumented Lib | NPM |
| --- | --- | --- |
| [opentelemetry-instrumentation-kafkajs](./packages/instrumentation-kafkajs) | [`kafkajs`](https://kafka.js.org) | [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-kafkajs.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-kafkajs) |
| [opentelemetry-instrumentation-aws-sdk](./packages/instrumentation-aws-sdk) | [`aws-sdk`](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/) | [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-aws-sdk.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-aws-sdk)
| [opentelemetry-instrumentation-typeorm](./packages/instrumentation-typeorm) | [`TypeORM`](https://typeorm.io/) | [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-typeorm.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-typeorm) |
| [opentelemetry-instrumentation-sequelize](./packages/instrumentation-sequelize) | [`Sequelize`](https://sequelize.org/) | [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-sequelize.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-sequelize) |
| [opentelemetry-instrumentation-mongoose](./packages/instrumentation-mongoose) | [`mongoose`](https://mongoosejs.com/) | [![NPM version](https://img.shields.io/npm/v/opentelemetry-instrumentation-mongoose.svg)](https://www.npmjs.com/package/opentelemetry-instrumentation-mongoose) |

## Compatibility with opentelemetry versions
### Instrumentations in this repo are using opentelemetry [Instrumentation API](https://github.com/open-telemetry/opentelemetry-js/tree/main/packages/opentelemetry-instrumentation).
For documentation using with the old [plugin](https://github.com/open-telemetry/opentelemetry-js/blob/main/packages/opentelemetry-core/src/trace/Plugin.ts) api, please go [here](https://github.com/aspecto-io/opentelemetry-ext-js/tree/4393fff108c477d05ecd02dd7d9552ea1d482853).

**Tested and verified against otel v0.16.0**
**Tested and verified against otel v0.17.0**
- Versions 0.2.x of the instrumentations are compatible with otel version v0.17.0
- Versions 0.1.x of the instrumentations are compatible with otel version v0.16.0
- Versions 0.0.x of the instrumentations are compatible with otel version v0.15.0
12 changes: 6 additions & 6 deletions packages/instrumentation-aws-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@
"url": "https://github.com/aspecto-io/opentelemetry-ext-js/issues"
},
"dependencies": {
"@opentelemetry/api": "^0.16.0",
"@opentelemetry/instrumentation": "^0.16.0",
"@opentelemetry/semantic-conventions": "^0.16.0",
"@opentelemetry/api": "^0.17.0",
"@opentelemetry/instrumentation": "^0.17.0",
"@opentelemetry/semantic-conventions": "^0.17.0",
"opentelemetry-propagation-utils": "^0.3.0"
},
"devDependencies": {
"@opentelemetry/api": "^0.16.0",
"@opentelemetry/node": "^0.16.0",
"@opentelemetry/tracing": "^0.16.0",
"@opentelemetry/api": "^0.17.0",
"@opentelemetry/node": "^0.17.0",
"@opentelemetry/tracing": "^0.17.0",
"@types/mocha": "^8.2.0",
"aws-sdk": "^2.780.0",
"expect": "^26.6.2",
Expand Down
59 changes: 28 additions & 31 deletions packages/instrumentation-aws-sdk/src/aws-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
no callback | 0 | 1
callback | 1 | 2
*/
import { Span, Attributes, SpanKind, context, setSpan, suppressInstrumentation, Context } from '@opentelemetry/api';
import { Span, SpanAttributes, SpanKind, context, setSpan, suppressInstrumentation, Context, diag } from '@opentelemetry/api';
import AWS from 'aws-sdk';
import { AttributeNames } from './enums';
import { ServicesExtensions } from './services';
Expand Down Expand Up @@ -37,7 +37,6 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {

setConfig(config: Config = {}) {
this._config = Object.assign({}, config);
if (config.logger) this._logger = config.logger;
}

protected init(): InstrumentationModuleDefinition<typeof AWS> {
Expand All @@ -51,9 +50,9 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {
}

protected patch(moduleExports: typeof AWS) {
this.servicesExtensions = new ServicesExtensions(this.tracer, this._logger, this._config);
this.servicesExtensions = new ServicesExtensions(this.tracer, this._config);

this._logger.debug(`applying patch to ${AwsInstrumentation.component}`);
diag.debug(`applying patch to ${AwsInstrumentation.component}`);
this.unpatch(moduleExports);
this._wrap(moduleExports?.Request.prototype, 'send', this._getRequestSendPatch.bind(this));
this._wrap(moduleExports?.Request.prototype, 'promise', this._getRequestPromisePatch.bind(this));
Expand Down Expand Up @@ -82,7 +81,7 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {

private _startAwsSpan(
request: AWS.Request<any, any>,
additionalAttributes?: Attributes,
additionalSpanAttributes?: SpanAttributes,
spanKind?: SpanKind,
spanName?: string
): Span {
Expand All @@ -100,7 +99,7 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {
[AttributeNames.AWS_SERVICE_API]: service?.api?.className,
[AttributeNames.AWS_SERVICE_IDENTIFIER]: service?.serviceIdentifier,
[AttributeNames.AWS_SERVICE_NAME]: service?.api?.abbreviation,
...additionalAttributes,
...additionalSpanAttributes,
},
});

Expand All @@ -114,7 +113,7 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {
() => this._config.preRequestHook(span, request),
(e: Error) => {
if (e)
this._logger.error(`${AwsInstrumentation.component} instrumentation: preRequestHook error`, e);
diag.error(`${AwsInstrumentation.component} instrumentation: preRequestHook error`, e);
},
true
);
Expand All @@ -126,22 +125,22 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {
safeExecuteInTheMiddle(
() => this._config.responseHook(span, response),
(e: Error) => {
if (e) this._logger.error(`${AwsInstrumentation.component} instrumentation: responseHook error`, e);
if (e) diag.error(`${AwsInstrumentation.component} instrumentation: responseHook error`, e);
},
true
);
}
}

private _registerCompletedEvent(span: Span, request: AWS.Request<any, any>, completedEventContext: Context) {
const thisInstrumentation = this;
const self = this;
request.on('complete', (response) => {
// read issue https://github.com/aspecto-io/opentelemetry-ext-js/issues/60
context.with(completedEventContext, () => {
if (!request[thisInstrumentation.REQUEST_SPAN_KEY]) {
if (!request[self.REQUEST_SPAN_KEY]) {
return;
}
request[thisInstrumentation.REQUEST_SPAN_KEY] = undefined;
request[self.REQUEST_SPAN_KEY] = undefined;

if (response.error) {
span.setAttribute(AttributeNames.AWS_ERROR, response.error);
Expand All @@ -150,28 +149,26 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {
this._callUserResponseHook(span, response);
this.servicesExtensions.responseHook(response, span);

span.setAttributes({
[AttributeNames.AWS_REQUEST_ID]: response.requestId,
});
span.setAttribute(AttributeNames.AWS_REQUEST_ID, response.requestId);
span.end();
});
});
}

private _getRequestSendPatch(original: (callback?: (err: any, data: any) => void) => void) {
const thisInstrumentation = this;
const self = this;
return function (callback?: (err: any, data: any) => void) {
const awsRequest: AWS.Request<any, any> = this;
/*
if the span was already started, we don't want to start a new one
when Request.promise() is called
*/
if (this._asm.currentState === 'complete' || awsRequest[thisInstrumentation.REQUEST_SPAN_KEY]) {
if (this._asm.currentState === 'complete' || awsRequest[self.REQUEST_SPAN_KEY]) {
return original.apply(this, arguments);
}

const requestMetadata = thisInstrumentation.servicesExtensions.requestHook(awsRequest);
const span = thisInstrumentation._startAwsSpan(
const requestMetadata = self.servicesExtensions.requestHook(awsRequest);
const span = self._startAwsSpan(
awsRequest,
requestMetadata.spanAttributes,
requestMetadata.spanKind,
Expand All @@ -180,44 +177,44 @@ export class AwsInstrumentation extends InstrumentationBase<typeof AWS> {
const activeContextWithSpan = setSpan(context.active(), span);
const callbackWithContext = context.bind(callback, activeContextWithSpan);

thisInstrumentation._callUserPreRequestHook(span, awsRequest);
thisInstrumentation._registerCompletedEvent(span, awsRequest, activeContextWithSpan);
self._callUserPreRequestHook(span, awsRequest);
self._registerCompletedEvent(span, awsRequest, activeContextWithSpan);

return context.with(activeContextWithSpan, () => {
thisInstrumentation.servicesExtensions.requestPostSpanHook(awsRequest);
return thisInstrumentation._callOriginalFunction(() => original.call(awsRequest, callbackWithContext));
self.servicesExtensions.requestPostSpanHook(awsRequest);
return self._callOriginalFunction(() => original.call(awsRequest, callbackWithContext));
});
};
}

private _getRequestPromisePatch(original: () => Promise<any>) {
const thisInstrumentation = this;
const self = this;
return function (): Promise<any> {
const awsRequest: AWS.Request<any, any> = this;
// if the span was already started, we don't want to start a new one when Request.promise() is called
if (this._asm.currentState === 'complete' || awsRequest[thisInstrumentation.REQUEST_SPAN_KEY]) {
if (this._asm.currentState === 'complete' || awsRequest[self.REQUEST_SPAN_KEY]) {
return original.apply(this, arguments);
}

const requestMetadata = thisInstrumentation.servicesExtensions.requestHook(awsRequest);
const span = thisInstrumentation._startAwsSpan(
const requestMetadata = self.servicesExtensions.requestHook(awsRequest);
const span = self._startAwsSpan(
awsRequest,
requestMetadata.spanAttributes,
requestMetadata.spanKind,
requestMetadata.spanName
);

const activeContextWithSpan = setSpan(context.active(), span);
thisInstrumentation._callUserPreRequestHook(span, awsRequest);
thisInstrumentation._registerCompletedEvent(span, awsRequest, activeContextWithSpan);
self._callUserPreRequestHook(span, awsRequest);
self._registerCompletedEvent(span, awsRequest, activeContextWithSpan);

const origPromise: Promise<any> = context.with(activeContextWithSpan, () => {
thisInstrumentation.servicesExtensions.requestPostSpanHook(awsRequest);
return thisInstrumentation._callOriginalFunction(() => original.call(awsRequest, arguments));
self.servicesExtensions.requestPostSpanHook(awsRequest);
return self._callOriginalFunction(() => original.call(awsRequest, arguments));
});

return requestMetadata.isIncoming
? thisInstrumentation._bindPromise(origPromise, activeContextWithSpan)
? self._bindPromise(origPromise, activeContextWithSpan)
: origPromise;
};
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Span, Attributes, SpanKind } from '@opentelemetry/api';
import { Span, SpanAttributes, SpanKind } from '@opentelemetry/api';

export interface RequestMetadata {
// isIncoming - if true, then the operation callback / promise should be bind with the operation's span
isIncoming: boolean;
spanAttributes?: Attributes;
spanAttributes?: SpanAttributes;
spanKind?: SpanKind;
spanName?: string;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Tracer, Span, Logger } from '@opentelemetry/api';
import { Tracer, Span } from '@opentelemetry/api';
import { ServiceExtension, RequestMetadata } from './ServiceExtension';
import { SqsServiceExtension } from './sqs';
import * as AWS from 'aws-sdk';
Expand All @@ -8,8 +8,8 @@ import { DynamodbServiceExtension } from './dynamodb';
export class ServicesExtensions implements ServiceExtension {
services: Map<string, ServiceExtension> = new Map();

constructor(tracer: Tracer, logger: Logger, instrumentationConfig: AwsSdkInstrumentationConfig) {
this.services.set('sqs', new SqsServiceExtension(tracer, logger, instrumentationConfig?.sqsProcessHook));
constructor(tracer: Tracer, instrumentationConfig: AwsSdkInstrumentationConfig) {
this.services.set('sqs', new SqsServiceExtension(tracer, instrumentationConfig?.sqsProcessHook));
this.services.set('dynamodb', new DynamodbServiceExtension());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Logger, SpanKind } from '@opentelemetry/api';
import { SpanKind } from '@opentelemetry/api';
import { RequestMetadata, ServiceExtension } from './ServiceExtension';
import { DatabaseAttribute } from '@opentelemetry/semantic-conventions';

Expand Down
5 changes: 2 additions & 3 deletions packages/instrumentation-aws-sdk/src/services/sqs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {
SpanKind,
Span,
propagation,
Logger,
diag,
TextMapGetter,
TextMapSetter,
setSpan,
Expand Down Expand Up @@ -61,7 +61,6 @@ const sqsContextGetter = new SqsContextGetter();
export class SqsServiceExtension implements ServiceExtension {
constructor(
private tracer: Tracer,
private logger: Logger,
private sqsProcessHook: AwsSdkSqsProcessCustomAttributeFunction
) {}

Expand Down Expand Up @@ -180,7 +179,7 @@ export class SqsServiceExtension implements ServiceExtension {
if (Object.keys(attributes).length < SQS_MAX_MESSAGE_ATTRIBUTES) {
propagation.inject(context.active(), attributes, sqsContextSetter);
} else {
this.logger.warn(
diag.warn(
'OpenTelemetry aws-sdk instrumentation cannot set context propagation on SQS message due to maximum amount of MessageAttributes'
);
}
Expand Down
4 changes: 2 additions & 2 deletions packages/instrumentation-aws-sdk/test/aws-sdk.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'mocha';
import { AwsInstrumentation } from '../src';
import { InMemorySpanExporter, SimpleSpanProcessor, ReadableSpan, Span } from '@opentelemetry/tracing';
import { context, StatusCode } from '@opentelemetry/api';
import { context, SpanStatusCode } from '@opentelemetry/api';
import { NodeTracerProvider } from '@opentelemetry/node';
import { ContextManager } from '@opentelemetry/context-base';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
Expand Down Expand Up @@ -259,7 +259,7 @@ describe('instrumentation-aws-sdk', () => {
s3.createBucket({ Bucket: bucketName }, async function (err, data) {
const awsSpans = getAwsSpans();
expect(awsSpans.length).toBe(1);
expect(awsSpans[0].status.code).toStrictEqual(StatusCode.UNSET);
expect(awsSpans[0].status.code).toStrictEqual(SpanStatusCode.UNSET);
done();
});
});
Expand Down
6 changes: 3 additions & 3 deletions packages/instrumentation-aws-sdk/test/sqs.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import 'mocha';
import { AwsInstrumentation } from '../src';
import { NodeTracerProvider } from '@opentelemetry/node';
import { ContextManager } from '@opentelemetry/context-base';
import { context, SpanKind, StatusCode } from '@opentelemetry/api';
import { context, SpanKind, SpanStatusCode } from '@opentelemetry/api';
import { InMemorySpanExporter, SimpleSpanProcessor, ReadableSpan, Span } from '@opentelemetry/tracing';
import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks';
import { mockAwsSend } from './testing-utils';
Expand Down Expand Up @@ -383,8 +383,8 @@ describe('sqs', () => {
.getFinishedSpans()
.filter((s) => s.attributes[SqsAttributeNames.MESSAGING_OPERATION] === 'process');
expect(processSpans.length).toBe(2);
expect(processSpans[0].status.code).toStrictEqual(StatusCode.UNSET);
expect(processSpans[1].status.code).toStrictEqual(StatusCode.UNSET);
expect(processSpans[0].status.code).toStrictEqual(SpanStatusCode.UNSET);
expect(processSpans[1].status.code).toStrictEqual(SpanStatusCode.UNSET);
});
});
});
10 changes: 5 additions & 5 deletions packages/instrumentation-kafkajs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@
"url": "https://github.com/aspecto-io/opentelemetry-ext-js/issues"
},
"dependencies": {
"@opentelemetry/api": "^0.16.0",
"@opentelemetry/instrumentation": "^0.16.0",
"@opentelemetry/semantic-conventions": "^0.16.0"
"@opentelemetry/api": "^0.17.0",
"@opentelemetry/instrumentation": "^0.17.0",
"@opentelemetry/semantic-conventions": "^0.17.0"
},
"devDependencies": {
"@opentelemetry/node": "^0.16.0",
"@opentelemetry/tracing": "^0.16.0",
"@opentelemetry/node": "^0.17.0",
"@opentelemetry/tracing": "^0.17.0",
"@types/mocha": "^8.2.0",
"expect": "^26.6.2",
"kafkajs": "^1.12.0",
Expand Down
Loading