Cloud watch needs to be clear and in particular meaningful so once you decide to collect data by Sumologic or Splunk or any other log stream collector, you will receive a proper log.

By proper log I mean these kind of supports:

  • nicely Json formatted log
  • CorrelationId to connect all logs over execution period of lambda
  • log level to be able to activate debug level at runtime in case some error happened and you need to see more detail.

Since AWS Lambda follow a standard way of coding, we can log detail based on some pre-assumption.
For instance every single function which is introduced as a entry point, have event and context with a clear definition which we can leverage.

I deployed a log-winston-aws-level npm package which covers all scenarios above and we will review it in this post.

Quick recap of the code flow

In the following image, you can see a very typical flow for Aws Lambda function. We can potentially capture some initial state for our function and generate the CorrelationId to pass it through during the execution time to all methods.
aws-lambda-flow-2

Capture initial data at entryPoint

Calling the code below can help capturing and returning the necessary detail:

const setupLogger = (event, context) => {
 if ((event.headers) && (event.headers['level'])) {
   process.env.LOGLEVEL = event.headers['level'];
   logger.updateLevel(process.env.LOGLEVEL);
 }
 else process.env.LOGLEVEL = 'info';
 return logger.entryPoint(event, context);
}

The code above gets the log level at runtime from header of request and set in order to log all debug level logs.

Also logger.entryPoint(event, context) will capture the start time, Correlation and some other details about the event and return the object for connecting all codes by CorrelationId

Capture final response at endPoint

Happy lambda will return a response as you expected and sometimes you need to capture the response, CorrelationId, StatusCode and ExecutionTime.
They are all can be done in endPoint code. Per the follow above, the handleSuccess will call logger.endPoint(result, loggParams);

Format the Error object

When error happens you potentially can log Stack, Status and Error message by calling logger.error(logger.errTransformer(err, loggParams.CorrelationId));

logger.errTransformer(err, loggParams.CorrelationId) some how extract these properties from the error object and pump it to logger.error which is one of the functions of winston library.

Format all logs

formatter hooked up to console.log transporter so all logs are formatted before they are written on the the log stream.
you basically can see and understand more detail by looking at winston