https://pulumi.com logo
Title
m

millions-furniture-75402

03/05/2021, 4:44 PM
How do I add a Cloudwatch Metrics Alarm Widget to a Cloudwatch Dashboard? I don’t see the widget type, is it unsupported? https://www.pulumi.com/docs/reference/pkg/nodejs/pulumi/awsx/cloudwatch/#apis In a cloudwatch dashboard body it would look something like:
{
  "widgets": [
    {
      "type": "alarm",
      "x": 0,
      "y": 0,
      "width": 24,
      "height": 3,
      "properties": {
        "title": "",
        "alarms": [
          "arn:aws:cloudwatch:us-east-2:0123456789:alarm:SystemBackupDuration-a2737a4",
        ]
      }
    }
  ]
}
p

purple-jelly-68780

03/05/2021, 4:57 PM
@millions-furniture-75402 it looks like there's a MetricAlarm resource under the regular aws package: https://www.pulumi.com/docs/reference/pkg/aws/cloudwatch/metricalarm/ Is that what you're looking for?
m

millions-furniture-75402

03/05/2021, 5:00 PM
I think that’s more for the metric alarm itself. I need a dashboard widget that can display the status of the metric alarm.
There’s a
dashboardBody
property on the
Dashboard
resource you pass a JSON object to.
m

millions-furniture-75402

03/05/2021, 5:03 PM
Yeah, but that’s all or nothing without using the advantageous of the awsx package.
the awsx package seems to be missing
awsx.cloudwatch.AlarmWidget
which I think is what I need.
Or there is a way to use the base classes to provide a more raw widget similar to the snippet in my OP which is a truncated Dashboard Body.
f

faint-table-42725

03/05/2021, 5:05 PM
Ah, sorry, and re-reading your original post, I see you’re looking at this from the
awsx
perspective.
m

millions-furniture-75402

03/05/2021, 5:06 PM
For more context, I’m building my dashboard using awsx:
const dashboardName = `${appName}-${aws.config.region}`;

new awsx.cloudwatch.Dashboard(dashboardName, {
  widgets: [
    // EC2 / bastion
    new awsx.cloudwatch.TextWidget({
      markdown: "# Bastion",
      height: 1,
      width: 24,
    }),
    new awsx.cloudwatch.LineGraphMetricWidget({
      title: "CPU Utilization",
      width: 6,
      height: 3,
      annotations: new awsx.cloudwatch.HorizontalAnnotation(bastionAlarms.cpuUtilization),
      metrics: bastionMetrics.cpuUtilization,
    }),
    new awsx.cloudwatch.LineGraphMetricWidget({
      title: "Network",
      width: 6,
      height: 3,
      metrics: [
        bastionMetrics.networkIn,
        bastionMetrics.networkOut,
      ],
    }),

  ],
});
What I want is something like:
new awsx.cloudwatch.AlarmWidget({
      width: 24,
      height: 3,
      alarms: [
        bastionMetrics.cpuUtilization
      ],
    }),
f

faint-table-42725

03/05/2021, 5:08 PM
is going to be limiting in the way the library is structured
m

millions-furniture-75402

03/05/2021, 5:09 PM
Are theres classes in awsx that I can extend to ultimately create a new widget from RAW json?
I’m not sure if I’m just missing something in the reference documentation that will enable me to do that.
SimpleWidget and
addWidgetJson
method maybe
I’ll revisit after lunch, thanks for rubberducking 🙂 🦆
f

faint-table-42725

03/05/2021, 5:12 PM
I can’t think of an easy way if you’re staying w/in the confines of TypeScript because addWidgetJson takes
WidgetJson
which restricts the
type
to
metric
and
text
I think there’s probably a way to do this by casting things away. Or happy to take a PR where you extend this to include
alarm
🙂
m

millions-furniture-75402

03/05/2021, 6:23 PM
I hacked something together within my project to unblock myself for now. I can revisit a PR, but the barrier to entry for that will be higher for me than someone more familiar with the code case already:
export interface AlarmWidgetArgs extends awsx.cloudwatch.SimpleWidgetArgs {
  alarms: pulumi.Input<string>[];
}

export interface WidgetJson {
  type: pulumi.Input<"alarm" | "metric" | "text">;
  x: pulumi.Input<number>;
  y: pulumi.Input<number>;
  width: pulumi.Input<number>;
  height: pulumi.Input<number>;
  properties: Record<string, any>;
}

export class AlarmWidget implements awsx.cloudwatch.Widget {
  private readonly alarms: pulumi.Input<string>[];

  constructor(private readonly alarmArgs: AlarmWidgetArgs) {
    this.alarms = alarmArgs.alarms;
  }

  public width() {
    return this.alarmArgs.width !== undefined ? this.alarmArgs.width : 6;
  }

  public height() {
    return this.alarmArgs.height !== undefined ? this.alarmArgs.height : 6;
  }

  /** For internal use only. */
  public addWidgetJson(widgetJsons: WidgetJson[], xOffset: number, yOffset: number) {
    // Build the structure common to all simple widgets.  Defer to our subclasses for
    // details only they can fill in.
    widgetJsons.push({
      x: xOffset,
      y: yOffset,
      width: this.width(),
      height: this.height(),
      type: "alarm",
      properties: {
        alarms: this.alarmArgs.alarms
      },
    });
  }
}
Usage:
new AlarmWidget({
      height: 3,
      width: 24,
      alarms: [
        rdsAlarms.burstBalance.arn,
        rdsAlarms.cpuCreditBalance.arn,
        rdsAlarms.cpuUtilization.arn,
        rdsAlarms.databaseConnections.arn,
        rdsAlarms.diskQueueDepth.arn,
        rdsAlarms.freeableMemory.arn,
        rdsAlarms.freeStorageSpace.arn,
        rdsAlarms.swapUsage.arn,
      ],
    }),
Thanks for pointing me in the right direction, you saved me a lot of time 🙂
👍 1