Aws-cdk: CloudWatch Alarms need actions

Created on 25 Mar 2019  路  12Comments  路  Source: aws/aws-cdk

I think so far via the CDK I can't add actions to execute when a CW Alarm enters the alarm state. That's a gap

@aws-cdaws-cloudwatch

Most helpful comment

@AdonousTech I've tried your example and it works great, but this.alarmTopicAction.bind(this, this.alarm); seems to be unnecessary.

All 12 comments

What actions are you looking to execute? it currently supports actions (and you can write your own).

const testAlarm = new Alarm(this, "TestAlarm", {
      ...yourProps
    });

    testAlarm.onAlarm(yourSnsQueue)

It also supports StepScalingAction's if you are looking to scale on alarms

Oh, ok,
I didn't realize that. I was expecting something like alarmActions on AlarmProps, probably because I saw the same prop on CfnAlarmProps.

Daniel

is .onAlarm now deprecated in favour of .addAlarmAction?

I can't seem to find any good examples of using addAlarmAction correctly

    new cloudwatch.Alarm(ref, `${props.name}-${type}`, alarmConfig)
        .addAlarmAction();

So taking a look at the method it self

(method) cloudwatch.Alarm.addAlarmAction(...actions: cloudwatch.IAlarmAction[]): void

So I thought initially we would just pass in the ARN of that action?

The key is to add an object that has a function called bind:

let yourTopic = new Topic(this, 'your-topic');

yourAlarm.addAlarmAction({
    bind(scope, alarm) {
        return { alarmActionArn: yourTopic.topicArn };
    },
});

(Though I don't understand the ceremony needed just to return a topic arn)

Closing this issue since the solution has been provided. Feel free to open a feature request if you think the way it's implemented could be improved.

I know this is closed, but thought I would add some additional info due to the confusing syntax. In addition to @jeshan solution, you can also do the following:

2/14/20 - Removed call to bind

```javascript
const alarmTopic = new Topic(this, 'your-topic');
this.alarmTopicAction = new SnsAction(this.alarmTopic); // assuming this.alarmTopic is in scope
this.alarm.addAlarmAction(this.alarmTopicAction);

@AdonousTech I've tried your example and it works great, but this.alarmTopicAction.bind(this, this.alarm); seems to be unnecessary.

I think I'm hitting this with the Python libraries and I'm not sure what's the workaround.

This is the code:

topic = aws_sns.Topic(
    self,
    "notifications-send-email",
)
topic.add_subscription(aws_sns_subscriptions.EmailSubscription(env["SNS_NOTIFICATIONS_EMAIL"]))

metric = aws_cloudwatch.Metric(
    metric_name="{}-lambda-errors-metric",
    namespace=id,
    statistic="SampleCount",
    period=core.Duration.minutes(amount=1),  # pylint: disable=no-value-for-parameter
    unit=aws_cloudwatch.Unit.COUNT,
)

alarm = aws_cloudwatch.Alarm(
    self,
    "%s-lambda-errors" % id,
    metric=metric,
    evaluation_periods=metric.period.to_seconds(),
    threshold=1,
    actions_enabled=True,
    treat_missing_data=aws_cloudwatch.TreatMissingData.NOT_BREACHING,
)

As soon as I add alarm.add_alarm_action(topic) after alarm definition CDK fails to synthesize:

cdk synth
[...]
jsii.errors.JavaScriptError:
  TypeError: a.bind is not a function
      at /private/var/folders/gq/9w8kyl0s4gjdzlz6vl2w59300000gn/T/jsii-kernel-t87pC3/node_modules/@aws-cdk/aws-cloudwatch/lib/alarm.js:114:57
      at Array.map (<anonymous>)
      at Alarm.addAlarmAction (/private/var/folders/gq/9w8kyl0s4gjdzlz6vl2w59300000gn/T/jsii-kernel-t87pC3/node_modules/@aws-cdk/aws-cloudwatch/lib/alarm.js:114:46)
      at /workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7589:51
      at Kernel._wrapSandboxCode (/workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8225:19)
      at /workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7589:25
      at Kernel._ensureSync (/workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:8198:20)
      at Kernel.invoke (/workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7588:26)
      at KernelHost.processRequest (/workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7296:28)
      at KernelHost.run (/workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7236:14)
      at Immediate._onImmediate (/workdir/.env/lib/python3.8/site-packages/jsii/_embedded/jsii/jsii-runtime.js:7239:37)
      at processImmediate (internal/timers.js:456:21)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "src/cdk.py", line 34, in <module>
    ApiStack(
  File "/workdir/.env/lib/python3.8/site-packages/jsii/_runtime.py", line 66, in __call__
    inst = super().__call__(*args, **kwargs)
  File "/workdir/src/stacks/api/__init__.py", line 90, in __init__
    alarm.add_alarm_action(topic)
  File "/workdir/.env/lib/python3.8/site-packages/aws_cdk/aws_cloudwatch/__init__.py", line 2565, in add_alarm_action
    return jsii.invoke(self, "addAlarmAction", [*actions])
  File "/workdir/.env/lib/python3.8/site-packages/jsii/_kernel/__init__.py", line 113, in wrapped
    return _recursize_dereference(kernel, fn(kernel, *args, **kwargs))
  File "/workdir/.env/lib/python3.8/site-packages/jsii/_kernel/__init__.py", line 284, in invoke
    response = self.provider.invoke(
  File "/workdir/.env/lib/python3.8/site-packages/jsii/_kernel/providers/process.py", line 348, in invoke
    return self._process.send(request, InvokeResponse)
  File "/workdir/.env/lib/python3.8/site-packages/jsii/_kernel/providers/process.py", line 318, in send
    raise JSIIError(resp.error) from JavaScriptError(resp.stack)
jsii.errors.JSIIError: a.bind is not a function
Subprocess exited with error 1

cdk version  # macOs v10.14.6
1.23.0 (build 01f326e)

Now I'm testing with v1.24.0 (build 6619e36) but the error is the same.

You need to use classes from the aws-cloudwatch-actions package. Will add examples to the README.

And how do you create reboot ec2 instance action with cdk?

Was this page helpful?
0 / 5 - 0 ratings