Skip to content

refactor(tracer): log warning instead of throwing when segment is not found #1370

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 20, 2023
Merged
Show file tree
Hide file tree
Changes from 5 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
16 changes: 8 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions packages/tracer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
},
"dependencies": {
"@aws-lambda-powertools/commons": "^1.6.0",
"aws-xray-sdk-core": "^3.4.0"
"aws-xray-sdk-core": "^3.4.1"
},
"keywords": [
"aws",
Expand All @@ -63,4 +63,4 @@
"serverless",
"nodejs"
]
}
}
35 changes: 14 additions & 21 deletions packages/tracer/src/Tracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { Segment, Subsegment } from 'aws-xray-sdk-core';
*
* const tracer = new Tracer({ serviceName: 'serverlessAirline' });
*
* const lambdaHandler = async (_event: any, _context: any) => {
* const lambdaHandler = async (_event: any, _context: any) => {
* ...
* };
*
Expand Down Expand Up @@ -154,19 +154,24 @@ class Tracer extends Utility implements TracerInterface {
*
* @param error - Error to serialize as metadata
*/
public addErrorAsMetadata(error: Error): void {
public addErrorAsMetadata(error: Error, remote?: boolean): void {
if (!this.isTracingEnabled()) {
return;
}

const subsegment = this.getSegment();
if (subsegment === undefined) {

return;
}

if (!this.captureError) {
subsegment.addErrorFlag();

return;
}

subsegment.addError(error, false);
subsegment.addError(error, remote || false);
}

/**
Expand Down Expand Up @@ -527,13 +532,15 @@ class Tracer extends Utility implements TracerInterface {
*
* @returns segment - The active segment or subsegment in the current scope.
*/
public getSegment(): Segment | Subsegment {
public getSegment(): Segment | Subsegment | undefined {
if (!this.isTracingEnabled()) {
return new Subsegment('## Dummy segment');
}
const segment = this.provider.getSegment();
if (segment === undefined) {
throw new Error('Failed to get the current sub/segment from the context.');
console.warn(
'Failed to get the current sub/segment from the context, this is likely because you are not using the Tracer in a Lambda function.'
);
}

return segment;
Expand Down Expand Up @@ -573,13 +580,7 @@ class Tracer extends Utility implements TracerInterface {
public putAnnotation(key: string, value: string | number | boolean): void {
if (!this.isTracingEnabled()) return;

const document = this.getSegment();
if (document instanceof Segment) {
console.warn('You cannot annotate the main segment in a Lambda execution environment');

return;
}
document.addAnnotation(key, value);
this.provider.putAnnotation(key, value);
}

/**
Expand All @@ -606,15 +607,7 @@ class Tracer extends Utility implements TracerInterface {
public putMetadata(key: string, value: unknown, namespace?: string | undefined): void {
if (!this.isTracingEnabled()) return;

const document = this.getSegment();
if (document instanceof Segment) {
console.warn('You cannot add metadata to the main segment in a Lambda execution environment');

return;
}

namespace = namespace || this.serviceName;
document.addMetadata(key, value, namespace);
this.provider.putMetadata(key, value, namespace || this.serviceName);
}

/**
Expand Down
4 changes: 2 additions & 2 deletions packages/tracer/src/TracerInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { CaptureLambdaHandlerOptions, CaptureMethodOptions, HandlerMethodDecorat
import { Segment, Subsegment } from 'aws-xray-sdk-core';

interface TracerInterface {
addErrorAsMetadata(error: Error): void
addErrorAsMetadata(error: Error, remote?: boolean): void
addResponseAsMetadata(data?: unknown, methodName?: string): void
addServiceNameAnnotation(): void
annotateColdStart(): void
Expand All @@ -11,7 +11,7 @@ interface TracerInterface {
captureAWSClient<T>(service: T): void | T
captureLambdaHandler(options?: CaptureLambdaHandlerOptions): HandlerMethodDecorator
captureMethod(options?: CaptureMethodOptions): MethodDecorator
getSegment(): Segment | Subsegment
getSegment(): Segment | Subsegment | undefined
getRootXrayTraceId(): string | undefined
isTracingEnabled(): boolean
putAnnotation: (key: string, value: string | number | boolean) => void
Expand Down
20 changes: 14 additions & 6 deletions packages/tracer/src/middleware/middy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,26 @@ import type {
* @returns middleware - The middy middleware object
*/
const captureLambdaHandler = (target: Tracer, options?: CaptureLambdaHandlerOptions): MiddlewareLikeObj => {
let lambdaSegment: Subsegment | Segment;
let lambdaSegment: Segment;
let handlerSegment: Subsegment;

const open = (): void => {
lambdaSegment = target.getSegment();
const handlerSegment = lambdaSegment.addNewSubsegment(`## ${process.env._HANDLER}`);
const segment = target.getSegment();
if (segment === undefined) {
return;
}
// If segment is defined, then it is a Segment as this middleware is only used for Lambda Handlers
lambdaSegment = segment as Segment;
handlerSegment = lambdaSegment.addNewSubsegment(`## ${process.env._HANDLER}`);
target.setSegment(handlerSegment);
};

const close = (): void => {
const subsegment = target.getSegment();
subsegment.close();
target.setSegment(lambdaSegment as Segment);
if (handlerSegment === undefined || lambdaSegment === null) {
return;
}
handlerSegment.close();
target.setSegment(lambdaSegment);
};

const captureLambdaHandlerBefore = async (): Promise<void> => {
Expand Down
53 changes: 50 additions & 3 deletions packages/tracer/src/provider/ProviderService.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,27 @@
import { ContextMissingStrategy } from 'aws-xray-sdk-core/dist/lib/context_utils';
import {
ContextMissingStrategy
} from 'aws-xray-sdk-core/dist/lib/context_utils';
import { Namespace } from 'cls-hooked';
import { ProviderServiceInterface } from '.';
import { captureAWS, captureAWSClient, captureAWSv3Client, captureAsyncFunc, captureFunc, captureHTTPsGlobal, getNamespace, getSegment, setSegment, Segment, Subsegment, setContextMissingStrategy, setDaemonAddress, setLogger, Logger } from 'aws-xray-sdk-core';
import {
captureAWS,
captureAWSClient,
captureAWSv3Client,
captureAsyncFunc,
captureFunc,
captureHTTPsGlobal,
getNamespace,
getSegment,
setSegment,
Segment,
Subsegment,
setContextMissingStrategy,
setDaemonAddress,
setLogger,
Logger
} from 'aws-xray-sdk-core';

class ProviderService implements ProviderServiceInterface {

public captureAWS<T>(awssdk: T): T {
return captureAWS(awssdk);
}
Expand Down Expand Up @@ -42,6 +59,36 @@ class ProviderService implements ProviderServiceInterface {
return getSegment();
}

public putAnnotation(key: string, value: string | number | boolean): void {
const segment = this.getSegment();
if (segment === undefined) {
console.warn('No active segment or subsegment found, skipping annotation');

return;
}
if (segment instanceof Segment) {
console.warn('You cannot annotate the main segment in a Lambda execution environment');

return;
}
segment.addAnnotation(key, value);
}

public putMetadata(key: string, value: unknown, namespace?: string): void {
const segment = this.getSegment();
if (segment === undefined) {
console.warn('No active segment or subsegment found, skipping metadata addition');

return;
}
if (segment instanceof Segment) {
console.warn('You cannot add metadata to the main segment in a Lambda execution environment');

return;
}
segment.addMetadata(key, value, namespace);
}

public setContextMissingStrategy(strategy: unknown): void {
setContextMissingStrategy(strategy as ContextMissingStrategy);
}
Expand Down
4 changes: 4 additions & 0 deletions packages/tracer/src/provider/ProviderServiceInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ interface ProviderServiceInterface {
captureFunc(name: string, fcn: (subsegment?: Subsegment) => unknown, parent?: Segment | Subsegment): unknown

captureHTTPsGlobal(): void

putAnnotation(key: string, value: string | number | boolean): void

putMetadata(key: string, value: unknown, namespace?: string): void
}

export {
Expand Down
Loading