I have two microservices namely user-service and notification-service, whenever user sign-up to user-service. the message will add to sqs queue with AWSTraceHeader, now from notification-service sqs-consumer will poll and pass that message to handleMessage callback function and send an email to enduser using SES.
I can able to trace the process till, user-service ---> sqs queue, but how can traceId entire flow like user-service->queue->notification-service->ses. I tried the following code
handleMessage: async (message: SQS.Message) => {
const segment = AWSXRay.getSegment()
if(segment){
segment.trace_id = message.Attributes?.AWSTraceHeader
}
await wiring.sqsService.handleMessage(message);
}
but got the error like below
Property 'trace_id' does not exist on type 'Segment | Subsegment'.
Property 'trace_id' does not exist on type 'Subsegment'.
How can I trace the entire process?
Hello,
In order to set the trace ID of a segment as you want to here, you need to access the trace_id field on the parent Segment, not on the subsegment as you're attempting to now. The AWSXRay.getSegment() API is a bit of a misnomer, it actually gets the current segment OR subsegment in progress. To always retrieve the top-level segment from the subsegment, do:
const entity = AWSXRay.getSegment();
// If entity is a segment, retrieve trace ID directly, otherwise get trace ID from parent segment
const traceId = entity.trace_id ? entity.trace_id : entity.segment.trace_id;
The only problem with this is that you may have several traces representing SQS messages that are "Fanning in" to a single trace on the consumer side. This is the issue that is tracked in #208, so we will not address it here to avoid duplication.
Thanks for your reply, one small question, if I close the segment after handleMessage like below
handleMessage: async (message: SQS.Message) => {
const segment = AWSXRay.getSegment()
if(segment){
segment.trace_id = message.Attributes?.AWSTraceHeader
}
await wiring.sqsService.handleMessage(message);
segment.closeSegment()
}
Do I need to open the new segment again, because openSegment() invoked like below.
const segment = new AWSXRay.Segment(this.appName);
const ns = AWSXRay.getNamespace();
ns.run(() => {
AWSXRay.setSegment(segment);
this.sqsConsumer.start();
});
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs in next 7 days. Thank you for your contributions.
@hariharasudhan-nineleaps I'm not sure I entirely understand your question. Each call to open a segment should have a corresponding call to close the segment later in execution, no matter what (e.g. in a finally block).