I recently tried to use AWS X-Ray in NodeJS and C# Lambdas. My informational objects go through these both types of Lambdas, so I would like to build an entire lifecycle represented as a trace for the objects. Accordingly, in order to achieve this, I need to connect the current segment to the parent traceId. I like the option to turn off the Active Tracing flag for NodeJS Lambdas and implemented a custom tracing logic, which works well:
const segment = new Segment(segmentName);
const traceHeaderStr = sqsRecord?.attributes?.AWSTraceHeader;
if (traceHeaderStr) {
const traceHeader = AWSXRay.utils.processTraceData(sqsRecord?.attributes?.AWSTraceHeader);
segment.trace_id = traceHeader["root"];
segment.parent_id = traceHeader["parent"];
}
await AWSXRay.getNamespace().runPromise(async function () {
AWSXRay.setSegment(segment);
try {
// do some work here
} catch (error) {
segment.addError(error);
throw error;
} finally {
segment.close();
}
});
The same approach doesn't work for C# Lambdas, since it they are using a Facade Segment without allowing to overwrite parentId or traceId. I tried to reproduce the NodeJS logic, but if the Active Tracing flag is turned off, nothing gets passed to X-Ray at all. If it's turned on, parentId or traceId don't seem to be overwritten + annotations don't get added either.
I know that it's not a standard way to use C# Lambdas, since I'm supposed to use subsegments instead. However, this works for NodeJS! And I need a way to connect the current segment to the previous context. Do you know any tricks which would help reproduce same behavior as NodeJS and at the same time would be nicer than using the pure X-Ray API (manually written JSON objects in PutTraceSegmentsAsync)?
My C# snippet:
Segment segment = new Segment(_serviceName);
string traceHeaderStr = sqsMessage.Attributes.TryGetValue("AWSTraceHeader");
if (!string.IsNullOrEmpty(traceHeaderStr))
{
TraceHeader traceHeader = TraceHeader.FromString(traceHeaderStr);
segment.TraceId = traceHeader.RootTraceId;
segment.ParentId = traceHeader.ParentId;
}
AWSXRayRecorder.Instance.SetEntity(segment);
try
{
segment.AddAnnotation("MyNote", "test");
// do some work here
}
catch (Exception ex)
{
segment.AddException(ex);
throw;
}
finally
{
segment.Release();
}
I think ideally segment creation is not allowed in lambda. I'm not sure why you are able to see traces in Node SDK. I think this is not the recommended way to use X-Ray SDK inside lambda. If you want to trace entire life cycle then probably you can parse the trace id from trace header and use it on the other end.