"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const cdk = require("@aws-cdk/cdk");
const alarm_1 = require("./alarm");
const util_statistic_1 = require("./util.statistic");
/**
 * A metric emitted by a service
 *
 * The metric is a combination of a metric identifier (namespace, name and dimensions)
 * and an aggregation function (statistic, period and unit).
 *
 * It also contains metadata which is used only in graphs, such as color and label.
 * It makes sense to embed this in here, so that compound constructs can attach
 * that metadata to metrics they expose.
 *
 * This class does not represent a resource, so hence is not a construct. Instead,
 * Metric is an abstraction that makes it easy to specify metrics for use in both
 * alarms and graphs.
 */
class Metric {
    /**
     * Grant permissions to the given identity to write metrics.
     *
     * @param identity The IAM identity to give permissions to.
     */
    static grantPutMetricData(identity) {
        if (!identity) {
            return;
        }
        identity.addToPolicy(new cdk.PolicyStatement()
            .addAllResources()
            .addAction("cloudwatch:PutMetricData"));
    }
    constructor(props) {
        if (props.periodSec !== undefined
            && props.periodSec !== 1 && props.periodSec !== 5 && props.periodSec !== 10 && props.periodSec !== 30
            && props.periodSec % 60 !== 0) {
            throw new Error("'periodSec' must be 1, 5, 10, 30, or a multiple of 60");
        }
        this.dimensions = props.dimensions;
        this.namespace = props.namespace;
        this.metricName = props.metricName;
        this.periodSec = props.periodSec !== undefined ? props.periodSec : 300;
        this.statistic = props.statistic || "Average";
        this.label = props.label;
        this.color = props.color;
        this.unit = props.unit;
        // Try parsing, this will throw if it's not a valid stat
        util_statistic_1.parseStatistic(this.statistic);
    }
    /**
     * Return a copy of Metric with properties changed.
     *
     * All properties except namespace and metricName can be changed.
     *
     * @param props The set of properties to change.
     */
    with(props) {
        return new Metric({
            dimensions: ifUndefined(props.dimensions, this.dimensions),
            namespace: this.namespace,
            metricName: this.metricName,
            periodSec: ifUndefined(props.periodSec, this.periodSec),
            statistic: ifUndefined(props.statistic, this.statistic),
            unit: ifUndefined(props.unit, this.unit),
            label: ifUndefined(props.label, this.label),
            color: ifUndefined(props.color, this.color)
        });
    }
    /**
     * Make a new Alarm for this metric
     *
     * Combines both properties that may adjust the metric (aggregation) as well
     * as alarm properties.
     */
    newAlarm(parent, name, props) {
        return new alarm_1.Alarm(parent, name, {
            metric: this.with({
                statistic: props.statistic,
                periodSec: props.periodSec,
            }),
            alarmName: props.alarmName,
            alarmDescription: props.alarmDescription,
            comparisonOperator: props.comparisonOperator,
            threshold: props.threshold,
            evaluationPeriods: props.evaluationPeriods,
            evaluateLowSampleCountPercentile: props.evaluateLowSampleCountPercentile,
            treatMissingData: props.treatMissingData,
            actionsEnabled: props.actionsEnabled,
        });
    }
    /**
     * Return the dimensions of this Metric as a list of Dimension.
     */
    dimensionsAsList() {
        const dims = this.dimensions;
        if (dims === undefined) {
            return [];
        }
        const list = Object.keys(dims).map(key => ({ name: key, value: dims[key] }));
        return list;
    }
}
exports.Metric = Metric;
/**
 * Statistic to use over the aggregation period
 */
var Statistic;
(function (Statistic) {
    Statistic["SampleCount"] = "SampleCount";
    Statistic["Average"] = "Average";
    Statistic["Sum"] = "Sum";
    Statistic["Minimum"] = "Minimum";
    Statistic["Maximum"] = "Maximum";
})(Statistic = exports.Statistic || (exports.Statistic = {}));
/**
 * Unit for metric
 */
var Unit;
(function (Unit) {
    Unit["Seconds"] = "Seconds";
    Unit["Microseconds"] = "Microseconds";
    Unit["Milliseconds"] = "Milliseconds";
    Unit["Bytes_"] = "Bytes";
    Unit["Kilobytes"] = "Kilobytes";
    Unit["Megabytes"] = "Megabytes";
    Unit["Gigabytes"] = "Gigabytes";
    Unit["Terabytes"] = "Terabytes";
    Unit["Bits"] = "Bits";
    Unit["Kilobits"] = "Kilobits";
    Unit["Megabits"] = "Megabits";
    Unit["Gigabits"] = "Gigabits";
    Unit["Terabits"] = "Terabits";
    Unit["Percent"] = "Percent";
    Unit["Count"] = "Count";
    Unit["BytesPerSecond"] = "Bytes/Second";
    Unit["KilobytesPerSecond"] = "Kilobytes/Second";
    Unit["MegabytesPerSecond"] = "Megabytes/Second";
    Unit["GigabytesPerSecond"] = "Gigabytes/Second";
    Unit["TerabytesPerSecond"] = "Terabytes/Second";
    Unit["BitsPerSecond"] = "Bits/Second";
    Unit["KilobitsPerSecond"] = "Kilobits/Second";
    Unit["MegabitsPerSecond"] = "Megabits/Second";
    Unit["GigabitsPerSecond"] = "Gigabits/Second";
    Unit["TerabitsPerSecond"] = "Terabits/Second";
    Unit["CountPerSecond"] = "Count/Second";
    Unit["None"] = "None";
})(Unit = exports.Unit || (exports.Unit = {}));
function ifUndefined(x, def) {
    if (x !== undefined) {
        return x;
    }
    return def;
}
//# sourceMappingURL=data:application/json;base64, 