Search code examples
amazon-web-servicesaws-cloudformationamazon-cloudwatchaws-cdk

How to add custom Metric and Alarm to AWS Lambda function via aws-cdk


I kind of stuck with configuring cdk a common use case: to have an Alarm and Metric for Lambda Function

    import lambda = require("@aws-cdk/aws-lambda")
    import { Duration } from "@aws-cdk/core"
    import lambda = require("@aws-cdk/aws-lambda")
    import { Duration } from "@aws-cdk/core";
    import { LogGroup } from '@aws-cdk/aws-logs'
    import { MetricFilter, FilterPattern } from '@aws-cdk/aws-logs'
    import { Alarm, ComparisonOperator, TreatMissingData } from "@aws-cdk/aws-cloudwatch"

    const lambdaFn = new lambda.Function(this, "VouchersPayoutQueueConsumer", {
        functionName: 'lambda-custom-name',
        runtime: lambda.Runtime.NODEJS_10_X,
        code: lambda.Code.fromAsset("dir_name"),
        timeout: Duration.seconds(15),
        memorySize: 1024,
        handler: "handler.handlerMethod",
    })

    const METRIC_NAME = 'metric-name'
    const METRIC_NAMESPACE = 'metric-namespace'

    new MetricFilter(this, `MetricFilterId`, {
        metricName: METRIC_NAME,
        metricNamespace: METRIC_NAMESPACE,
        logGroup: LogGroup.fromLogGroupName(this, "LambdaLogGroupId", `/aws/lambda/${lambdaFn.functionName}`),
        filterPattern: FilterPattern.stringValue("$.params.name", "==", "ReportErrorsToS3"),
        metricValue: "$.params.value"
    })

    new Alarm(this, "AlarmId", {
        metric,
        evaluationPeriods: 1,
        actionsEnabled: true,
        alarmName: `alarms-s3errors`,
        alarmDescription: "Alarm ReportErrorsToS3",
        comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
        treatMissingData: TreatMissingData.IGNORE,
        period: Duration.hours(1),
        threshold: 1,
        statistic: "max"
    })
  1. Where to get the metric and how to map it with MetricFilter?
  2. How to set properly logGroup for MetricFilter to solve the issue:

1/4 | 11:02:05 AM | CREATE_FAILED | AWS::Logs::MetricFilter | MetricFilter (MetricFilter8E0FEF2B) The specified log group does not exist. (Service: AWSLogs; Status Code: 400; Error Code: ResourceNotFoundException; Request ID: a1395551-5768-40c3-baaa-cbb133effe7b)

AWS CDK AWS 1.22.0


Solution

    • The metric is declared separately but the metricName and namespace must be the same as used for MetricFilter
    • LogGroup also must be instantiated separately but with the logGroupName which is the same as, the lambda will create.
    • The suggestive discussion - log group config for lambda function

    Result:

    import { Metric } from "@aws-cdk/aws-cloudwatch";
    import lambda = require("@aws-cdk/aws-lambda")
    import { Duration } from "@aws-cdk/core";
    import { LogGroup } from '@aws-cdk/aws-logs'
    import { MetricFilter, FilterPattern } from '@aws-cdk/aws-logs'
    import { Alarm, ComparisonOperator, TreatMissingData } from "@aws-cdk/aws-cloudwatch"
    
    const LAMBDA_CUSTOM_NAME = `lambda-custom-name`
    
    let logGroup = new LogGroup(this, 'LogGroup', {
      logGroupName: `/aws/lambda/${LAMBDA_CUSTOM_NAME}`
    })
    
    const lambdaFn = new lambda.Function(this, "VouchersPayoutQueueConsumer", {
        functionName: LAMBDA_CUSTOM_NAME,
        runtime: lambda.Runtime.NODEJS_10_X,
        code: lambda.Code.fromAsset("dir_name"),
        timeout: Duration.seconds(15),
        memorySize: 1024,
        handler: "handler.handlerMethod",
    });
    
    
    const METRIC_NAME = 'metric-name'
    const METRIC_NAMESPACE = 'metric-namespace'
    
    const metric = new Metric({
        namespace: METRIC_NAMESPACE,
        metricName: METRIC_NAME
    })
    
    new MetricFilter(this, `MetricFilterId`, {
        metricName: METRIC_NAME,
        metricNamespace: METRIC_NAMESPACE,
        logGroup: logGroup,
        filterPattern: FilterPattern.stringValue("$.params.name", "==", "ReportErrorsToS3"),
        metricValue: "$.params.value"
    })
    
    new Alarm(this, "AlarmId", {
        metric,
        evaluationPeriods: 1,
        actionsEnabled: true,
        alarmName: `alarms-s3errors`,
        alarmDescription: "Alarm ReportErrorsToS3",
        comparisonOperator: ComparisonOperator.GREATER_THAN_THRESHOLD,
        treatMissingData: TreatMissingData.IGNORE,
        period: Duration.hours(1),
        threshold: 1,
        statistic: "max"
    })