-
Notifications
You must be signed in to change notification settings - Fork 402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Support thread-local keys for logger #991
Comments
Wow, what a great write up @Dunedan !! Thank you! I really like the first proposal - this makes it explicit whoever is reading the code, it doesn't incur into an additional unbounded logger, etc. I have a few questions:
Internals For Logger, we keep state within the Formatter under When a log statement occurs, Python logging calls our custom Super looking forward to this. |
Sorry, I'm afraid don't have enough time for that right now. I'd be happy to provide feedback though.
Thread local storage sounds good. That's also how
For me that'd fit my expectation: Whenever I add something to the global context, it'll appear in log records afterwards, no matter if the record was logged by the main thread or any other thread.
Usually I'd say yes please, but there is one argument against adding additional keys by default to the logs: CloudWatch ingestion cost. We're already thinking twice about what to add to CloudWatch logs, simply because it's already one of the biggest line items on our AWS bill. |
Update: haven't forgotten this, but will likely to tackle only next year due to re:Invent and PTOs. We've recently added support for kwargs in all log statements that should make this problem slightly easier: https://awslabs.github.io/aws-lambda-powertools-python/2.2.0/core/logger/#ephemeral-metadata from aws_lambda_powertools import Logger
from aws_lambda_powertools.utilities.typing import LambdaContext
logger = Logger()
def handler(event: dict, context: LambdaContext) -> str:
logger.info("Collecting payment", request_id="1123")
return "hello world" |
Hi @heitorlessa, I'd be happy to work on the implementation of this issue if you haven't already started. |
I somehow missed this important message :/ Absolutely!! I haven't started and I'd love help here. ContextVars would highly likely be the solution here - we couldn't do that before as we supported 3.6. thank you @shanab !! |
Hey @heitorlessa, I want to contribute to this RFC. I got the implementation working locally and the PR should be ready in the next day or two. I just need to update some test cases and documentation. I will post the PR once it is ready. |
Hi everyone! @SimonBFrank is working on PR #5141 to implement thread-safe methods for the Logger utility and we are having some important discussions there. I will paste the link to the last comment here and would love some feedback there. Last comment: #5141 (comment) |
|
This is now released under 3.2.0 version! |
Key information
Summary
Provide the ability to append thread-local keys to a logger which only get included in log records logged in the thread they got added to.
Motivation
As AWS Lambda provides multiple CPU cores it makes sense for certain workloads to distribute work across multiple threads. Currently it's not possible to append keys to a logger on a per-thread basis. That however would be very helpful for logging thread-specific information.
structlog, another popular Python logger offering structured logging, supports such a feature under the term "thread-local contexts".
Proposal
In addition to manage globally scoped keys, Logger needs an interface to manage thread-local keys. This interface must consist of the ability to append keys, remove keys and clear all thread-local keys of the current thread. The ability to clear all keys of the current thread is helpful when using thread pools where threads are being reused, but shouldn't retain log keys of previous usages.
I can imagine two ways how this could work (but I'd be happy with another way as well): Additional methods for Logger for managing thread-local keys or the ability to get a "thread-aware" child logger which can then be used to configure thread-local keys.
Proposal 1: Additional methods
Using additional methods for the existing Logger class would require to somehow indicate that they relate to the current thread. So names like
append_thread_local_keys
/remove_thread_local_keys
/clear_thread_local_keys
could be used. Here is an example how that could look like:Proposal 2: Child logger
Offering the ability to get a thread-local child logger from an existing logger would offer usage like that:
For performance reasons when re-using threads it might be worth to consider to not create a new child logger for every call to
Logger.get_thread_local_logger()
, but instead to just to the clear keys of a possibly already existing child logger for the same thread.One drawback of this proposal might be that it'd be cumbersome to use when the logic running in a thread is more complex and spans multiple functions, as the logger instance would need to be passed between these functions.
If this feature should be available in other runtimes (e.g. Java, Typescript), how would this look like to ensure consistency?
IMO it shouldn't be a problem to port that to the other runtimes in the same way as well.
User Experience
How would customers use it?
Without the need for thread-local keys, customers would us AWS Lambda Powertools' Logger the same way as they do right now.
With the need for thread-local keys, customers would call the respective methods to enhance records logged in a thread with additional useful information. A code example for that is shown above.
Any configuration or corner cases you'd expect?
There might be different expectations regarding the behavior when globally scoped keys get appended while a thread is running and its logger configuration has been already done. Will such global keys be included in records logged by the thread immediately or only after the logger configuration for the thread got re-initialized? I personally would prefer global keys to get included immediately into records logged by threads as well.
Demonstration of before and after on how the experience will be better
Before:
After:
Drawbacks
The only drawbacks I can imagine right now are a more complex Logger interface and a possible performance impact when logging records, depending on the resulting implementation.
Rationale and alternatives
The only other option I did consider was manually creating one logger per thread, but that feels cumbersome, because aside from the thread-local keys, it would need to be configured identical to the logger for the main thread.
Customers who wish to log thread-local keys have no straight-forward way available to do so and either have to employ workarounds like using the
extra
keyword to add the desired keys for each record or to use another logger.Unresolved questions
The text was updated successfully, but these errors were encountered: