DEV Community

Cover image for Add AWS Powertools
Paweł Piwosz
Paweł Piwosz

Posted on

Add AWS Powertools

Recap

We have definitely better logging ability now. But notice one thing - what we have, allows us to understand the global information about Lambda. We still do not understand the internals. We know that execution suffered by cold start. But.. how much?

AWS Powertools

Fortunately, we have tooling which we can use to know more.

Unfortunatelly though, this tool is available for Python and Java only. At least, at this moment.

According to Roadmap there is some work on .Net support. Hopefully we will see it soon. Personally, I would like to see nodejs and golang support too.

But we are talking about Python.

We already added one layer, for Lambda Insights. This time we need to do exactly the same thing, add new layer, but we will do it completelly differently. And we will work with the SAM template only.

Ok, First, as you remember, adding Lambda Insights in SAM template was quite easy:

      Layers:
        - !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:14"
Enter fullscreen mode Exit fullscreen mode

We used !Sub to make substitution of ${AWS::Region} into actual region. It will not work with Powertools, as it is available in a few locations only.

We also have the version specified = :14 on the end. This time we will specify it differently too.

To say more, we will not reffer to lambda, but serverlessrepo.

In orger to have it completed, we create the new resource in our template. I placed it just below Resources: statement.

Resources:

  AwsLambdaPowertoolsPythonLayer:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer
        SemanticVersion: 1.22.0 # change to latest semantic version available in SAR
Enter fullscreen mode Exit fullscreen mode

At the time of writting this tutorial, the available version was 1.22.0


Obviously, we can check which versions we can use and which one is the last one.

aws serverlessrepo list-application-versions --application-id arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer
Enter fullscreen mode Exit fullscreen mode

Sometimes we need to add --region <region> (in my case it will be eu-west-1) and --profile <profile_name>. Let's see it:

aws serverlessrepo list-application-versions --application-id arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer --region eu-west-1 --profile demo 
Enter fullscreen mode Exit fullscreen mode

Output should look similar to this:

{
    "Versions": [
        {
            "ApplicationId": "arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer",
            "CreationTime": "2020-08-25T11:36:35.772Z",
            "SemanticVersion": "1.3.0",
            "SourceCodeUrl": "https://github.com/awslabs/aws-lambda-powertools-python"
        },
Enter fullscreen mode Exit fullscreen mode

It is not too handy to go through it. Let's make it better to select the last version.

aws serverlessrepo list-application-versions --application-id arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer --region eu-west-1 --profile demo --query 'Versions[*].SemanticVersion'
Enter fullscreen mode Exit fullscreen mode

And now we have:

[
    "1.3.0",
    "1.3.1",
    "1.4.0",
    "1.5.0",
    "1.6.0",
    "1.7.0",
    "1.8.0",
    "1.9.0",
    "1.10.0",
    "1.10.1",
    "1.10.2",
    "1.10.3",
    "1.10.4",
    "1.10.5",
    "1.11.0",
    "1.12.0",
    "1.13.0",
    "1.14.0",
    "1.15.0",
    "1.15.1",
    "1.16.0",
    "1.16.1",
    "1.17.0",
    "1.17.1",
    "1.18.0",
    "1.18.1",
    "1.19.0",
    "1.20.0",
-- More  --
Enter fullscreen mode Exit fullscreen mode

Better. But still... We have all versions and we need to scroll to grab the last one. Also, not perfect for scripting.

Let's nail it.

aws serverlessrepo list-application-versions --application-id arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer --region eu-west-1 --profile demo --query 'Versions[::-1].SemanticVersion | [0]'
Enter fullscreen mode Exit fullscreen mode

And now we have:

"1.22.0"
Enter fullscreen mode Exit fullscreen mode

Perfect.

What we have done? we used ---query in order to go through Versions and select all in reverse order [::-1]. We took into consideration only one field of Versions, which is .SemanticVersion. And on the end we piped it with | and took only the first value [0]. That's it :)


Ok, so we confirmed the version. We can safely use it in our resource description, shown on the beginning of this article.

But it is not the end!


Now it is time to add this layer to definition of our Lambda function.

Layers:
        - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn
        - !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:14"
Enter fullscreen mode Exit fullscreen mode

Notice, we added it before Insights, what is not that important. What is important, is the difference between these two definitions. In case of Powertools we used !GetAtt in order to get the attribute of the defined resource. In case of AWS::Serverless::Application we can use !Ref which is simply the id of the resource, or '!GetAtt to collect Outputs.ApplicationOutputName which is the ApplicationOutputName. Another words, we "anchor" the layer definition to created application.


We need to complete last step here, the configuration of Powertools. According to documentation, Lambda needs to have some Variables set. We will do it directly in SAM template.

      Layers:
        - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn
        - !Sub "arn:aws:lambda:${AWS::Region}:580247275435:layer:LambdaInsightsExtension:14"
      Environment:
        Variables:
          LOG_LEVEL: "INFO"
          POWERTOOLS_SERVICE_NAME: simpleFunctionService
          POWERTOOLS_METRICS_NAMESPACE: simpleFunctionMetrics
Enter fullscreen mode Exit fullscreen mode

I attached the snipped with previously added layer to show where to place variables.

What we have here?

We say what LOG_LEVEL we want. In our case it is "INFO" and it is enough. Also, it is the default value (another is DEBUG). We also set the POWERTOOLS_SERVICE_NAME, it is simply the name of the service which will be visible through all logs entries, and POWERTOOLS_METRICS_NAMESPACE which will be used to construct the namespace for the metrics in CloudWatch.

These three are the basic for our setup.


Last but not least, we need to remember that the IAM Role which we use (well, IAM Policy) needs to have access, therefore the easiest ay which you can go is just simply add serverlessrepo:* to your policy. It is ok for tests and plays, but for "professional use" please narrow it down.

Also, if you are creating the setup through CloudFormation, remember about CAPABILITY_AUTO_EXPAND capability. It is needed in order to operate with layer added the way we did.


More about it you can read in documentation


Lambda Powertools layer installed
Ok, we addedd the Powertools layer. But doing simply this we achieved nothing. What we need to do, is implementation in the code, what we will do in the next episode.


Cover image by Hebi B. from Pixabay

Discussion (0)