aws/aws-xray-sdk-node

need a hook or some other way to utilize the segment context elsewhere

codekitchen opened this issue · 2 comments

Hi! I'm struggling to find a reasonable way to read and update the root Segment in an express app in automatic mode. This seems like a gap in functionality, apologies if I'm just missing something.

A few examples of things I'm trying to do:

  • call segment.setUser() with the user from our auth middleware
  • Log the segment.trace_id and/or add it to the response headers to make it easy to look up a trace for a specific request

I was hoping to just use an express middleware for this, something like:

function addXRayContext(req, res, next) {
    if (req.user)
        AWSXRay.getSegment()?.setUser(req.user.id.toString())

    const traceID = AWSXRay.getSegment()?.trace_id
    if (traceID)
        res.header('X-Amzn-Trace-Id', traceID)

    next()
}

But if I inject that into my middleware stack I get the cls-hooked errors that the README warns about:

app.use(AWSXRay.express.openSegment('solflow-api'))
app.use(addXRayContext)  // doesn't work here
app.use(router)
app.use(AWSXRay.express.closeSegment())

I've dug through all the publicly exposed methods in the core and express packages and I haven't found anything that looks like it'll help me here -- the only option I can think of is to add a call to addXRayContext in every single route handler in our app, which of course would not be fun to maintain.

I think what I'm probably looking for is some way to hook into traceRequestResponseCycle after the root Segment is created. But maybe there's a better solution?

Hi @codekitchen
Once you get the current segment, you should be able to set and get its attribute the way you've mentioned. I don't currently know why it doesn't work. Can you provide a simple reproduction code?
Thanks.

hi @srprash I think there must be something more going on here, because when I tried to boil it down to a minimal repro I do not get an error adding that middleware to the stack between AWSXRay.express.openSegment and the app routes. We do get errors from cls-hooked when trying to do the same within our full application, though.

I was under the impression that this error was expected because of this section of the AWSXRay.express README, where it says:

In automatic mode, the openSegment middleware must be the last middleware added
before defining routes, and the closeSegment middleware must be the
first middleware added after defining routes. Otherwise issues with the cls-hooked
context may occur.

However it appears that is not always the case, which I see it says may occur. Do you know more details about under what situations adding a middleware here can cause cls-hooked errors?