aws-xray-sdk-node: Nodejs10.x Error: Missing AWS Lambda trace data for X-Ray.

After updating to the ‘nodejs10.x’ runtime environment, I am now seeing this error message at the start of the cloudwatch logs:

2019-06-14T21:24:54.713Z	undefined	ERROR	Error: Missing AWS Lambda trace data for X-Ray. Expected _X_AMZN_TRACE_ID to be set.
at Object.contextMissingLogError [as contextMissing] (/var/task/handler.js:37802:19)
at Segment.resolveLambdaTraceData (/var/task/handler.js:167833:43)
at Object.getSegment (/var/task/handler.js:37870:17)
at Object.resolveSegment (/var/task/handler.js:37849:19)
at captureOutgoingHTTPs (/var/task/handler.js:94553:31)
at Object.captureHTTPsRequest [as request] (/var/task/handler.js:94638:12)
at Promise (/var/runtime/RAPIDClient.js:91:31)
at new WrappedPromise (/var/task/handler.js:161080:18)
at RAPIDClient.nextInvocation (/var/runtime/RAPIDClient.js:90:12)
at Runtime.handleOnce (/var/runtime/Runtime.js:52:51)

We are using, AWSXRay.captureHTTPsGlobal(require('http')); to capture all http requests and this is the source of the error. It is also capturing all calls to 127.0.0.1 as part of the runtime event loop.

A fix was to move the captureHTTPsGlobal command inside of the lambda function function handler. Before, it was running from the global module level. We are still getting x-ray results for calls to localhost for the lambda runtime environment. Is there a way to ignore requests to 127.0.0.1?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 15
  • Comments: 35 (10 by maintainers)

Most upvoted comments

Lambda has told us a potential solution is underway. I will update this thread once it is released. If the solution does not work, our team will add the filtering logic to ignore these internal calls before Node 8 EOL is reached.

So, I initialize thusly:

const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
AWSXRay.captureHTTPsGlobal(require('https'));

function getKeepAliveAgent() {
  const options = {
    keepAlive: true,
    maxSockets: 50, // from aws-sdk
    rejectUnauthorized: true, // from aws-sdk
  };
  const agent = new https.Agent(options);
  agent.setMaxListeners(0); // from aws-sdk
  return agent;
}

AWS.config.update({
    httpOptions: {
      agent: getKeepAliveAgent(),
    },
  });

Where I’m seeing this error is during cold starts of my Lambda function, wherein I use SecretsManager outside of the handler in the global scope to get the secrets config once and keep it around for the lifetime of the function instance. This global initialization is a pretty common scenario in Lambda.

Hi, can you explain why capturePromise() should be inside lambda handler or otherwise it throws ‘Missing AWS Lambda trace data for X-Ray. Expected _X_AMZN_TRACE_ID to be set’ error (only during lambda’s cold start)? In aws doc (https://docs.aws.amazon.com/xray/latest/devguide/xray-sdk-nodejs-httpclients.html) there is no mention of need for capturePromise invocation, but in aws-xray for node readme (https://github.com/aws/aws-xray-sdk-node/tree/master/packages/core#capture-all-outgoing-axios-requests) there is example for capturing axios with capturePromise invoked on the top of a module, which is opposite to this issue’s solving. According to this issue’s solution capturePromise should be called at the end of a handler, but capturePromise patches promise’s then method, so in my opinion it should be called right at the beginning of a handler to capture all requests inside handler - why you recommend it to be called at the end? It’s a bit confusing, so can you please explain what is correct way of capturing http(s) requests and why?

The problem with calling things like capturePromises is that it is adding another function to the .then. Depending on how many calls a lambda gets, it could end up adding a lot of functions to the Promise prototype slowing things down.

function patchPromise(Promise) {
  var then = Promise.prototype.then;
  Promise.prototype.then = function(onFulfilled, onRejected) {
    if (contextUtils.isAutomaticMode()
      && tryGetCurrentSegment()
    ) {
      var ns = contextUtils.getNamespace();

      onFulfilled = onFulfilled && ns.bind(onFulfilled);
      onRejected = onRejected && ns.bind(onRejected);
    }

    return then.call(this, onFulfilled, onRejected);
  };
}

https://github.com/aws/aws-xray-sdk-node/blob/aws-xray-sdk%403.1.0/packages/core/lib/patchers/promise_p.js#L12-L26

Well… since I’m using Middy I refactored this into middleware so I don’t feel so dirty 🙂

In case anyone’s interested:

// middlewares/instrument.ts
import { Handler } from 'aws-lambda'
import { NextFunction } from "middy";
const AWSXRay = require('aws-xray-sdk');

const instrumentationMiddleware = {
  after: (handler: Handler, next: NextFunction) => {
    AWSXRay.capturePromise();
    next();
  },
}

export default instrumentationMiddleware;
// index.ts
import { APIGatewayEvent, Context, ProxyResult } from 'aws-lambda';
const wrap = require('@dazn/lambda-powertools-pattern-basic');
import instrumentationMiddleware from "./middlewares/instrument";

export const handler = wrap(async (event: APIGatewayEvent, context: Context): Promise<ProxyResult> => {
  /* ... */
  return response;
})
.use(instrumentationMiddleware);

Hi @chearmstrong,

I resolved the issue by moving AWSXRay.capturePromise() into the function handler, immediately before your return statement. Feel free to reopen if you still have issues.

Lambda has released what should be a fix for this problem globally! Please follow up if this issue persists, otherwise I’ll close this issue.

Are there any updates on this issue? We are experiencing this as well and with Node 8 being EoL at year end this would become a problem

Not stale, still relevant.

This remains an issue for us, even after moving AWSXRay.captureHTTPsGlobal(require('https')); into the handler.

Versions of aws-xray-sdk-core tried:

  • 2.5.0
  • 3.0.0-alpha.1

Before – we see “Missing AWS Lambda trace data for X-Ray”

const { ApolloServer } = require("apollo-server-lambda");
const xray = require('aws-xray-sdk-core');
xray.captureHTTPsGlobal(require('https'), false);

// ... other stuff

const server = new ApolloServer({ /** config **/ })
exports.handler = server.createHandler();

After – we still see “Missing AWS Lambda trace data for X-Ray”

const { ApolloServer } = require("apollo-server-lambda");
const xray = require('aws-xray-sdk-core');

// ... other stuff

const server = new ApolloServer({ /** config **/ })
const createHandler = function() {
  const handler = server.createHandler();
  xray.captureHTTPsGlobal(require('https'), false);
  return handler;
}

exports.handler = createHandler();

@willarmiros I’m experiencing the same issue - why is it necessary to move AWSXRay.capturePromise()?

@willarmiros I’m getting Error: Missing AWS Lambda trace data for X-Ray. Expected _X_AMZN_TRACE_ID to be set. when upgrading to version 3.0.0-alpha.1.

I’m using Node v12, and I’m using HTTP keep-alive.

I didn’t get it with version 2.5.0-experimental.1 btw.