Skip to content

Feature request: Simplified logger formatter when in AWS SAM Local #1527

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

Closed
1 of 2 tasks
pmarko1711 opened this issue Sep 20, 2022 · 9 comments
Closed
1 of 2 tasks

Feature request: Simplified logger formatter when in AWS SAM Local #1527

pmarko1711 opened this issue Sep 20, 2022 · 9 comments
Assignees
Labels
feature-request feature request

Comments

@pmarko1711
Copy link
Contributor

Use case

I use aws_lambda_powertools.Logger which works very nicely when looking at logs in Cloudwatch.
Nevertheless, when testing/debugging lambda functions using AWS SAM local invoke, I find the json representation difficult to read and cluttering the console too much.

I know I can swap the logger, or use a custom formatter. But would it not be meaningful to include a simple formatter (instead of the LambdaPowertoolsFormatter that prints out jsons) and use it automatically when not really in Lambda (but e.g. in AWS SAM local invoke) ?

Related issue: #409

Note:

  • Strictly speaking this request might breach your tenet 1 ("AWS Lambda only"), but it depends where you place AWS SAM local invoke or development & testing of Lambda functions outside Lambda

Solution/User Experience

  • Add a "simple" formatter that would print a single line, without serializing to json
    • optionally with a custom format
  • With that, use the existing json formatter only when really in Lambda
    • or alternatively, use the simple one when in AWS SAM Local (and similar, if it can be detected).
    • or make it easy to swap, by e.g. an envvar

Alternative solutions

There exists a solution already and that is to use a custom formatter. 

I opened the issue to consider building this in thinking that it might be beneficial for more users developing and testing Lambda functions.

Acknowledgment

@pmarko1711 pmarko1711 added feature-request feature request triage Pending triage from maintainers labels Sep 20, 2022
@boring-cyborg
Copy link

boring-cyborg bot commented Sep 20, 2022

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 AWS Lambda Powertools Discord: Invite link

@heitorlessa
Copy link
Contributor

Hey @pmarko1711, thanks a lot for taking the time to help us improve! Would you have the output handy to make it easier to reason the next steps?

I need to spin up a project to test. I can't remember if it's an one line JSON (cost optimization), or indented -- would it be more helpful to have indented JSON when running locally if that's not the case yet?

My initial concern: transparently swapping for a no JSON output could lead to incorrect assumptions how the final output would be when deployed.

Look forward to hearing from you

@heitorlessa heitorlessa added need-more-information Pending information to continue need-customer-feedback Requires more customers feedback before making or revisiting a decision and removed triage Pending triage from maintainers labels Sep 25, 2022
@heitorlessa
Copy link
Contributor

Example

Demonstrating how it could look like without any code change.

Before

sam local invoke     
Invoking app.lambda_handler (python3.9)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.9:rapid-1.56.1-x86_64.

Mounting /Users/lessa/DEV/pt-issue-1527/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: ea90d758-5a78-4777-9c46-2017b472fc08 Version: $LATEST
{"level": "INFO", "location": "lambda_handler:39", "message": "This should appear indented and not compacted into a single line...", "timestamp": "2022-09-26 09:03:38,349+0000", "service": "issue-1527"}
END RequestId: ea90d758-5a78-4777-9c46-2017b472fc08
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}REPORT RequestId: ea90d758-5a78-4777-9c46-2017b472fc08     Init Duration: 1.39 ms  Duration: 1141.96 msBilled Duration: 1142 ms Memory Size: 128 MB     Max Memory Used: 128 MB

After

> sam local invoke
Invoking app.lambda_handler (python3.9)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-python3.9:rapid-1.56.1-x86_64.

Mounting /Users/lessa/DEV/pt-issue-1527/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: 9d9eeaaa-6a1f-4355-ac3a-dc20da33f1c6 Version: $LATEST
{
    "level": "INFO",
    "location": "lambda_handler:39",
    "message": "This should appear indented and not compacted into a single line...",
    "timestamp": "2022-09-26 09:02:05,262+0000",
    "service": "issue-1527"
}
END RequestId: 9d9eeaaa-6a1f-4355-ac3a-dc20da33f1c6
REPORT RequestId: 9d9eeaaa-6a1f-4355-ac3a-dc20da33f1c6  Init Duration: 1.04 ms  Duration: 1120.49 ms    Billed Duration: 1121 ms        Memory Size: 128 MB     Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}%

@pmarko1711
Copy link
Contributor Author

Thanks for coming back to be, @heitorlessa .

Right now the output is in this format:

{"level":"INFO","location":"functionB:615","message":"Soemthing happening here","timestamp":"2022-09-26 09:16:26,735+0000","service":"ABC"}
{"level":"INFO","location":"send_message_to_queue:563","message":"{'MessageAttributes': {'somekey1': {'StringValue': 'ABC', 'DataType': 'String'}}, 'MessageBody': '{\"somekey2\": \"someval2\", \"somekey3\": \"true\"}'}","timestamp":"2022-09-26 09:16:26,733+0000","service":"ABC"}
{"level":"INFO","location":"lambda_handler:98","message":"Something else happening here","timestamp":"2022-09-26 09:16:26,735+0000","service":"ABC"}
{"level":"INFO","location":"_functionB:185","message":"Another thing here","timestamp":"2022-09-26 09:16:26,735+0000","service":"ABC"}
{"level":"INFO","location":"_functionC:401","message":"And finally, this happened","timestamp":"2022-09-26 09:16:26,736+0000","service":"ABC"}

In here it looks quite OK, but imagine these messages to be quite longer and auto-wrapped into multiple rows. It's then not that easy to find and read the actual messages while debugging.

When I submitted the ticket I thought of simply outputting (when in AWS SAM Local) something more condensed, where message would be easier to find (since it'd be normally the last item in each row), e.g.:

2022-09-26 09:16:26,735+0000|INFO|ABC|functionB:615|Soemthing happening here
2022-09-26 09:16:26,733+0000|DEBUG|ABC|send_messages_to_queue:563|{'MessageAttributes': {'somekey1': {'StringValue': 'ABC', 'DataType': 'String'}}, 'MessageBody': '{\"somekey2\": \"someval2\", \"somekey3\": \"true\"}'}
2022-09-26 09:16:26,735+0000|WARNING|ABC|lambda_handler:98|Something else happening here
2022-09-26 09:16:26,735+0000|INFO|ABC|_functionB:185|Another thing here
2022-09-26 09:16:26,736+0000|INFO|ABC|_functionC:401|And finally, this happened

For now I've achieved this by initializing a logger with a custom formatter that conditionally overwrote the inherited serialize() method. So in Lambda I get the jsons, but in AWS SAM Local only a more plain output. I guess that's a bit dirty, but still, see (*) below. I thought of embedding something similar into the LambdaPowertoolsFormatter to do this either automatically or on request. If one went this route, it'd be nice if there was a default, concise format that one could override (something along format parameter of Python's logging).

Nevertheless, your idea of indenting JSON outputs could be sufficient here. Maybe making use of pprint then? Wouldn't however having multi-line messages cause more issues elsewhere? (it seems a bit non-standard)

(*)

import os
from aws_lambda_powertools.logging.formatter import LambdaPowertoolsFormatter

AWS_SAM_LOCAL = os.getenv("AWS_SAM_LOCAL", "false").lower() == "true"

class MyCustomFormatter(LambdaPowertoolsFormatter):
    def serialize(self, log: dict) -> str:
        """Use serialize"""
        if AWS_SAM_LOCAL:
            # https://awslabs.github.io/aws-lambda-powertools-python/latest/core/logger/#standard-structured-keys
            prefix = "|".join(
                [
                    log[k]
                    for k in ["timestamp", "level", "service", "location"]
                    if k in log
                ]
            )
            suffix = f"\n{log['exception']}" if "exception" in log else ""
            return "{}: {}{}".format(prefix, log.get("message", ""), suffix)
        else:
            return super().serialize(log)

logger = Logger(service="ABC", logger_formatter=MyCustomFormatter())

@heitorlessa
Copy link
Contributor

On Mobile so excuse formatting and briefness

For JSON multi-line, stdlib "json" has an indent param which is what I used for this POC - it's a no brainer to enable it for local dev ;-)

pprint however could skew results as you have nested objects (plus multiple conversions).

My main worry about plain text is setting the expectations to customers who would see different results in CloudWatch Logs (or elsewhere) -- we have a distinct set of customers persona (dev, Data engineers, Ops, InfoSec) so we always take that into account.

If JSON multi-line suffices for you, we could make this available in the next release!

I could either guide you where to make changes (formatter.py) so we can credit you in the release notes, or if you don't have the bandwidth I can make it later this week.

Once I get my laptop tomorrow,
I'd like to dig on your good comment on "format" method - I'm all for making it easier for customers... and we use standard logging so that's a plus

@pmarko1711
Copy link
Contributor Author

Thanks. Ok, and happy to do add it myself so that I get familiar with your contribute process (and can contribute with sthg else in the future)

@pmarko1711
Copy link
Contributor Author

should it get activated automatically (looking at AWS_SAM_LOCAL) or via a parameter / or a new envvar?

@heitorlessa
Copy link
Contributor

heitorlessa commented Sep 27, 2022 via email

@heitorlessa heitorlessa removed need-more-information Pending information to continue need-customer-feedback Requires more customers feedback before making or revisiting a decision labels Sep 28, 2022
@heitorlessa heitorlessa added the pending-release Fix or implementation already in dev waiting to be released label Oct 4, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Oct 5, 2022

This is now released under 1.30.0 version!

@github-actions github-actions bot closed this as completed Oct 5, 2022
@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Oct 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature-request feature request
Projects
None yet
Development

No branches or pull requests

3 participants