powertools-lambda-python icon indicating copy to clipboard operation
powertools-lambda-python copied to clipboard

Allow logging additional keys as a context manager

Open CaptainDriftwood opened this issue 1 year ago • 8 comments

Use case

The built in logger supports adding additional context using the append_keys and removing that additional context using the remove_keys methods, as documented here: https://docs.powertools.aws.dev/lambda/python/latest/core/logger/#appending-additional-keys

Allow the built in logger to support logging keys as a context manager using the with keyword.

Solution/User Experience

Just adding an additional method that implements the contextlib module's contextmanager decorator as documented here: https://docs.python.org/3/library/contextlib.html#contextlib.contextmanager

Example:

    with logger.with_keys(some_key="some_value"):
        # do something
        logger.info("Something was done")
        # the log output would include the 'some_key' context
    # Do some other thing
    logger.info("Some other thing was done")
    # the log output would not include the 'some_key' context

This would reduce the need to remember to call remove_keys when specific context no longer wants to be logged.

Alternative solutions

No response

Acknowledgment

CaptainDriftwood avatar Feb 06 '24 19:02 CaptainDriftwood

Thanks for opening your first issue here! We'll come back to you as soon as we can. In the meantime, check out the #python channel on our Powertools for AWS Lambda Discord: Invite link

boring-cyborg[bot] avatar Feb 06 '24 19:02 boring-cyborg[bot]

Thanks @CaptainDriftwood for submitting this, we will discuss it during our next gathering.

sthulb avatar Feb 07 '24 09:02 sthulb

Simon and I discussed this a minute ago... got a question @CaptainDriftwood - is your intent to have a given set of keys temporarily added for N log statements? OR add N keys for a given log statement?

This feature would make sense for the former*, but the latter is already possible by passing arbitrary keyword arguments to any log statement

*caveat being that this is not thread-safe (append_keys), as we don't use contextvars yet.


from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger()


def lambda_handler(event: dict, context: LambdaContext) -> str:
    # these keys will only be available in this log statement, subsequent `logger.info` won't have them
    logger.info("Collecting payment", request_id="1123", some_key="some_value")

    return "hello world"

heitorlessa avatar Feb 07 '24 09:02 heitorlessa

@heitorlessa It would be temporarily added for N log statements. I'm not sure how ya'll would get around the thread safety aspect. That is a good point.

CaptainDriftwood avatar Feb 07 '24 20:02 CaptainDriftwood

gotcha! In this case, until we refactor Logger to use contextvars to make it thread-safe, a workaround is to implement a _bind feature which would provide an independent Logger (a deep clone): https://gist.github.com/heitorlessa/95a54e7252f0cb4cf900072fc6f30606

Updating to something like this from your earlier example:

    with logger.with_keys(some_key="some_value") as _logger:  # new logger with some_key="some_value" appended
        # do something
        _logger.info("Something was done")
        # the log output would include the 'some_key' context

    # Do some other thing
    logger.info("Some other thing was done")
    # the log output would not include the 'some_key' context

Would this work for you? or would you prefer to wait for a refactor to use contextvars so the original snippet would stay true (maybe second half of the year)?

Edit: add question.

heitorlessa avatar Feb 26 '24 14:02 heitorlessa

@heitorlessa Can this be done without the contextvars? I'd also like to give the thread-local feature a try but I think I would require some help from your side.

aminalaee avatar Mar 13 '24 14:03 aminalaee

@heitorlessa Apologies for the delayed response. I would prefer to wait for a refactor to use contextvars so the original snippet I provided could be used.

CaptainDriftwood avatar May 12 '24 02:05 CaptainDriftwood

I'm also interested in this feature. For example I know it from loguru in Python or zerolog in Go.

context_logger = logger.bind(ip="192.168.0.1", user="someone")
context_logger.info("Contextualize your logger easily")

trallnag avatar Jul 02 '24 11:07 trallnag