Skip to content

Bug: flush_buffer discards args - percent-style log interpolation broken for buffered records #8005

@niroshaimos

Description

@niroshaimos

Expected Behaviour

When flushing logs from buffer containing percent-style format arguments, logs should be formatted with said args, i.e
logger.debug("user=%s count=%d", "alice", 42) should be flushed as:
"user=alice count=42"

Current Behaviour

Logs flushed from buffer containing, percent-style format arguments (*args) are stored correctly in the buffer but discarded when the buffer is flushed.
i.e
logger.debug("user=%s count=%d", "alice", 42) Is flushed as:
"user=%s count=%d"

Code snippet

import logging
import os

os.environ["_X_AMZN_TRACE_ID"] = (
    "Root=1-5759e988-bd862e3fe1be46a994272793;Parent=53995c3f42cd8ad8;Sampled=1"
)

from aws_lambda_powertools import Logger
from aws_lambda_powertools.logging.buffer import LoggerBufferConfig


class RecordCollector(logging.Handler):
    """Handler that captures emitted LogRecords for inspection."""

    def __init__(self):
        super().__init__()
        self.records: list[logging.LogRecord] = []

    def emit(self, record):
        self.records.append(record)

    def messages(self):
        return [r.getMessage() for r in self.records]


collector = RecordCollector()
collector.setLevel(logging.DEBUG)

logger = Logger(
    service="repro",
    buffer_config=LoggerBufferConfig(
        max_bytes=20480,
        buffer_at_verbosity="DEBUG",
        flush_on_error_log=True,
    ),
)
logger.addHandler(collector)

logger.debug("user=%s count=%d", "alice", 42)
assert collector.messages() == [], "Should be buffered, not emitted yet"

logger.flush_buffer()

print("Flushed messages:", collector.messages())

# BUG: message is "user=%s count=%d" instead of "user=alice count=42"
assert "user=alice count=42" in collector.messages(), (
    f"Expected interpolated message, got: {collector.messages()}"
)

Possible Solution

_create_and_flush_log_record hardcodes args=() instead of using the args saved in the buffer record.
The result is that flushed log messages contain the raw format string (e.g. "user=%s count=%d") instead of the interpolated message ("user=alice count=42").

When manually changing args=() to args=log_line.get("args", ()), at this line the flush works as expected

Steps to Reproduce

The above snippet proves the issue locally - the general issue reproduced in running lambdas as well

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.12

Packaging format used

PyPi

Debugging logs

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriagePending triage from maintainers

    Type

    No type

    Projects

    Status

    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions