Node: Request context when invoked by other lambda function

Viewed 554

I'm building an application which consists of multiple lambda functions and which will be part of an already existing application landscape.

My issue on this: I don't know how to extend my logs with a unique trace id in an easy fashion, so that all logs regarding one transaction are logged with the same id.

To give some insight on one of the processes:

  • lambda #1 is using express and is exposing an API via ApiGateway. Within one 'transaction' it is also queuing some events in SQS.
  • lambda #2 is polling the queue regularly and is doing some other work. Afterwards it is calling lambda #1 directly to finish the transaction.

So the whole flow: some other app --Request with TraceID--> ApiGateway -> lambda #1 -> SQS -> lambda #2 -> lambda #1.

What I did until now I'm using request-context for tracing requests. But thats just working if you got a valid request context. So I can't log with the correct trace id on lambda #1 after it was called at the last stage by lambda #2 (which is submitting the trace id in its request).

The invocation point for lambda #1 looks like this:

export function handler(event: any, context: any) {
  if (event.targetAction) {
    switch (event.targetAction as TargetAction) {
      // invocation by lambda #2 will end up here
      // we got no request context for express
      case TargetAction.FINISH_TRANSACTION:
        /** do some other work **/
        return;
      default:
      /** **/
    }
  }
  return awsServerlessExpress.proxy(server, event, context);
}

How do I get my trace-id to the logs in this case?

Other thoughts:

  • I could do a workaround and add a new route to lambda #1 and also submit a path & http method to my event and then pass it to the proxy handler so we end up on an express route. Seems like a bad solution.

I'm very glad for every help or thought on this, even if its pointing me in some complete other direction.

Edit

For now I'm going with the workaround which is working fine. I've created a router which is for internal usage. This is how the handler looks like if anyone is interested:

export function handler(event: any, context: any) {
if (event.targetAction) {
  switch (event.targetAction as TargetAction) {
     case TargetAction.UPDATE_TRANSACTION:
        const updateEvent: ExpressProxyEvent = {
           path: '/internal/update-transaction',
           headers: {
              'Content-Type': 'application/json',
              'x-trace-id': event.xtraceId,
              'x-internal-router-secret': Constants.INTERNAL_ROUTER_SECRET
           },
           body: JSON.stringify(event),
           httpMethod: 'POST'
         };
         event = updateEvent;
         break;
      case /** **/
    }
    return awsServerlessExpress.proxy(server, event, context);
}

With this the traceId can be set in the request-context middleware when invoked directly by another lambda function (the event could also be correctly created in lambda #2, but then it needs to know the path & method for the internal router in lambda #1).

Nevertheless I'm still interested in an independent solution.

0 Answers
Related