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

Commit b61047d

Browse files
author
Amir Blum
authored
feat(plugin-aws-sdk): make dynamodb complaint to database client semantic conventions (#45)
1 parent b54811b commit b61047d

File tree

8 files changed

+398
-307
lines changed

8 files changed

+398
-307
lines changed

packages/plugin-aws-sdk/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"dependencies": {
4848
"@opentelemetry/api": "^0.13.0",
4949
"@opentelemetry/core": "^0.13.0",
50+
"@opentelemetry/semantic-conventions": "^0.13.0",
5051
"opentelemetry-propagation-utils": "0.1.0",
5152
"shimmer": "^1.2.1"
5253
},

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,18 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
8484
return newSpan;
8585
}
8686

87-
private _callPreRequestHooks(span: Span, request: AWS.Request<any, any>) {
87+
private _callUserPreRequestHook(span: Span, request: AWS.Request<any, any>) {
8888
if (this._config?.preRequestHook) {
8989
this._safeExecute(span, () => this._config.preRequestHook(span, request), false);
9090
}
9191
}
9292

93+
private _callUserResponseHook(span: Span, response: AWS.Response<any, any>) {
94+
if (this._config?.responseHook) {
95+
this._safeExecute(span, () => this._config.responseHook(span, response), false);
96+
}
97+
}
98+
9399
private _registerCompletedEvent(span: Span, request: AWS.Request<any, any>) {
94100
const thisPlugin = this;
95101
request.on('complete', (response) => {
@@ -102,6 +108,7 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
102108
span.setAttribute(AttributeNames.AWS_ERROR, response.error);
103109
}
104110

111+
this._callUserResponseHook(span, response);
105112
this.servicesExtensions.responseHook(response, span);
106113

107114
span.setAttributes({
@@ -130,7 +137,7 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
130137
requestMetadata.spanKind,
131138
requestMetadata.spanName
132139
);
133-
thisPlugin._callPreRequestHooks(span, awsRequest);
140+
thisPlugin._callUserPreRequestHook(span, awsRequest);
134141
thisPlugin._registerCompletedEvent(span, awsRequest);
135142

136143
const callbackWithContext = thisPlugin._tracer.bind(callback, span);
@@ -160,7 +167,7 @@ class AwsPlugin extends BasePlugin<typeof AWS> {
160167
requestMetadata.spanKind,
161168
requestMetadata.spanName
162169
);
163-
thisPlugin._callPreRequestHooks(span, awsRequest);
170+
thisPlugin._callUserPreRequestHook(span, awsRequest);
164171
thisPlugin._registerCompletedEvent(span, awsRequest);
165172

166173
const origPromise: Promise<any> = thisPlugin._tracer.withSpan(span, () => {

packages/plugin-aws-sdk/src/services/ServiceExtension.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { Span, Attributes, SpanKind } from '@opentelemetry/api';
22

3-
/*
4-
isIncoming - if true, then the operation callback / promise should be bind with the operation's span
5-
*/
63
export interface RequestMetadata {
4+
// isIncoming - if true, then the operation callback / promise should be bind with the operation's span
75
isIncoming: boolean;
86
spanAttributes?: Attributes;
97
spanKind?: SpanKind;
@@ -17,5 +15,5 @@ export interface ServiceExtension {
1715
// called before request is sent, and after span is started
1816
requestPostSpanHook?: (request: AWS.Request<any, any>) => void;
1917

20-
responseHook: (response: AWS.Response<any, any>, span: Span) => void;
18+
responseHook?: (response: AWS.Response<any, any>, span: Span) => void;
2119
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@ import { ServiceExtension, RequestMetadata } from './ServiceExtension';
33
import { SqsServiceExtension } from './sqs';
44
import * as AWS from 'aws-sdk';
55
import { AwsSdkPluginConfig } from '../types';
6+
import { DynamodbServiceExtension } from './dynamodb';
67

78
export class ServicesExtensions implements ServiceExtension {
89
services: Map<string, ServiceExtension> = new Map();
910

1011
constructor(tracer: Tracer, logger: Logger, pluginConfig: AwsSdkPluginConfig) {
1112
this.services.set('sqs', new SqsServiceExtension(tracer, logger, pluginConfig?.sqsProcessHook));
13+
this.services.set('dynamodb', new DynamodbServiceExtension());
1214
}
1315

1416
requestHook(request: AWS.Request<any, any>): RequestMetadata {
@@ -31,7 +33,6 @@ export class ServicesExtensions implements ServiceExtension {
3133
responseHook(response: AWS.Response<any, any>, span: Span) {
3234
const serviceId = (response as any)?.request?.service?.serviceIdentifier;
3335
const serviceExtension = this.services.get(serviceId);
34-
if (!serviceExtension) return;
35-
serviceExtension.responseHook(response, span);
36+
serviceExtension?.responseHook?.(response, span);
3637
}
3738
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Logger, SpanKind } from '@opentelemetry/api';
2+
import { RequestMetadata, ServiceExtension } from './ServiceExtension';
3+
import { DatabaseAttribute } from '@opentelemetry/semantic-conventions';
4+
5+
export class DynamodbServiceExtension implements ServiceExtension {
6+
requestHook(request: AWS.Request<any, any>): RequestMetadata {
7+
let spanKind: SpanKind = SpanKind.CLIENT;
8+
let spanName: string;
9+
let isIncoming = false;
10+
const operation = (request as any)?.operation;
11+
12+
const spanAttributes = {
13+
[DatabaseAttribute.DB_SYSTEM]: 'dynamodb',
14+
[DatabaseAttribute.DB_NAME]: (request as any)?.params?.TableName,
15+
[DatabaseAttribute.DB_OPERATION]: operation,
16+
[DatabaseAttribute.DB_STATEMENT]: JSON.stringify((request as any)?.params),
17+
};
18+
19+
return {
20+
isIncoming,
21+
spanAttributes,
22+
spanKind,
23+
spanName,
24+
};
25+
}
26+
}

packages/plugin-aws-sdk/src/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,21 @@ export interface AwsSdkRequestCustomAttributeFunction {
55
(span: Span, request: AWS.Request<any, any>): void;
66
}
77

8+
export interface AwsSdkResponseCustomAttributeFunction {
9+
(span: Span, response: AWS.Response<any, any>): void;
10+
}
11+
812
export interface AwsSdkSqsProcessCustomAttributeFunction {
913
(span: Span, message: AWS.SQS.Message): void;
1014
}
1115

1216
export interface AwsSdkPluginConfig extends PluginConfig {
13-
/** hook for adding custom attributes before producer message is sent */
17+
/** hook for adding custom attributes before request is sent to aws */
1418
preRequestHook?: AwsSdkRequestCustomAttributeFunction;
1519

20+
/** hook for adding custom attributes when response is received from aws */
21+
responseHook?: AwsSdkResponseCustomAttributeFunction;
22+
1623
/** hook for adding custom attribute when an sqs process span is started */
1724
sqsProcessHook?: AwsSdkSqsProcessCustomAttributeFunction;
1825
}

0 commit comments

Comments
 (0)