I'm currently trying to set up XRay for a Lambda API. I'm unable to get a stack trace or statusCode that isn't 200. Im hitting an endpoint that simply throws a 500 error. The idea here would be that any errors in my code would bubble up to a final catch statement with an error handler that returns a 500 and logs the error. I would also hope to view the stack trace to the associated error in XRay and sort by 500 responses to find said error.
The function looks something like this (it's in Typescript):
Ignore the obvious errors, missing imports, etc. I basically took the important bits only.
import AWSXRay from 'aws-xray-sdk';
import Logger from "../../common/utils/logger";
import {
AlbEvent,
ALBReturnType,
LambdaContext,
ApiErrorResponse,
} from "src/common/types";
export const formatApiError = (error: ApiError): ApiErrorResponse => ({
statusCode: error.statusCode,
Errors: typeof error.body === "string" ? [error.body] : error.body,
})
export const handleError = (
segment: AWSXRay.Segment,
ctx: LambdaContext,
cb: (x:any, y?:any) => void,
logger: Logger,
error: Error | ApiError
): Promise<ApiErrorResponse | void | String> => {
const subsegment = segment.addNewSubsegment('handleError');
subsegment.addError(error);
if (error instanceof ApiError) {
const response = JSON.stringify(formatApiError(error as ApiError));
segment.close()
return Promise.reject(response);
} else {
logger.error("Internal Server Error: ", error);
const response = JSON.stringify(formatApiError(new ApiError(500, "Internal Server Error: ")));
segment.close()
return Promise.reject(response);
}
};
const handler = async (
event: AlbEvent,
context: LambdaContext,
cb: () => void
): Promise<String> => {
const segment = AWSXRay.getSegment();
logger.child({
requestId: context.requestId,
}); // Pino logger
return handleError(segment as AWSXRay.Segment, context, cb, logger, new Error("Error: oh no"))
}
export { handler };
My response from the API looks like this (Postman does indeed recognize this as a 500 error):
{
"statusCode": 500,
"Errors": [
"Error: oh no"
]
}
However the XRay console only has 200 status codes: XRay only 200 response
And no stack trace is visible: No stack trace
The tracing also doesn't seem to capture the call to the errorHandler function, or the handler:
From what I read in this thread: https://github.com/aws/aws-xray-sdk-node/issues/148
You only have to call "getSegment" to get the auto-generated nodejs lambda root segment.
It's also worth noting that I'm using the API Gateway Lambda integration with lambda error regex/mapping templates. Obviously that's is downstream from the response that XRay records, but maybe the format I'm returning isn't standard for what XRay expects by default?
From the snippet, the subsegment
in handError
is never closed and hence is never sent out. Please refer to https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-subsegments.html to close every subsegment opened.