You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Ability to swap out the logger with default python logger during local testing #409
Is your feature request related to a problem? Please describe.
When working locally, we often wish to visualise the "message" of logs without structured logging as it is more readable and we have no intention of searching the logs. We also wish to log to file often when testing locally.
Is there any way we can hot-swap the default Python logger or replace the logger universally across a codebase?
Describe the solution you'd like
Ability to disable structured logging across a code base and default to a standard python logger such that we have a way to make the code base log to local file and display without structured logs during local testing.
Describe alternatives you've considered
I thought initially we could just mock out the logger with the default logger, but the introduction of child=True (which is not in the default logger) would mean that does not work I think.
I was thinking maybe we could also try and add the default logger as an additional logger by patching the init of the powertools logger maybe?
hey @bml1g12 would the addition of a custom formatter (structured, not structured) and handler (file, stdout, etc.) as per #404 help?
If so, I can easily add an option to pass in a custom logging handler that writes to a file as that was going to be my last piece before merging that PR.
That way you can control what you want within your formatter, and optionally pass a handler when doing it locally. If not, I'd need some time to think this more deeply.
fromaws_lambda_powertoolsimportLoggerfromaws_lambda_powertools.logging.formatterimportBasePowertoolsFormatterclassCustomFormatter(BasePowertoolsFormatter):
custom_format= {}
defappend_keys(self, **additional_keys):
# used by inject_lambda_context decorator, Logger initialization, and structure_logself.custom_format.update(additional_keys)
defremove_keys(self, keys: Iterable[str]):
# used by Logger public methodforkeyinkeys:
self.custom_format.pop(key, None)
defformat(self, record: logging.LogRecord) ->str: # noqa: A003# Convert logging record to any format you'd want, doesn't have to be JSONreturnjson.dumps(
{
"message": super().format(record),
"timestamp": self.formatTime(record),
"my_default_key": "test",
**self.custom_format,
}
)
custom_formatter=CustomFormatter()
handler=logging.FileHandler('logs.txt')
logger=Logger(logger_formatter=custom_formatter, logger_handler=handler)
Or for when you're not using append_keys, remove_keys, structure_logs, inject_lambda_context decorator, you can:
fromaws_lambda_powertoolsimportLoggerimportloggingformatter=logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
handler=logging.FileHandler('logs.txt') # log output to a filelogger=Logger(logger_formatter=formatter, logger_handler=handler)
Also @bml1g12, if you're not on the AWS Developers Slack channel to chat directly on #lambda-powertools.. I'm happy to jump on a call to learn more about your use of Logger as I believe we can get this UX right for everyone :) You have my email
I am from the same team as @bml1g12, to explain a little further:
We have a serverless application running in lambda that performs some work we would like to evaluate locally in a program that wraps around it. So we would like to have logging such that when we run our serverless application locally the logging calls, that would normally be JSON formatted and written to console, would instead be written to file in a traditional text format.
From what I understand that second example you provide would be able to do just that right? It would capture the logs from when we do powertools log calls, and save them to file in a text.
I will gladly give this a spin and let you know how it goes! Sounds like this is not merged yet, how would I go about testing the custom formater and handler? Getting a bit late here, but I can jump onto a slack call tomorrow!
Perfect, thanks for the additional context.
I haven’t pushed the handler changes as I had them staged. I’ll merge that
on develop branch by tomorrow EOD and ping here so you can take it for a
spin.
On Thu, 22 Apr 2021 at 11:58, Stian Hanssen ***@***.***> wrote:
Hi @heitorlessa <https://github.com/heitorlessa>!
I am from the same team as @bml1g12 <https://github.com/bml1g12>, to
explain a little further:
We have a serverless application running in lambda that performs some work
we would like to evaluate locally in a program that wraps around it. So we
would like to have to such that when we run out serverless application
locally, the logging calls that would normally be JSON formatted and
written to console, would instead be written to file in a traditional text
format.
From what I understand that second example you provide would be able to do
just that right? It would capture the logs from when we do powertools log
calls, and save them to file in a text (JSON format)
If so I will gladly give this a spin and let you know how it goes! Sounds
like this is not merged yet, what branch would have the ability to add
custom formater and handler?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#409 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAZPQBDNSYZUZPTS7HWSTETTJ7XMZANCNFSM43L2XJ5A>
.
@StianHanssen this is now available in the develop branch - You can pip install directly against.
This is the UX to log directly to a file
fromaws_lambda_powertoolsimportLoggerhandler=logging.FileHandler(filename="log_file.json")
logger=Logger(logger_handler=handler)
logger.info("Hello") # populates `log_file.json` in your filesystem
For functional testing, you can also instruct Logger to a custom stream (will document in the next PR):
Hey sorry for late reply! My info was slightly incorrect earlier, the output should go to txt files in a regular logging format like you would have with python's native logging library. I assume it would still just be a case of setting the formater and provide a txt file to the FileHandler.
What do you mean by "develop branch - You can pip install directly against"?
I can't find what version to set for pip to install develop, and I can't seem to be able to pip install the cloned repo. Planning to give it a try now :)
Hey @StianHanssen, no problem, here's how you can do it - and yes you can use a custom formatter.
#Add this line in your requirements.txt
git+https://github.com/awslabs/aws-lambda-powertools-python
#Or if you're doing in a virtual environment to experiment in a quick script
pip install git+https://github.com/awslabs/aws-lambda-powertools-python
NOTE: While you can use any logging.Formatter to test this out and log into a file, it'll fail if you're using Logger decorator inject_lambda_context and structure_logs method, because logging.Formatter won't have append_keys, remove_keys. Checkout the PR readme on the how to do that while I update the docs today: #404
Here's two examples - 1/ Using Pytest Live Log feature w/ no code change, 2/ Conditionally adding a plain text formatter and logging to a file when a flag is set
Thanks for these examples. This works nicely, but it occurs to me that being able to log to both standard out and a file simultaneously would be even better. It seems I can get away with doing using the protected attribute _logger.addHandler to get the best of both worlds. Is this safe?
Will need to test in more detail later and produce a minimal example but it seems some part of the above changes means that we string substitution into the structured logging is not working.
i.e. is_human_readable_enabled = False (structured logging enabled)
LOGGER.info("Hello %s", 1)
Shows in CloudWatch "hello %s" rather than "hello 1"
On Thu, 13 May 2021 at 11:57, Benjamin Lowe ***@***.***> wrote:
Will need to test in more detail later and produce a minimal example but
it seems some part of the above changes means that we string substitution
into the structured logging is not working.
i.e. is_human_readable_enabled = False (structured logging enabled)
LOGGER.info("Hello %s", 1)
Shows in CloudWatch "hello %s" rather than "hello 1"
—
You are receiving this because you were assigned.
Reply to this email directly, view it on GitHub
<#409 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAZPQBBHRPKGGB266WJIDEDTNOPBPANCNFSM43L2XJ5A>
.
I'd do what you basically did - Extract exception_name and exception and use it just like you did.
I've updated the gist to include the exception and the traceback. The stack trace is formatted in an earlier step of the LambdaPowertoolsFormatter named format(), so all you need to do within serialize is to decide how the final output should be.
If you want, you could use a if bloc to check whether there's a traceback in the first place before adding it to the final string, so you don't have blanks - {}, but that's more of an micro-optimization than anything else.
Let me know if there's anything else I can do to make this experience better for you.
Activity
heitorlessa commentedon Apr 22, 2021
hey @bml1g12 would the addition of a custom formatter (structured, not structured) and handler (file, stdout, etc.) as per #404 help?
If so, I can easily add an option to pass in a custom logging handler that writes to a file as that was going to be my last piece before merging that PR.
That way you can control what you want within your formatter, and optionally pass a handler when doing it locally. If not, I'd need some time to think this more deeply.
Or for when you're not using
append_keys,remove_keys,structure_logs,inject_lambda_contextdecorator, you can:heitorlessa commentedon Apr 22, 2021
Also @bml1g12, if you're not on the AWS Developers Slack channel to chat directly on
#lambda-powertools.. I'm happy to jump on a call to learn more about your use of Logger as I believe we can get this UX right for everyone :) You have my emailStianHanssen commentedon Apr 22, 2021
Hi @heitorlessa!
I am from the same team as @bml1g12, to explain a little further:
We have a serverless application running in lambda that performs some work we would like to evaluate locally in a program that wraps around it. So we would like to have logging such that when we run our serverless application locally the logging calls, that would normally be JSON formatted and written to console, would instead be written to file in a traditional text format.
From what I understand that second example you provide would be able to do just that right? It would capture the logs from when we do powertools log calls, and save them to file in a text.
I will gladly give this a spin and let you know how it goes! Sounds like this is not merged yet, how would I go about testing the custom formater and handler? Getting a bit late here, but I can jump onto a slack call tomorrow!
heitorlessa commentedon Apr 22, 2021
heitorlessa commentedon Apr 22, 2021
@StianHanssen this is now available in the
developbranch - You can pip install directly against.This is the UX to log directly to a file
For functional testing, you can also instruct Logger to a custom stream (will document in the next PR):
PR for early docs on custom formatter, handler, UTC, etc. until I produce them: #404
StianHanssen commentedon Apr 23, 2021
Hey sorry for late reply! My info was slightly incorrect earlier, the output should go to txt files in a regular logging format like you would have with python's native logging library. I assume it would still just be a case of setting the formater and provide a txt file to the FileHandler.
What do you mean by "develop branch - You can pip install directly against"?
I can't find what version to set for pip to install develop, and I can't seem to be able to pip install the cloned repo. Planning to give it a try now :)
heitorlessa commentedon Apr 23, 2021
Hey @StianHanssen, no problem, here's how you can do it - and yes you can use a custom formatter.
NOTE: While you can use any
logging.Formatterto test this out and log into a file, it'll fail if you're using Logger decoratorinject_lambda_contextandstructure_logsmethod, becauselogging.Formatterwon't haveappend_keys,remove_keys. Checkout the PR readme on the how to do that while I update the docs today: #404Let me know if you run into any trouble
bml1g12 commentedon May 4, 2021
I tried this but it does not log to file?
heitorlessa commentedon May 4, 2021
The direct install didn't seem to work as you shouldn't be seeing
"logger_handler"as a logging key nor the output in the console.It's working on a fresh new environment - I'm uploading a build from
developbranch. Also, we're releasing 1.15.0 as soon as #418 PR gets merged.aws_lambda_powertools-1.14.0b.tar.gz
bml1g12 commentedon May 4, 2021
Great thanks, indeed a fresh environment sorted me out and this seems to work nicely:
4 remaining items
heitorlessa commentedon May 8, 2021
Here's two examples - 1/ Using Pytest Live Log feature w/ no code change, 2/ Conditionally adding a plain text formatter and logging to a file when a flag is set
https://gist.github.com/heitorlessa/cc36ca86c26ce83eec855b9c250b9e1c
I personally prefer 1 as this is primarily for testing, where 2 being a cleaner than monkey patching IMHO.
bml1g12 commentedon May 11, 2021
Thanks for these examples. This works nicely, but it occurs to me that being able to log to both standard out and a file simultaneously would be even better. It seems I can get away with doing using the protected attribute
_logger.addHandlerto get the best of both worlds. Is this safe?bml1g12 commentedon May 13, 2021
Will need to test in more detail later and produce a minimal example but it seems some part of the above changes means that we string substitution into the structured logging is not working.
i.e. is_human_readable_enabled = False (structured logging enabled)
LOGGER.info("Hello %s", 1)
Shows in CloudWatch "hello %s" rather than "hello 1"
heitorlessa commentedon May 13, 2021
heitorlessa commentedon May 13, 2021
@bml1g12 the regression fix is now out as part of 1.15.1 - would you mind triple check that for us?
bml1g12 commentedon May 13, 2021
I can confirm it fixes this issue for me
bml1g12 commentedon May 13, 2021
When running your gist example
The stacktrace is not logged by a logger.exception call - how does one provide a nicely formatted stack trace?
Would:
Be the recommended approach?
heitorlessa commentedon May 13, 2021
I'd do what you basically did - Extract
exception_nameandexceptionand use it just like you did.I've updated the gist to include the exception and the traceback. The stack trace is formatted in an earlier step of the
LambdaPowertoolsFormatternamedformat(), so all you need to do withinserializeis to decide how the final output should be.If you want, you could use a
ifbloc to check whether there's a traceback in the first place before adding it to the final string, so you don't have blanks- {}, but that's more of an micro-optimization than anything else.Let me know if there's anything else I can do to make this experience better for you.
log.txt: https://gist.github.com/heitorlessa/cc36ca86c26ce83eec855b9c250b9e1c#file-log-txt
heitorlessa commentedon May 21, 2021
Hey @bml1g12 checking in to see if you still need any help here :)
bml1g12 commentedon May 21, 2021
Ah all good thanks; working nicely and thanks for your assistance with this one.