Winston Force flush before ending lambda execution

Viewed 292

I'm trying to use Winston to send logs to Datadog from an Aws Lambda. The problem with the lambdas is that once we return a response, the lambda execution stops and it doesn't give time to Winston to flush the logs.

Is there a way I can force the flush before returning. I'm trying this but it doesn't seem to do the trick:

async function handler (event): Promise<FormattedJSONResponse> {
    const logger = getLogger()
    // do some work
    await closeLogger(logger)
    return awsResponse
}

function closeLogger (logger: Logger): Promise<any> {
  const loggerDone = new Promise((resolve, _) => {
    logger.on('finish', () => {
      resolve(logger)
    })
  })

  logger.end()
  logger.close()
  return loggerDone
}

Versions:

  • AWS Lambda with nodejs 12
  • Winston: 3.3.3

Thanks for your help

1 Answers

First of all I don't understand why you would want to send your logs within you lambda function? If you do so your lambda function will run longer to process the logs, meaning you will be charged for the time it takes to send the logs to Datadog.

Instead, you could save the logs to CloudWatch. To avoid high charges for CloudWatch set the retention to a rather short time, maybe one day. On the CloudWatch log stream you can then add a subscriber which could be another lambda function. This "log-processor"-lambda-function will process, transform the logs and send them to Datadog. With this architecture your first lambda function containing the business logic won't fail if Datadog cannot be reached for instance. It makes your architecture more resilient and has better separation of concerns. Yan Cui wrote a great article on "Centralised logging for AWS Lambda"

Another approach, still separating your logging from your lambda function business logic to some degree, builds upon lambda extensions namely the Lambda Logs API.

AWS Lambda: How runtime and extension API play side-by-side

Put simple, lambda extensions add an extra layer to your function but are not part of the lambda function's code itself. Probably the best part for you: Datadog already offers a ready to use extension, which is responsible for:

  • Pushing real-time enhanced Lambda metrics, custom metrics, and traces from the Datadog Lambda Library to Datadog.
  • Forwarding logs from your Lambda function to Datadog.

For more info on Lambda extensions follow the links mentioned above or have a look at Yan Cui's post "Lambda Logs API: a new way to process Lambda logs in real-time"

Related