Skip to content

Bug: Under load stdout writes are buffered and lost on lambda runtime termination #4774

@slewis77

Description

@slewis77

Expected Behavior

We log a lot of data to CW that has a field index for searching. These are logged at INFO level using Logger. These arrive in large batches from Firehose

We expect all data to be logged successfully in CW

Current Behavior

Under load we find that the underlying stdout write isn't immediately flushed and is queued in memory by the underlying stream. I think this is internal to the writes made via the Console object.

When this happens, nothing waits for that buffer to be freed up and when the lambda completes and the runtime is terminated, that queue is lost and the data isn't written

Note: This is not the same buffer as you get with DEBUG logs in Logger.

This is the docs from the underlying stream write:

/**
* Sends data on the socket. The second parameter specifies the encoding in the
* case of a string. It defaults to UTF8 encoding.
*
* Returns `true` if the entire data was flushed successfully to the kernel
* buffer. Returns `false` if all or part of the data was queued in user memory.`'drain'` will be emitted when the buffer is again free.
*
* The optional `callback` parameter will be executed when the data is finally
* written out, which may not be immediately.
*/

Code snippet

export const logSomething = async (message: ExampleMessage, logger: Logger) => {
  for (const entry of message.results) {
    logger.info('SOME_VALUE', {
      item1: entry.item1,
      item2: entry.item2,
    });
  }
};

Steps to Reproduce

Create a lambda with a known log message at the start and end
Trigger the lambda with data in the event or hardcoded that has a large array of items (in the region of 10,000 items 200 byte objects) to log individually
Add code to the lambda to iterate over the array logging each item
Check the cloudwatch logs, if reproduced you will see the start log message and many of the logged objects, but likely not the end message as the lambda was terminated before the queued data was written

Possible Solution

Add a promise around the socket's drain callback and resolve when fully complete

Powertools for AWS Lambda (TypeScript) version

latest

AWS Lambda function runtime

22.x

Packaging format used

npm

Execution logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingloggerThis item relates to the Logger Utility

    Type

    No type

    Projects

    Status

    Pending customer

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions