diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md b/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md index 63c7a4cd38..a49b72860a 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/README.md @@ -71,12 +71,11 @@ In addition to the above attributes, the instrumentation also collect the follow | `aws.service.identifier` | string | Identifier for the service in the sdk | "sqs" | | `aws.service.name` | string | Abbreviation name for the service | "Amazon SQS" | | `aws.request.id` | uuid | Request unique id, as returned from aws on response | "01234567-89ab-cdef-0123-456789abcdef" | -| `aws.error` | string | information about a service or networking error, as returned from AWS | "UriParameterError: Expected uri parameter to have length >= 1, but found "" for params.Bucket" | ### Custom User Attributes -The instrumentation user can configure a `preRequestHook` function which will be called before each request, with a normalized request object (across v2 and v3) and the corresponding span. -This hook can be used to add custom attributes to the span with any logic. +The instrumentation user can configure a `preRequestHook` function which will be called before each request, with a normalized request object (across v2 and v3) and the corresponding span. +This hook can be used to add custom attributes to the span with any logic. For example, user can add interesting attributes from the `request.params`, and write custom logic based on the service and operation. Usage example: diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts index 0342a87a70..c74f0433c9 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/aws-sdk.ts @@ -320,7 +320,7 @@ export class AwsInstrumentation extends InstrumentationBase { self._callUserResponseHook(span, normalizedResponse); if (response.error) { - span.setAttribute(AttributeNames.AWS_ERROR, response.error); + span.recordException(response.error); } else { this.servicesExtensions.responseHook( normalizedResponse, diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/enums.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/enums.ts index 8d8f2d2974..c3a36dcb12 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/src/enums.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/src/enums.ts @@ -14,7 +14,6 @@ * limitations under the License. */ export enum AttributeNames { - AWS_ERROR = 'aws.error', AWS_OPERATION = 'aws.operation', AWS_REGION = 'aws.region', AWS_SERVICE_API = 'aws.service.api', diff --git a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts index 0d7d8a8aea..bf11de2060 100644 --- a/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts +++ b/plugins/node/opentelemetry-instrumentation-aws-sdk/test/aws-sdk-v2.test.ts @@ -33,6 +33,8 @@ import { AttributeNames } from '../src/enums'; import { mockV2AwsSend } from './testing-utils'; import { expect } from 'expect'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; +import { AWSError } from 'aws-sdk'; +import { HttpResponse } from 'aws-sdk/lib/http_response'; describe('instrumentation-aws-sdk-v2', () => { const responseMockSuccess = { @@ -43,9 +45,20 @@ describe('instrumentation-aws-sdk-v2', () => { }, }; - const responseMockWithError = { + const error: AWSError = { + name: 'error', + message: 'something went wrong', + stack: 'fakeStack', + code: 'errorCode', + time: new Date(), + }; + + const responseMockWithError: Pick< + AWS.Response, + 'requestId' | 'error' + > & { httpResponse: Partial } = { requestId: '0000000000000', - error: 'something went wrong', + error, httpResponse: { statusCode: 400, }, @@ -275,9 +288,22 @@ describe('instrumentation-aws-sdk-v2', () => { const awsSpans = getAwsSpans(); expect(awsSpans.length).toBe(1); const [spanCreateBucket] = awsSpans; - expect(spanCreateBucket.attributes[AttributeNames.AWS_ERROR]).toBe( - responseMockWithError.error + const exceptionEvent = spanCreateBucket.events.filter( + event => event.name === 'exception' ); + expect(exceptionEvent.length).toBe(1); + + expect(exceptionEvent[0]).toStrictEqual( + expect.objectContaining({ + name: 'exception', + attributes: { + 'exception.message': 'something went wrong', + 'exception.stacktrace': 'fakeStack', + 'exception.type': 'errorCode', + }, + }) + ); + expect( spanCreateBucket.attributes[SemanticAttributes.HTTP_STATUS_CODE] ).toBe(400);