UNPKG

@pulumi/awsx

Version:

[![Actions Status](https://github.com/pulumi/pulumi-awsx/workflows/master/badge.svg)](https://github.com/pulumi/pulumi-awsx/actions) [![Slack](http://www.pulumi.com/images/docs/badges/slack.svg)](https://slack.pulumi.com) [![NPM version](https://badge.fur

411 lines • 18 kB
"use strict"; // Copyright 2016-2018, Pulumi Corporation. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.Metric = void 0; exports.mergeDimensions = mergeDimensions; const aws = __importStar(require("@pulumi/aws")); const pulumi = __importStar(require("@pulumi/pulumi")); const widgets_simple_1 = require("./widgets_simple"); const utils = __importStar(require("../utils")); /** * Metrics are the fundamental concept in CloudWatch. A metric represents a time-ordered set of data * points that are published to CloudWatch. Think of a metric as a variable to monitor, and the data * points as representing the values of that variable over time. For example, the CPU usage of a * particular EC2 instance is one metric provided by Amazon EC2. The data points themselves can come * from any application or business activity from which you collect data. * * AWS services send metrics to CloudWatch, and you can send your own custom metrics to CloudWatch. * You can add the data points in any order, and at any rate you choose. You can retrieve statistics * about those data points as an ordered set of time-series data. * * Metrics exist only in the region in which they are created. Metrics cannot be deleted, but they * automatically expire after 15 months if no new data is published to them. Data points older than * 15 months expire on a rolling basis; as new data points come in, data older than 15 months is * dropped. * * Metrics are uniquely defined by a name, a namespace, and zero or more dimensions. Each data point * in a metric has a time stamp, and (optionally) a unit of measure. You can retrieve statistics * from CloudWatch for any metric. * * see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html#Metric * for more details. */ class Metric { /** * Optional resource this is a metric for. Used only for parenting purposes when making new alarms. */ resource; /** * The namespace for this metric. See docs for the * [list of namespaces](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/aws-namespaces.html). * See docs for * [supported metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html). */ namespace; /** * The name for this metric. See docs for * [supported metrics](https://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html). */ name; /** * The dimensions for this metric. For the list of available dimensions see the AWS documentation * [here](http://docs.aws.amazon.com/AmazonCloudWatch/latest/DeveloperGuide/CW_Support_For_AWS.html). */ dimensions; /** * The period in seconds over which the specified [statistic] is applied. Must be in multiples * of 60. Periods are defined in numbers of seconds, and valid values for period are 1, 5, 10, * 30, or any multiple of 60. For example, to specify a period of six minutes, use 360 as the * period value. You can adjust how the data is aggregated by varying the length of the period. * A period can be as short as one second or as long as one day (86,400 seconds). The default * value is 60 seconds. * * See https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html * for more details. */ period; /** * The statistic to apply to the alarm's associated metric. Either of the following is * supported: `SampleCount`, `Average`, `Sum`, `Minimum`, `Maximum`. * * Defaults to [Average] if [statistic] and [extendedStatistic] is unspecified. */ statistic; /** * The percentile statistic for the metric associated with the alarm. Specify a value between * [0.0] and [100]. */ extendedStatistic; /** * The unit for this metric. * * See https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/API_MetricDatum.html */ unit; /** * The six-digit HTML hex color code to be used for this metric. * * Only used if this metric is displayed in a [Dashboard] with a [MetricWidget]. */ color; /** * The label to display for this metric in the graph legend. If this is not specified, the * metric is given an autogenerated label that distinguishes it from the other metrics in the * widget. * * Only used if this metric is displayed in a [Dashboard] with a [MetricWidget]. */ label; /** * Set this to true to have the metric appear in the graph, or false to have it be hidden. The * default is true. * * Only used if this metric is displayed in a [Dashboard] with a [MetricWidget]. */ visible; /** * Where on the graph to display the y-axis for this metric. The default is left. * * Only used if this metric is displayed in a [Dashboard] with a [MetricWidget]. */ yAxis; /** * The id of this metric. This id can be used as part of a math expression. */ id; /** * @param resource Optional resource this is a metric for. This is only used for parenting * purposes. i.e. if an [Alarm] is created from this [Metric], then [resource] will be used as * the parent of the alarm by default. */ constructor(args, resource) { this.resource = resource; this.name = pulumi.output(args.name); if (args.dimensions) { this.dimensions = pulumi.output(args.dimensions); } this.namespace = pulumi.output(args.namespace); this.period = utils.ifUndefined(args.period, 300).apply(p => validatePeriod(p)); this.statistic = pulumi.all([args.statistic, args.extendedStatistic]) .apply(([statistic, extendedStatistic]) => validateStatistics(statistic, extendedStatistic)); this.extendedStatistic = pulumi.output(args.extendedStatistic).apply(es => validateExtendedStatistic(es)); this.unit = pulumi.output(args.unit); // Only for metrics that are placed in dashboards. this.color = pulumi.output(args.color); this.label = pulumi.output(args.label); this.visible = utils.ifUndefined(args.visible, true); this.yAxis = utils.ifUndefined(args.yAxis, "left"); this.id = pulumi.output(args.id); } with(change) { if (!change) { return this; } let result = this; result = hasOwnProperty(change, "dimensions") ? result.withDimensions(change.dimensions) : result; result = hasOwnProperty(change, "period") ? result.withPeriod(change.period) : result; result = hasOwnProperty(change, "statistic") ? result.withStatistic(change.statistic) : result; result = hasOwnProperty(change, "extendedStatistic") ? result.withExtendedStatistic(change.extendedStatistic) : result; result = hasOwnProperty(change, "unit") ? result.withUnit(change.unit) : result; result = hasOwnProperty(change, "color") ? result.withColor(change.color) : result; result = hasOwnProperty(change, "label") ? result.withLabel(change.label) : result; result = hasOwnProperty(change, "visible") ? result.withVisible(change.visible) : result; result = hasOwnProperty(change, "yAxis") ? result.withYAxis(change.yAxis) : result; result = hasOwnProperty(change, "id") ? result.withId(change.id) : result; return result; } features() { return { namespace: this.namespace, name: this.name, dimensions: this.dimensions, period: this.period, statistic: this.statistic, extendedStatistic: this.extendedStatistic, unit: this.unit, }; } spread() { return { resource: this.resource, namespace: this.namespace, name: this.name, dimensions: this.dimensions, period: this.period, statistic: this.statistic, extendedStatistic: this.extendedStatistic, unit: this.unit, color: this.color, label: this.label, visible: this.visible, yAxis: this.yAxis, id: this.id }; } /** * Produces a new [Metric] instances with the specific [dimensions] of this instance overwritten * with the [dimensions] pass in as arguments. Because this is a merging, to unset a particular * dimension, pass in an explicit value of `{ name: undefined }`. To clear all dimensions, pass * in `undefined` for the entire argument. */ withDimensions(dimensions) { return new Metric({ ...this.spread(), dimensions: mergeDimensions(this.dimensions, dimensions), }, this.resource); } withPeriod(period) { return new Metric({ ...this.spread(), period }, this.resource); } withUnit(unit) { return new Metric({ ...this.spread(), unit }, this.resource); } withColor(color) { return new Metric({ ...this.spread(), color }, this.resource); } withLabel(label) { return new Metric({ ...this.spread(), label }, this.resource); } withVisible(visible) { return new Metric({ ...this.spread(), visible }, this.resource); } withYAxis(yAxis) { return new Metric({ ...this.spread(), yAxis }, this.resource); } withId(id) { return new Metric({ ...this.spread(), id }, this.resource); } withStatistic(statistic) { // If they're supplying a statistic, then we want to clear out extendedStatistic. return new Metric({ ...this.spread(), statistic, extendedStatistic: pulumi.all([statistic, this.extendedStatistic]) .apply(([statistic, extendedStatistic]) => statistic !== undefined ? undefined : extendedStatistic), }, this.resource); } withExtendedStatistic(extendedStatistic) { // If they're supplying an extendedStatistic, then we want to clear out statistic. return new Metric({ ...this.spread(), statistic: pulumi.all([this.statistic, extendedStatistic]) .apply(([statistic, extendedStatistic]) => extendedStatistic !== undefined ? undefined : statistic), extendedStatistic, }, this.resource); } createAlarm(name, args, opts = {}) { const comparisonOperator = utils.ifUndefined(args.comparisonOperator, "GreaterThanOrEqualToThreshold"); return new aws.cloudwatch.MetricAlarm(name, { ...args, comparisonOperator, actionsEnabled: utils.ifUndefined(args.actionsEnabled, true), alarmDescription: computeDescription(this, args, comparisonOperator), treatMissingData: utils.ifUndefined(args.treatMissingData, "missing"), dimensions: this.dimensions, extendedStatistic: this.extendedStatistic.apply(s => s === undefined ? undefined : `p${s}`), metricName: this.name, namespace: this.namespace, period: this.period, statistic: this.statistic, unit: this.unit.apply(u => u), }, { parent: this.resource, ...opts }); } /** For internal use only. */ addWidgetJson(metrics) { // Each single metric in the metrics array has the following format: // [Namespace, MetricName, [{DimensionName,DimensionValue}...] [Rendering Properties Object] ] // See: https://docs.aws.amazon.com/AmazonCloudWatch/latest/APIReference/CloudWatch-Dashboard-Body-Structure.html#CloudWatch-Dashboard-Properties-Metrics-Array-Format const op = pulumi.all([this.spread(), (0, widgets_simple_1.statisticString)(this.spread())]).apply(([uw, stat]) => { const result = []; if (uw.period % 60 !== 0) { throw new Error(`Dashboard metric period must be a multiple of 60: ${uw.period}`); } result.push(uw.namespace); result.push(uw.name); // note that dimensions are just added added directly into the array, there's no // sub-array or other structure to hold them. if (uw.dimensions) { for (const key in uw.dimensions) { if (uw.dimensions.hasOwnProperty(key)) { result.push(key); result.push(uw.dimensions[key]); } } } const renderingProps = { stat, color: uw.color, label: uw.label, period: uw.period, visible: uw.visible, yAxis: uw.yAxis, id: uw.id }; result.push(renderingProps); return result; }); metrics.push(op); } } exports.Metric = Metric; /** @internal */ function mergeDimensions(oldDimensions, newDimensions) { if (!newDimensions) { // they're explicitly clearing out all dimensions. return undefined; } return pulumi.all([oldDimensions, newDimensions]).apply(([oldDimensions, newDimensions]) => { if (!oldDimensions) { // no old dimensions, can just use all the new dimensions passed in. return newDimensions; } // have both old and new. need to overwrite all the old dimensions with whatever is in new. const result = { ...oldDimensions }; for (const name in newDimensions) { if (newDimensions.hasOwnProperty(name)) { result[name] = newDimensions[name]; } } return result; }); } function hasOwnProperty(obj, key) { return obj.hasOwnProperty(key); } function computeDescription(metric, args, comparisonOperator) { return pulumi.all([metric, args, comparisonOperator]) .apply(([metric, args, comparisonOperator]) => { if (args.alarmDescription !== undefined) { return args.alarmDescription; } const name = metric.label || metric.name; const op = operatorDescription(comparisonOperator); const period = args.evaluationPeriods === 1 ? `for 1 datapoint` : `for ${args.evaluationPeriods} datapoints`; const time = args.evaluationPeriods * metric.period; const timeDesc = time % 60 === 0 ? `within ${time / 60} minutes` : `within ${time} seconds`; return `${name} ${op} ${args.threshold} ${period} ${timeDesc}`; }); } function operatorDescription(op) { switch (op) { case "GreaterThanOrEqualToThreshold": return ">="; case "GreaterThanThreshold": return ">"; case "LessThanThreshold": return "<"; case "LessThanOrEqualToThreshold": return "<="; default: throw new Error(`Unexpected comparison operator: ${op}`); } } function validatePeriod(period) { // valid values for period are 1, 5, 10, 30, or any multiple of 60 if (period !== 1 && period !== 5 && period !== 10 && period !== 30 && period % 60 !== 0) { throw new Error("Valid values for [args.period] are 1, 5, 10, 30, or any multiple of 60"); } return period; } function validateStatistics(statistic, extendedStatistic) { if (statistic === undefined && extendedStatistic === undefined) { return "Average"; } if (statistic !== undefined && extendedStatistic !== undefined) { throw new Error("Only provide one of [args.statistic] and [args.extendedStatistic]"); } return statistic; } function validateExtendedStatistic(extendedStatistic) { if (extendedStatistic !== undefined) { if (extendedStatistic < 0 || extendedStatistic > 100) { throw new Error("[args.extendedStatistic] must be between 0 and 100."); } } return extendedStatistic; } //# sourceMappingURL=metric.js.map