In this step, we are going to define a couple of metrics that we want to capture amongst our three core services, and will instrument the logMetricEMF() method to push them asynchronously to CloudWatch Metrics, having them first logged to CloudWatch Logs and then processed in background by the utility module we deployed in the previous step.
Let’s define the following Business & Operational metrics:
ColdStartUnsupportedHTTPMethodSuccessfulGetAllItemsFailedGetAllItemsGo back you your Cloud9 environment and open your app workspace at serverless-observability-workshop/code/sample-app.
We are going to edit the serverless-observability-workshop/code/sample-app/template.yaml file to include a Custom Metric Namespace for all Lambda functions in our template. Open the your YAML template and locate the Global section. Add the AWS_EMF_NAMESPACE environment variable for Lambda.
Globals:
Function:
    Runtime: nodejs12.x
    Timeout: 100
    MemorySize: 128
    CodeUri: ./
    Environment:
    Variables:
        APP_NAME: !Ref SampleTable
        SAMPLE_TABLE: !Ref SampleTable
        SERVICE_NAME: item_service
        ENABLE_DEBUG: false
        AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1
        AWS_EMF_NAMESPACE: MonitoringApp # <----- ADD FOR NAMESPACE SETUP  
Save your changes to the serverless-observability-workshop/code/sample-app/template.yaml file.
Open the Lambda function located on /serverless-observability-workshop/code/sample-app/src/handlers/get-all-items.js and start by importing the required Unit and logMetricEMF dependencies in the beginning of the file and initializing a _cold_start variable to capture cold starts in our lambda executions:
const AWS = require('aws-sdk')
const docClient = new AWS.DynamoDB.DocumentClient()
const { Unit } = require("aws-embedded-metrics");
const { logMetricEMF } = require('../lib/logging/logger')
let _cold_start = true
Now, inside the getAllItemsHandler() we are going to test whether it’s the first execution of a given Lambda container and label it as Cold Start, also pushing this information as a CloudWatch Metric using our logMetricEMF() method. Add and if statement checking whether the _cold_start variable is true or false right after the beginning of the try block.
exports.getAllItemsHandler = async (event, context) => {
    let response
    try {
        if (_cold_start) {
            //Metrics
            await logMetricEMF(name = 'ColdStart', unit = Unit.Count, value = 1, { service: 'item_service', function_name: context.functionName })
            _cold_start = false
        }
Now, we are going to capture metrics for UnsupportedHTTPMethod, instrumenting the putMetric() method call if our if (event.httpMethod !== 'GET') evaluates true.
    if (event.httpMethod !== 'GET') {
        await logMetricEMF(name = 'UnsupportedHTTPMethod', unit = Unit.Count, value = 1, { service: 'item_service', operation: 'get-all-items' })
        throw new Error(`getAllItems only accept GET method, you tried: ${event.httpMethod}`)
    }
Next, we are ready to add our business metrics for successful and failed item list retrievals. Still inside your getAllItemsHandler(), find and add in the end of your try and beginning of your catch blocks the metrics for SuccessfulGetAllItems and FailedGetAllItems:
    try{
        //After Successful Response Composition
        //Metrics
        await logMetricEMF(name = 'SuccessfulGetAllItems', unit = Unit.Count, value = 1, { service: 'item_service', operation: 'get-all-items' })
    } catch (err) {
        //After Exception Handling
        //Metrics
        await logMetricEMF(name = 'FailedGetAllItems', unit = Unit.Count, value = 1, { service: 'item_service', operation: 'get-all-items' })
    }
Save your changes to the serverless-observability-workshop/code/sample-app/src/handlers/get-all-items.js file.
Your getAllItemsHandler method should look like the one below
cd ~/environment/serverless-observability-workshop/code/sample-app
sam build && sam deploy
To invoke our API’s, we first need to fetch the ApiUrl output variable that our CloudFormation stack gives us. So let us iterate through our stack and export all output variables as environment variables:
export ApiUrl=$(aws cloudformation describe-stacks --stack-name monitoring-app --output json | jq '.Stacks[].Outputs[] | select(.OutputKey=="ApiUrl") | .OutputValue' | sed -e 's/^"//'  -e 's/"$//')
echo "export ApiUrl="$ApiUrl
Get All Items operationcurl -X GET $ApiUrl/items/ | jq