13

I am trying to debug what appears to be a socket error in the node.js https library environment when running in the AWS Lambda environment (Node.js 4.3). This issue only occurs highly intermittently and only under heavy load. My team has been able to reproduce the issue consistently with a load test, and we would like to enable debug logging from the https module.

I've found in the node documentation that I can enable debug logging by setting the NODE_DEBUG=https environment variable. However, I don't believe that I can set environment variables: How can I use environmental variables on AWS Lambda?. Additionally, I don't have the ability to change the command line that Lambda uses to invoke my function.

Is there another way to create the same debug logging as setting NODE_DEBUG?

Community
  • 1
  • 1
Ryan Gross
  • 6,423
  • 2
  • 32
  • 44

4 Answers4

6

Here's a monkeypatch:

const util    = require('util');
let debuglog  = util.debuglog;
util.debuglog = set => {
  if (set === 'https') {
    let pid = process.pid;
    return function() {
      let msg = util.format.apply(util, arguments);
      console.error('%s %d: %s', set, pid, msg);
    }
  }
  return debuglog(set);
}

// This has to occur _after_ the code above:
const https = require('https');

It basically enables debug logging for https regardless of $NODE_DEBUG. Easily rewritten to work for any module, tested with Node v4 and v6.

robertklep
  • 198,204
  • 35
  • 394
  • 381
  • 1
    Note that after this answer was posted, it became possible to set environment variables in AWS Lambda (see this answer stackoverflow.com/a/40774215/1024811 on the question about setting env vars in AWS Lambda). That said, being able to control Node's debugging without setting environment variables is still useful, e.g. for Google Cloud Functions. And for anyone with this problem but for the `debug` module, check this out: https://github.com/visionmedia/debug/commit/ab5083f68a7e4c1ab474ff06cd5995d706abf143 – Peter W May 14 '18 at 08:15
1

I'm not familiar with Aws Lambda, but maybe you can still export the variable in the command like below:

NODE_DEBUG=https node app.js
Slawomir Pasko
  • 907
  • 8
  • 14
1

child_process.fork() allows one module to spawn a new node environment with specified environment variables. The two processes can send messages to each other via send(), and receive those messages via 'message' events.

For example, if your current main module is named server.js, then you could add a temporary start.js module (which will be the new lambda function) in the same directory that looks something like this:

// Add NODE_DEBUG to this process's environment variables, which are passed by default to
// the forked node environment.
process.env.NODE_DEBUG = 'https';

const cp = require('child_process');
const n = cp.fork('server.js');

// Cached callback functions, in case client can pass in different callbacks.
// Use an object instead of array, to avoid memory leaks. 
const cbs = {};
var cbIndexCounter = 0; // To make callback indices unique

// Call appropriate callback with response from child process, and delete cached callback.
n.on('message', (m) => {
  cbs[m.cbIndex](m.error, m.result);
  delete cbs[m.cbIndex];
});

n.on('error', (err) => {
  console.log('Child node env error: ', err);
});

// Cache the callback; forward event, context, index to child process; and increment index.
exports.myHandler = function(event, context, callback) {
  cbs[cbIndexCounter] = callback;
  n.send({
    event: event,
    context: context,
    cbIndex: cbIndexCounter++
  });
}

The server.js module can be modified slightly by adding a 'message' event listener:

process.on('message', (m) => {
  exports.myHandler(m.event, m.context, function(error, result) {
    process.send({
      error: error,
      result: result,
      cbIndex: m.cbIndex
    });
  });
});

// The rest of your original code ...
exports.myHandler = function (event, context, callback) {
   // Whatever you need here...
}
cybersam
  • 63,203
  • 6
  • 53
  • 76
0

run the following:

node app.js --https-debug

and inside your app.js have this at the beginning of the script

  process.argv.forEach((val, index) => {
    if(val.match(/--https-debug/)) {
      process.env.NODE_DEBUG = "https";
    }
  });

process.env is an object just like any object, but node sets the environment variables on it, you can always hack it and override whatever variables are set from node global environment.

we use process.argv to capture all arguments sent to node js file in the terminal.

Bamieh
  • 10,358
  • 4
  • 31
  • 52
  • 1
    In lambda, I don't control the command line. When you set the process.env.NODE_DEBUG inside the program, it is already too late. – Ryan Gross Aug 22 '16 at 03:20