The NodeSource Blog

Tutorial: Getting Started on N|Solid for AWS Lambda with CloudFormation and Serverless

Recently NodeSource announced N|Solid for AWS Lambda, which offers low-impact monitoring for Lambda functions built on Node.js. This is the first time NodeSource's monitoring solution for Node.js has been offered for a serverless environment. To help new users get started with ease, I've prepared the following tutorial to provide step-by-step instructions that can be followed by folks who may not already have Lambda functions running in production.

Sample Function

To start, let's write a simple GraphQL Hello World as a serverless function using Apollo and N|Solid for AWS Lambda

const { ApolloServer, gql } = require('apollo-server-lambda')

const typeDefs = gql`
  type Query {
    helloWorld: String
  }
`

const resolvers = {
  Query: {
    helloWorld: () => 'Hello from N|Solid Lambda'
  }
}

const server = new ApolloServer({
  typeDefs,
  resolvers
})

exports.handler = server.createHandler()

It's not required that you use this example—you can use any function you'd like as you proceed through the rest of the tutorial.

AWS Serverless Application Model (SAM)

Next, you'll need a template.yaml file to organize some basic information about your function:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
  helloGraphQL:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: provided
      Environment:
        Variables:
          NSOLID_LICENSE_KEY: <license-key>
      Layers:
        - arn:aws:lambda:us-east-1:800406105498:layer:nsolid-node-10:5
      Events:
        AnyRequest:
          Type: Api
          Properties:
            Path: /graphql
            Method: ANY

template.yaml

  • Runtime property must be set to provided
  • Environment must contain the variable NSOLID_LICENSE_KEY
  • Layers must contain an ARN for the N|Solid runtime layer

Your NSOLID_LICENSE_KEY and instructions for determining the appropriate ARN for your N|Solid runtime layer can both be found in your NodeSource accounts portal.

AWS requires you to create a S3 bucket to store your package, which you can do by running:

aws s3 mb s3://apollo-lambda

Now it's time to create a package and upload it to S3:

aws cloudformation package \
--template-file template.yaml \
--s3-bucket apollo-lambda \
--output-template-file output-template.yaml

After you've uploaded to S3, you can trigger the deploy using the output-template.yaml file generated by aws cloudformation package:

aws cloudformation deploy \
--template-file output-template.yaml \
--stack-name apollolambda \
--capabilities CAPABILITY_IAM

You should now see a message in the terminal that looks like this, which indicates that the deployment was successful:

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - staging

Believe it or not, that's it! Your function will be running using N|Solid for AWS Lambda.

There are other frameworks that simplify writing and deploying functions to AWS Lambda, let's see some other alternatives.

Updating existing AWS Lambda functions

If you already have functions running in AWS Lambda you can update their runtime to use N|Solid by running:

aws lambda update-function-configuration \
--layers arn:aws:lambda:us-east-1:800406105498:layer:nsolid-node-10:5 \
--runtime provided \
--function-name <function-name> \
--environment "Variables={NSOLID_LICENSE_KEY=<license-key>}"
Start using N|Solid for AWS Lambda today Create your NodeSource Account

Serverless Framework

Serverless is a toolkit to develop functions for different providers, including for AWS Lambda.

First, you'll need to install the serverless toolkit:

npm install -g serverless

Next, create a serverless.yaml file. As you can tell from the example below, this is quite similar to the template.yaml file from earlier, but is somewhat simplified and compatible with multiple platforms.

service: apollo-lambda
provider:
  name: aws
  stage: dev
  region: us-east-1
  environment:
    NSOLID_LICENSE_KEY: <license-key>
functions:
  helloGraphQL:
    handler: index.handler
    runtime: provided
    layers:
      - arn:aws:lambda:us-east-1:800406105498:layer:nsolid-node-10:5

serverless.yaml

  • runtime property must be set to provided
  • environment must contain the variable NSOLID_LICENSE_KEY, which can be found in your NodeSource accounts portal, where you can find the appropriate ARN
  • layers must contain a N|Solid runtime layer ARN

Using serverless simplifies the process a bit, so if you're using this option you don't need to create a S3 bucket or a package first.
Ensure all the dependencies are in your source folder by installing them using npm install (in our example we are using apollo-server-lambda) and then run:

serverless deploy

When the deploy has successfully completed you'll see this output in your terminal, including the URL of the deployed function:

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (5.54 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..............................
Serverless: Stack update finished...
Service Information
service: apollo-lambda-serverless
stage: dev
region: us-east-1
stack: apollo-lambda-serverless-dev
api keys:
  None
endpoints:
  ANY - https://xxxxxxx.execute-api.us-east-1.amazonaws.com/dev/graphql
functions:
  helloGraphQL: apollo-lambda-serverless-dev-helloGraphQL
layers:
  None

Additional Layers

If you want to make effective and efficient use of the new AWS Lambda Layers feature to improve sharing of code or dependencies across your layers, N|Solid makes this very easy.

The Node.js module resolution path will include the /lib/node directory of any layer you add to your function when using N|Solid on AWS Lambda. So if you publish a layer that provides your dependencies in that location, they can be both shared, and independently managed from your function’s code.

Bear in mind that the standard Node.js runtimes provided by AWS (nodejs6.10 and nodejs8.10) do not provide a layer-based solution for Node dependencies, so make sure you’re including the N|Solid runtime layer and have selected “Use custom runtime in function code or layer”

Example

Let’s say your function depends on the Redis npm package and today you include it in your function archive with the current structure:

index.js
node_modules/redis/index.js
[...]

With N|Solid, you can publish this dependency as an independent layer with the following structure:

lib/node/redis/index.js
[...]

And by adding this layer along with t he N|Solid runtime, it will transparently discover and load your dependencies as if you had included them in the function itself. As many as 5 layers can be configured for a single Lambda function, including N|Solid itself.

Monitoring your Lambda functions

Once you have your Lambda functions up and running on N|Solid, you can track their activity and performance to identify potential issues or targets for further optimization:

Screen Shot 2018-12-12 at 11.59.45 AM

N|Solid will automatically generate a CPU profile for a random sample of functions. From the CPU profile view, you can zoom in on a specific time frame or view the behavior of specific components in isolation.

Screen Shot 2018-12-12 at 12.00.10 PM

Visit our Getting Started Guide to find more information about implementing and using N|Solid for AWS Lambda. We’re eager to hear feedback on our latest product offering, so if you run into issues or have questions, please don’t hesitate to contact us!

N|Solid for AWS Lambda offers a high-definition view of the performance and behavior of serverless functions.

Start for Free