elbik
elbik

Reputation: 1897

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

Upvotes: 6

Views: 18159

Answers (2)

elbik
elbik

Reputation: 1897

  • 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"
})

Upvotes: 9

Luke
Luke

Reputation: 1

To build upon the answer above (I do not have enough points to comment) - If you want to follow this pattern, make sure you specify the the type 'metric' of your const metric. It should look like:

new Alarm(this, "AlarmId", {
    metric: 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"
})

Upvotes: 0

Related Questions