UNPKG

@aws-cdk/aws-cloudwatch

Version:

The CDK Construct Library for AWS::CloudWatch

546 lines 78.6 kB
"use strict"; var _a, _b; Object.defineProperty(exports, "__esModule", { value: true }); exports.MathExpression = exports.Metric = void 0; const jsiiDeprecationWarnings = require("../.warnings.jsii.js"); const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti"); const iam = require("@aws-cdk/aws-iam"); const cdk = require("@aws-cdk/core"); const alarm_1 = require("./alarm"); const metric_util_1 = require("./private/metric-util"); const statistic_1 = require("./private/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 { constructor(props) { var _c; try { jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MetricProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.constructor); } throw error; } this.period = props.period || cdk.Duration.minutes(5); const periodSec = this.period.toSeconds(); if (periodSec !== 1 && periodSec !== 5 && periodSec !== 10 && periodSec !== 30 && periodSec % 60 !== 0) { throw new Error(`'period' must be 1, 5, 10, 30, or a multiple of 60 seconds, received ${periodSec}`); } this.dimensions = this.validateDimensions((_c = props.dimensionsMap) !== null && _c !== void 0 ? _c : props.dimensions); this.namespace = props.namespace; this.metricName = props.metricName; // Try parsing, this will throw if it's not a valid stat this.statistic = statistic_1.normalizeStatistic(props.statistic || 'Average'); this.label = props.label; this.color = props.color; this.unit = props.unit; this.account = props.account; this.region = props.region; this.warnings = undefined; } /** * Grant permissions to the given identity to write metrics. * * @param grantee The IAM identity to give permissions to. */ static grantPutMetricData(grantee) { return iam.Grant.addToPrincipal({ grantee, actions: ['cloudwatch:PutMetricData'], resourceArns: ['*'], }); } /** * 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) { var _c, _d; try { jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MetricOptions(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.with); } throw error; } // Short-circuit creating a new object if there would be no effective change if ((props.label === undefined || props.label === this.label) && (props.color === undefined || props.color === this.color) && (props.statistic === undefined || props.statistic === this.statistic) && (props.unit === undefined || props.unit === this.unit) && (props.account === undefined || props.account === this.account) && (props.region === undefined || props.region === this.region) // For these we're not going to do deep equality, misses some opportunity for optimization // but that's okay. && (props.dimensions === undefined) && (props.dimensionsMap === undefined) && (props.period === undefined || props.period.toSeconds() === this.period.toSeconds())) { return this; } return new Metric({ dimensionsMap: (_d = (_c = props.dimensionsMap) !== null && _c !== void 0 ? _c : props.dimensions) !== null && _d !== void 0 ? _d : this.dimensions, namespace: this.namespace, metricName: this.metricName, period: ifUndefined(props.period, this.period), statistic: ifUndefined(props.statistic, this.statistic), unit: ifUndefined(props.unit, this.unit), label: ifUndefined(props.label, this.label), color: ifUndefined(props.color, this.color), account: ifUndefined(props.account, this.account), region: ifUndefined(props.region, this.region), }); } /** * Attach the metric object to the given construct scope * * Returns a Metric object that uses the account and region from the Stack * the given construct is defined in. If the metric is subsequently used * in a Dashboard or Alarm in a different Stack defined in a different * account or region, the appropriate 'region' and 'account' fields * will be added to it. * * If the scope we attach to is in an environment-agnostic stack, * nothing is done and the same Metric object is returned. */ attachTo(scope) { const stack = cdk.Stack.of(scope); return this.with({ region: cdk.Token.isUnresolved(stack.region) ? undefined : stack.region, account: cdk.Token.isUnresolved(stack.account) ? undefined : stack.account, }); } toMetricConfig() { const dims = this.dimensionsAsList(); return { metricStat: { dimensions: dims.length > 0 ? dims : undefined, namespace: this.namespace, metricName: this.metricName, period: this.period, statistic: this.statistic, unitFilter: this.unit, account: this.account, region: this.region, }, renderingProperties: { color: this.color, label: this.label, }, }; } /** @deprecated use toMetricConfig() */ toAlarmConfig() { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.Metric#toAlarmConfig", "use toMetricConfig()"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.toAlarmConfig); } throw error; } const metricConfig = this.toMetricConfig(); if (metricConfig.metricStat === undefined) { throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead'); } const stat = statistic_1.parseStatistic(metricConfig.metricStat.statistic); return { dimensions: metricConfig.metricStat.dimensions, namespace: metricConfig.metricStat.namespace, metricName: metricConfig.metricStat.metricName, period: metricConfig.metricStat.period.toSeconds(), statistic: stat.type === 'simple' ? stat.statistic : undefined, extendedStatistic: stat.type === 'percentile' ? 'p' + stat.percentile : undefined, unit: this.unit, }; } /** * @deprecated use toMetricConfig() */ toGraphConfig() { var _c, _d, _e, _f; try { jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.Metric#toGraphConfig", "use toMetricConfig()"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.toGraphConfig); } throw error; } const metricConfig = this.toMetricConfig(); if (metricConfig.metricStat === undefined) { throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead'); } return { dimensions: metricConfig.metricStat.dimensions, namespace: metricConfig.metricStat.namespace, metricName: metricConfig.metricStat.metricName, renderingProperties: { period: metricConfig.metricStat.period.toSeconds(), stat: metricConfig.metricStat.statistic, color: asString((_c = metricConfig.renderingProperties) === null || _c === void 0 ? void 0 : _c.color), label: asString((_d = metricConfig.renderingProperties) === null || _d === void 0 ? void 0 : _d.label), }, // deprecated properties for backwards compatibility period: metricConfig.metricStat.period.toSeconds(), statistic: metricConfig.metricStat.statistic, color: asString((_e = metricConfig.renderingProperties) === null || _e === void 0 ? void 0 : _e.color), label: asString((_f = metricConfig.renderingProperties) === null || _f === void 0 ? void 0 : _f.label), unit: this.unit, }; } /** * Make a new Alarm for this metric * * Combines both properties that may adjust the metric (aggregation) as well * as alarm properties. */ createAlarm(scope, id, props) { try { jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_CreateAlarmOptions(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.createAlarm); } throw error; } return new alarm_1.Alarm(scope, id, { metric: this.with({ statistic: props.statistic, period: props.period, }), alarmName: props.alarmName, alarmDescription: props.alarmDescription, comparisonOperator: props.comparisonOperator, datapointsToAlarm: props.datapointsToAlarm, threshold: props.threshold, evaluationPeriods: props.evaluationPeriods, evaluateLowSampleCountPercentile: props.evaluateLowSampleCountPercentile, treatMissingData: props.treatMissingData, actionsEnabled: props.actionsEnabled, }); } toString() { return this.label || this.metricName; } /** * 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).sort().map(key => ({ name: key, value: dims[key] })); return list; } validateDimensions(dims) { if (!dims) { return dims; } var dimsArray = Object.keys(dims); if ((dimsArray === null || dimsArray === void 0 ? void 0 : dimsArray.length) > 10) { throw new Error(`The maximum number of dimensions is 10, received ${dimsArray.length}`); } dimsArray.map(key => { if (dims[key] === undefined || dims[key] === null) { throw new Error(`Dimension value of '${dims[key]}' is invalid`); } ; if (key.length < 1 || key.length > 255) { throw new Error(`Dimension name must be at least 1 and no more than 255 characters; received ${key}`); } ; if (dims[key].length < 1 || dims[key].length > 255) { throw new Error(`Dimension value must be at least 1 and no more than 255 characters; received ${dims[key]}`); } ; }); return dims; } } exports.Metric = Metric; _a = JSII_RTTI_SYMBOL_1; Metric[_a] = { fqn: "@aws-cdk/aws-cloudwatch.Metric", version: "1.157.0" }; function asString(x) { if (x === undefined) { return undefined; } if (typeof x !== 'string') { throw new Error(`Expected string, got ${x}`); } return x; } /** * A math expression built with metric(s) emitted by a service * * The math expression is a combination of an expression (x+y) and metrics to apply expression on. * 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. * * MathExpression can also be used for search expressions. In this case, * it also optionally accepts a searchRegion and searchAccount property for cross-environment * search expressions. * * This class does not represent a resource, so hence is not a construct. Instead, * MathExpression is an abstraction that makes it easy to specify metrics for use in both * alarms and graphs. */ class MathExpression { constructor(props) { var _c, _d; try { jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MathExpressionProps(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.constructor); } throw error; } this.period = props.period || cdk.Duration.minutes(5); this.expression = props.expression; this.usingMetrics = changeAllPeriods((_c = props.usingMetrics) !== null && _c !== void 0 ? _c : {}, this.period); this.label = props.label; this.color = props.color; this.searchAccount = props.searchAccount; this.searchRegion = props.searchRegion; const invalidVariableNames = Object.keys(this.usingMetrics).filter(x => !validVariableName(x)); if (invalidVariableNames.length > 0) { throw new Error(`Invalid variable names in expression: ${invalidVariableNames}. Must start with lowercase letter and only contain alphanumerics.`); } this.validateNoIdConflicts(); // Check that all IDs used in the expression are also in the `usingMetrics` map. We // can't throw on this anymore since we didn't use to do this validation from the start // and now there will be loads of people who are violating the expected contract, but // we can add warnings. const missingIdentifiers = allIdentifiersInExpression(this.expression).filter(i => !this.usingMetrics[i]); const warnings = []; if (missingIdentifiers.length > 0) { warnings.push(`Math expression '${this.expression}' references unknown identifiers: ${missingIdentifiers.join(', ')}. Please add them to the 'usingMetrics' map.`); } // Also copy warnings from deeper levels so graphs, alarms only have to inspect the top-level objects for (const m of Object.values(this.usingMetrics)) { warnings.push(...(_d = m.warnings) !== null && _d !== void 0 ? _d : []); } if (warnings.length > 0) { this.warnings = warnings; } } /** * 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) { try { jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MathExpressionOptions(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.with); } throw error; } // Short-circuit creating a new object if there would be no effective change if ((props.label === undefined || props.label === this.label) && (props.color === undefined || props.color === this.color) && (props.period === undefined || props.period.toSeconds() === this.period.toSeconds()) && (props.searchAccount === undefined || props.searchAccount === this.searchAccount) && (props.searchRegion === undefined || props.searchRegion === this.searchRegion)) { return this; } return new MathExpression({ expression: this.expression, usingMetrics: this.usingMetrics, label: ifUndefined(props.label, this.label), color: ifUndefined(props.color, this.color), period: ifUndefined(props.period, this.period), searchAccount: ifUndefined(props.searchAccount, this.searchAccount), searchRegion: ifUndefined(props.searchRegion, this.searchRegion), }); } /** * @deprecated use toMetricConfig() */ toAlarmConfig() { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.MathExpression#toAlarmConfig", "use toMetricConfig()"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.toAlarmConfig); } throw error; } throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead'); } /** * @deprecated use toMetricConfig() */ toGraphConfig() { try { jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.MathExpression#toGraphConfig", "use toMetricConfig()"); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.toGraphConfig); } throw error; } throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead'); } toMetricConfig() { return { mathExpression: { period: this.period.toSeconds(), expression: this.expression, usingMetrics: this.usingMetrics, searchAccount: this.searchAccount, searchRegion: this.searchRegion, }, renderingProperties: { label: this.label, color: this.color, }, }; } /** * Make a new Alarm for this metric * * Combines both properties that may adjust the metric (aggregation) as well * as alarm properties. */ createAlarm(scope, id, props) { try { jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_CreateAlarmOptions(props); } catch (error) { if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") { Error.captureStackTrace(error, this.createAlarm); } throw error; } return new alarm_1.Alarm(scope, id, { metric: this.with({ period: props.period, }), alarmName: props.alarmName, alarmDescription: props.alarmDescription, comparisonOperator: props.comparisonOperator, datapointsToAlarm: props.datapointsToAlarm, threshold: props.threshold, evaluationPeriods: props.evaluationPeriods, evaluateLowSampleCountPercentile: props.evaluateLowSampleCountPercentile, treatMissingData: props.treatMissingData, actionsEnabled: props.actionsEnabled, }); } toString() { return this.label || this.expression; } validateNoIdConflicts() { const seen = new Map(); visit(this); function visit(metric) { metric_util_1.dispatchMetric(metric, { withStat() { // Nothing }, withExpression(expr) { for (const [id, subMetric] of Object.entries(expr.usingMetrics)) { const existing = seen.get(id); if (existing && metric_util_1.metricKey(existing) !== metric_util_1.metricKey(subMetric)) { throw new Error(`The ID '${id}' used for two metrics in the expression: '${subMetric}' and '${existing}'. Rename one.`); } seen.set(id, subMetric); visit(subMetric); } }, }); } } } exports.MathExpression = MathExpression; _b = JSII_RTTI_SYMBOL_1; MathExpression[_b] = { fqn: "@aws-cdk/aws-cloudwatch.MathExpression", version: "1.157.0" }; /** * Pattern for a variable name. Alphanum starting with lowercase. */ const VARIABLE_PAT = '[a-z][a-zA-Z0-9_]*'; const VALID_VARIABLE = new RegExp(`^${VARIABLE_PAT}$`); const FIND_VARIABLE = new RegExp(VARIABLE_PAT, 'g'); function validVariableName(x) { return VALID_VARIABLE.test(x); } /** * Return all variable names used in an expression */ function allIdentifiersInExpression(x) { return Array.from(matchAll(x, FIND_VARIABLE)).map(m => m[0]); } function ifUndefined(x, def) { if (x !== undefined) { return x; } return def; } /** * Change periods of all metrics in the map */ function changeAllPeriods(metrics, period) { const ret = {}; for (const [id, metric] of Object.entries(metrics)) { ret[id] = changePeriod(metric, period); } return ret; } /** * Return a new metric object which is the same type as the input object, but with the period changed * * Relies on the fact that implementations of `IMetric` are also supposed to have * an implementation of `with` that accepts an argument called `period`. See `IModifiableMetric`. */ function changePeriod(metric, period) { if (isModifiableMetric(metric)) { return metric.with({ period }); } throw new Error(`Metric object should also implement 'with': ${metric}`); } function isModifiableMetric(m) { return typeof m === 'object' && m !== null && !!m.with; } // Polyfill for string.matchAll(regexp) function matchAll(x, re) { const ret = new Array(); let m; while (m = re.exec(x)) { ret.push(m); } return ret; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWV0cmljLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdDQUF3QztBQUN4QyxxQ0FBcUM7QUFFckMsbUNBQXNFO0FBRXRFLHVEQUFrRTtBQUNsRSxtREFBeUU7QUErTnpFOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFhLE1BQU07SUF5Q2pCLFlBQVksS0FBa0I7Ozs7Ozs7Ozs7O1FBQzVCLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU0sSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN0RCxNQUFNLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQzFDLElBQUksU0FBUyxLQUFLLENBQUMsSUFBSSxTQUFTLEtBQUssQ0FBQyxJQUFJLFNBQVMsS0FBSyxFQUFFLElBQUksU0FBUyxLQUFLLEVBQUUsSUFBSSxTQUFTLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRTtZQUN0RyxNQUFNLElBQUksS0FBSyxDQUFDLHdFQUF3RSxTQUFTLEVBQUUsQ0FBQyxDQUFDO1NBQ3RHO1FBQ0QsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsa0JBQWtCLE9BQUMsS0FBSyxDQUFDLGFBQWEsbUNBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1FBQ25GLElBQUksQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQztRQUNqQyxJQUFJLENBQUMsVUFBVSxHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUM7UUFDbkMsd0RBQXdEO1FBQ3hELElBQUksQ0FBQyxTQUFTLEdBQUcsOEJBQWtCLENBQUMsS0FBSyxDQUFDLFNBQVMsSUFBSSxTQUFTLENBQUMsQ0FBQztRQUNsRSxJQUFJLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQyxLQUFLLENBQUM7UUFDekIsSUFBSSxDQUFDLEtBQUssR0FB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b3J0ICogYXMgY2RrIGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuaW1wb3J0ICogYXMgY29uc3RydWN0cyBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEFsYXJtLCBDb21wYXJpc29uT3BlcmF0b3IsIFRyZWF0TWlzc2luZ0RhdGEgfSBmcm9tICcuL2FsYXJtJztcbmltcG9ydCB7IERpbWVuc2lvbiwgSU1ldHJpYywgTWV0cmljQWxhcm1Db25maWcsIE1ldHJpY0NvbmZpZywgTWV0cmljR3JhcGhDb25maWcsIFVuaXQgfSBmcm9tICcuL21ldHJpYy10eXBlcyc7XG5pbXBvcnQgeyBkaXNwYXRjaE1ldHJpYywgbWV0cmljS2V5IH0gZnJvbSAnLi9wcml2YXRlL21ldHJpYy11dGlsJztcbmltcG9ydCB7IG5vcm1hbGl6ZVN0YXRpc3RpYywgcGFyc2VTdGF0aXN0aWMgfSBmcm9tICcuL3ByaXZhdGUvc3RhdGlzdGljJztcblxuLy8ga2VlcCB0aGlzIGltcG9ydCBzZXBhcmF0ZSBmcm9tIG90aGVyIGltcG9ydHMgdG8gcmVkdWNlIGNoYW5jZSBmb3IgbWVyZ2UgY29uZmxpY3RzIHdpdGggdjItbWFpblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWR1cGxpY2F0ZS1pbXBvcnRzLCBpbXBvcnQvb3JkZXJcbmltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ0Bhd3MtY2RrL2NvcmUnO1xuXG5leHBvcnQgdHlwZSBEaW1lbnNpb25IYXNoID0ge1tkaW06IHN0cmluZ106IGFueX07XG5cbmV4cG9ydCB0eXBlIERpbWVuc2lvbnNNYXAgPSB7IFtkaW06IHN0cmluZ106IHN0cmluZyB9O1xuXG4vKipcbiAqIE9wdGlvbnMgc2hhcmVkIGJ5IG1vc3QgbWV0aG9kcyBhY2NlcHRpbmcgbWV0cmljIG9wdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDb21tb25NZXRyaWNPcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBwZXJpb2Qgb3ZlciB3aGljaCB0aGUgc3BlY2lmaWVkIHN0YXRpc3RpYyBpcyBhcHBsaWVkLlxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDUpXG4gICAqL1xuICByZWFkb25seSBwZXJpb2Q/OiBjZGsuRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIFdoYXQgZnVuY3Rpb24gdG8gdXNlIGZvciBhZ2dyZWdhdGluZy5cbiAgICpcbiAgICogQ2FuIGJlIG9uZSBvZiB0aGUgZm9sbG93aW5nOlxuICAgKlxuICAgKiAtIFwiTWluaW11bVwiIHwgXCJtaW5cIlxuICAgKiAtIFwiTWF4aW11bVwiIHwgXCJtYXhcIlxuICAgKiAtIFwiQXZlcmFnZVwiIHwgXCJhdmdcIlxuICAgKiAtIFwiU3VtXCIgfCBcInN1bVwiXG4gICAqIC0gXCJTYW1wbGVDb3VudCB8IFwiblwiXG4gICAqIC0gXCJwTk4uTk5cIlxuICAgKlxuICAgKiBAZGVmYXVsdCBBdmVyYWdlXG4gICAqL1xuICByZWFkb25seSBzdGF0aXN0aWM/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIERpbWVuc2lvbnMgb2YgdGhlIG1ldHJpY1xuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGRpbWVuc2lvbnMuXG4gICAqXG4gICAqIEBkZXByZWNhdGVkIFVzZSAnZGltZW5zaW9uc01hcCcgaW5zdGVhZC5cbiAgICovXG4gIHJlYWRvbmx5IGRpbWVuc2lvbnM/OiBEaW1lbnNpb25IYXNoO1xuXG4gIC8qKlxuICAgKiBEaW1lbnNpb25zIG9mIHRoZSBtZXRyaWNcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBkaW1lbnNpb25zLlxuICAgKi9cbiAgcmVhZG9ubHkgZGltZW5zaW9uc01hcD86IERpbWVuc2lvbnNNYXA7XG5cbiAgLyoqXG4gICAqIFVuaXQgdXNlZCB0byBmaWx0ZXIgdGhlIG1ldHJpYyBzdHJlYW1cbiAgICpcbiAgICogT25seSByZWZlciB0byBkYXR1bXMgZW1pdHRlZCB0byB0aGUgbWV0cmljIHN0cmVhbSB3aXRoIHRoZSBnaXZlbiB1bml0IGFuZFxuICAgKiBpZ25vcmUgYWxsIG90aGVycy4gT25seSB1c2VmdWwgd2hlbiBkYXR1bXMgYXJlIGJlaW5nIGVtaXR0ZWQgdG8gdGhlIHNhbWVcbiAgICogbWV0cmljIHN0cmVhbSB1bmRlciBkaWZmZXJlbnQgdW5pdHMuXG4gICAqXG4gICAqIFRoZSBkZWZhdWx0IGlzIHRvIHVzZSBhbGwgbWF0cmljIGRhdHVtcyBpbiB0aGUgc3RyZWFtLCByZWdhcmRsZXNzIG9mIHVuaXQsXG4gICAqIHdoaWNoIGlzIHJlY29tbWVuZGVkIGluIG5lYXJseSBhbGwgY2FzZXMuXG4gICAqXG4gICAqIENsb3VkV2F0Y2ggZG9lcyBub3QgaG9ub3IgdGhpcyBwcm9wZXJ0eSBmb3IgZ3JhcGhzLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEFsbCBtZXRyaWMgZGF0dW1zIGluIHRoZSBnaXZlbiBtZXRyaWMgc3RyZWFtXG4gICAqL1xuICByZWFkb25seSB1bml0PzogVW5pdDtcblxuICAvKipcbiAgICogTGFiZWwgZm9yIHRoaXMgbWV0cmljIHdoZW4gYWRkZWQgdG8gYSBHcmFwaCBpbiBhIERhc2hib2FyZFxuICAgKlxuICAgKiBZb3UgY2FuIHVzZSBbZHluYW1pYyBsYWJlbHNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9tb25pdG9yaW5nL2dyYXBoLWR5bmFtaWMtbGFiZWxzLmh0bWwpXG4gICAqIHRvIHNob3cgc3VtbWFyeSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZW50aXJlIGRpc3BsYXllZCB0aW1lIHNlcmllc1xuICAgKiBpbiB0aGUgbGVnZW5kLiBGb3IgZXhhbXBsZSwgaWYgeW91IHVzZTpcbiAgICpcbiAgICogYGBgXG4gICAqIFttYXg6ICR7TUFYfV0gTXlNZXRyaWNcbiAgICogYGBgXG4gICAqXG4gICAqIEFzIHRoZSBtZXRyaWMgbGFiZWwsIHRoZSBtYXhpbXVtIHZhbHVlIGluIHRoZSB2aXNpYmxlIHJhbmdlIHdpbGxcbiAgICogYmUgc2hvd24gbmV4dCB0byB0aGUgdGltZSBzZXJpZXMgbmFtZSBpbiB0aGUgZ3JhcGgncyBsZWdlbmQuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gbGFiZWxcbiAgICovXG4gIHJlYWRvbmx5IGxhYmVsPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgaGV4IGNvbG9yIGNvZGUsIHByZWZpeGVkIHdpdGggJyMnIChlLmcuICcjMDBmZjAwJyksIHRvIHVzZSB3aGVuIHRoaXMgbWV0cmljIGlzIHJlbmRlcmVkIG9uIGEgZ3JhcGguXG4gICAqIFRoZSBgQ29sb3JgIGNsYXNzIGhhcyBhIHNldCBvZiBzdGFuZGFyZCBjb2xvcnMgdGhhdCBjYW4gYmUgdXNlZCBoZXJlLlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpYyBjb2xvclxuICAgKi9cbiAgcmVhZG9ubHkgY29sb3I/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIEFjY291bnQgd2hpY2ggdGhpcyBtZXRyaWMgY29tZXMgZnJvbS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEZXBsb3ltZW50IGFjY291bnQuXG4gICAqL1xuICByZWFkb25seSBhY2NvdW50Pzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBSZWdpb24gd2hpY2ggdGhpcyBtZXRyaWMgY29tZXMgZnJvbS5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBEZXBsb3ltZW50IHJlZ2lvbi5cbiAgICovXG4gIHJlYWRvbmx5IHJlZ2lvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIG1ldHJpY1xuICovXG5leHBvcnQgaW50ZXJmYWNlIE1ldHJpY1Byb3BzIGV4dGVuZHMgQ29tbW9uTWV0cmljT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBOYW1lc3BhY2Ugb2YgdGhlIG1ldHJpYy5cbiAgICovXG4gIHJlYWRvbmx5IG5hbWVzcGFjZTogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBOYW1lIG9mIHRoZSBtZXRyaWMuXG4gICAqL1xuICByZWFkb25seSBtZXRyaWNOYW1lOiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBvZiBhIG1ldHJpYyB0aGF0IGNhbiBiZSBjaGFuZ2VkXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0cmljT3B0aW9ucyBleHRlbmRzIENvbW1vbk1ldHJpY09wdGlvbnMge1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYWJsZSBvcHRpb25zIGZvciBNYXRoRXhwcmVzc2lvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNYXRoRXhwcmVzc2lvbk9wdGlvbnMge1xuICAvKipcbiAgICogTGFiZWwgZm9yIHRoaXMgZXhwcmVzc2lvbiB3aGVuIGFkZGVkIHRvIGEgR3JhcGggaW4gYSBEYXNoYm9hcmRcbiAgICpcbiAgICogSWYgdGhpcyBleHByZXNzaW9uIGV2YWx1YXRlcyB0byBtb3JlIHRoYW4gb25lIHRpbWUgc2VyaWVzIChmb3JcbiAgICogZXhhbXBsZSwgdGhyb3VnaCB0aGUgdXNlIG9mIGBNRVRSSUNTKClgIG9yIGBTRUFSQ0goKWAgZXhwcmVzc2lvbnMpLFxuICAgKiBlYWNoIHRpbWUgc2VyaWVzIHdpbGwgYXBwZWFyIGluIHRoZSBncmFwaCB1c2luZyBhIGNvbWJpbmF0aW9uIG9mIHRoZVxuICAgKiBleHByZXNzaW9uIGxhYmVsIGFuZCB0aGUgaW5kaXZpZHVhbCBtZXRyaWMgbGFiZWwuIFNwZWNpZnkgdGhlIGVtcHR5XG4gICAqIHN0cmluZyAoYCcnYCkgdG8gc3VwcHJlc3MgdGhlIGV4cHJlc3Npb24gbGFiZWwgYW5kIG9ubHkga2VlcCB0aGVcbiAgICogbWV0cmljIGxhYmVsLlxuICAgKlxuICAgKiBZb3UgY2FuIHVzZSBbZHluYW1pYyBsYWJlbHNdKGh0dHBzOi8vZG9jcy5hd3MuYW1hem9uLmNvbS9BbWF6b25DbG91ZFdhdGNoL2xhdGVzdC9tb25pdG9yaW5nL2dyYXBoLWR5bmFtaWMtbGFiZWxzLmh0bWwpXG4gICAqIHRvIHNob3cgc3VtbWFyeSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgZGlzcGxheWVkIHRpbWUgc2VyaWVzXG4gICAqIGluIHRoZSBsZWdlbmQuIEZvciBleGFtcGxlLCBpZiB5b3UgdXNlOlxuICAgKlxuICAgKiBgYGBcbiAgICogW21heDogJHtNQVh9XSBNeU1ldHJpY1xuICAgKiBgYGBcbiAgICpcbiAgICogQXMgdGhlIG1ldHJpYyBsYWJlbCwgdGhlIG1heGltdW0gdmFsdWUgaW4gdGhlIHZpc2libGUgcmFuZ2Ugd2lsbFxuICAgKiBiZSBzaG93biBuZXh0IHRvIHRoZSB0aW1lIHNlcmllcyBuYW1lIGluIHRoZSBncmFwaCdzIGxlZ2VuZC4gSWYgdGhlXG4gICAqIG1hdGggZXhwcmVzc2lvbiBwcm9kdWNlcyBtb3JlIHRoYW4gb25lIHRpbWUgc2VyaWVzLCB0aGUgbWF4aW11bVxuICAgKiB3aWxsIGJlIHNob3duIGZvciBlYWNoIGluZGl2aWR1YWwgdGltZSBzZXJpZXMgcHJvZHVjZSBieSB0aGlzXG4gICAqIG1hdGggZXhwcmVzc2lvbi5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBFeHByZXNzaW9uIHZhbHVlIGlzIHVzZWQgYXMgbGFiZWxcbiAgICovXG4gIHJlYWRvbmx5IGxhYmVsPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBDb2xvciBmb3IgdGhpcyBtZXRyaWMgd2hlbiBhZGRlZCB0byBhIEdyYXBoIGluIGEgRGFzaGJvYXJkXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gQXV0b21hdGljIGNvbG9yXG4gICAqL1xuICByZWFkb25seSBjb2xvcj86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIHBlcmlvZCBvdmVyIHdoaWNoIHRoZSBleHByZXNzaW9uJ3Mgc3RhdGlzdGljcyBhcmUgYXBwbGllZC5cbiAgICpcbiAgICogVGhpcyBwZXJpb2Qgb3ZlcnJpZGVzIGFsbCBwZXJpb2RzIGluIHRoZSBtZXRyaWNzIHVzZWQgaW4gdGhpc1xuICAgKiBtYXRoIGV4cHJlc3Npb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IER1cmF0aW9uLm1pbnV0ZXMoNSlcbiAgICovXG4gIHJlYWRvbmx5IHBlcmlvZD86IGNkay5EdXJhdGlvbjtcblxuICAvKipcbiAgICogQWNjb3VudCB0byBldmFsdWF0ZSBzZWFyY2ggZXhwcmVzc2lvbnMgd2l0aGluLlxuICAgKlxuICAgKiBTcGVjaWZ5aW5nIGEgc2VhcmNoQWNjb3VudCBoYXMgbm8gZWZmZWN0IHRvIHRoZSBhY2NvdW50IHVzZWRcbiAgICogZm9yIG1ldHJpY3Mgd2l0aGluIHRoZSBleHByZXNzaW9uIChwYXNzZWQgdmlhIHVzaW5nTWV0cmljcykuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVwbG95bWVudCBhY2NvdW50LlxuICAgKi9cbiAgcmVhZG9ubHkgc2VhcmNoQWNjb3VudD86IHN0cmluZztcblxuICAvKipcbiAgICAqIFJlZ2lvbiB0byBldmFsdWF0ZSBzZWFyY2ggZXhwcmVzc2lvbnMgd2l0aGluLlxuICAgICpcbiAgICAqIFNwZWNpZnlpbmcgYSBzZWFyY2hSZWdpb24gaGFzIG5vIGVmZmVjdCB0byB0aGUgcmVnaW9uIHVzZWRcbiAgICAqIGZvciBtZXRyaWNzIHdpdGhpbiB0aGUgZXhwcmVzc2lvbiAocGFzc2VkIHZpYSB1c2luZ01ldHJpY3MpLlxuICAgICpcbiAgICAqIEBkZWZhdWx0IC0gRGVwbG95bWVudCByZWdpb24uXG4gICAgKi9cbiAgcmVhZG9ubHkgc2VhcmNoUmVnaW9uPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgZm9yIGEgTWF0aEV4cHJlc3Npb25cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNYXRoRXhwcmVzc2lvblByb3BzIGV4dGVuZHMgTWF0aEV4cHJlc3Npb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIFRoZSBleHByZXNzaW9uIGRlZmluaW5nIHRoZSBtZXRyaWMuXG4gICAqXG4gICAqIFdoZW4gYW4gZXhwcmVzc2lvbiBjb250YWlucyBhIFNFQVJDSCBmdW5jdGlvbiwgaXQgY2Fubm90IGJlIHVzZWRcbiAgICogd2l0aGluIGFuIEFsYXJtLlxuICAgKi9cbiAgcmVhZG9ubHkgZXhwcmVzc2lvbjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBUaGUgbWV0cmljcyB1c2VkIGluIHRoZSBleHByZXNzaW9uLCBpbiBhIG1hcC5cbiAgICpcbiAgICogVGhlIGtleSBpcyB0aGUgaWRlbnRpZmllciB0aGF0IHJlcHJlc2VudHMgdGhlIGdpdmVuIG1ldHJpYyBpbiB0aGVcbiAgICogZXhwcmVzc2lvbiwgYW5kIHRoZSB2YWx1ZSBpcyB0aGUgYWN0dWFsIE1ldHJpYyBvYmplY3QuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRW1wdHkgbWFwLlxuICAgKi9cbiAgcmVhZG9ubHkgdXNpbmdNZXRyaWNzPzogUmVjb3JkPHN0cmluZywgSU1ldHJpYz47XG59XG5cbi8qKlxuICogQSBtZXRyaWMgZW1pdHRlZCBieSBhIHNlcnZpY2VcbiAqXG4gKiBUaGUgbWV0cmljIGlzIGEgY29tYmluYXRpb24gb2YgYSBtZXRyaWMgaWRlbnRpZmllciAobmFtZXNwYWNlLCBuYW1lIGFuZCBkaW1lbnNpb25zKVxuICogYW5kIGFuIGFnZ3JlZ2F0aW9uIGZ1bmN0aW9uIChzdGF0aXN0aWMsIHBlcmlvZCBhbmQgdW5pdCkuXG4gKlxuICogSXQgYWxzbyBjb250YWlucyBtZXRhZGF0YSB3aGljaCBpcyB1c2VkIG9ubHkgaW4gZ3JhcGhzLCBzdWNoIGFzIGNvbG9yIGFuZCBsYWJlbC5cbiAqIEl0IG1ha2VzIHNlbnNlIHRvIGVtYmVkIHRoaXMgaW4gaGVyZSwgc28gdGhhdCBjb21wb3VuZCBjb25zdHJ1Y3RzIGNhbiBhdHRhY2hcbiAqIHRoYXQgbWV0YWRhdGEgdG8gbWV0cmljcyB0aGV5IGV4cG9zZS5cbiAqXG4gKiBUaGlzIGNsYXNzIGRvZXMgbm90IHJlcHJlc2VudCBhIHJlc291cmNlLCBzbyBoZW5jZSBpcyBub3QgYSBjb25zdHJ1Y3QuIEluc3RlYWQsXG4gKiBNZXRyaWMgaXMgYW4gYWJzdHJhY3Rpb24gdGhhdCBtYWtlcyBpdCBlYXN5IHRvIHNwZWNpZnkgbWV0cmljcyBmb3IgdXNlIGluIGJvdGhcbiAqIGFsYXJtcyBhbmQgZ3JhcGhzLlxuICovXG5leHBvcnQgY2xhc3MgTWV0cmljIGltcGxlbWVudHMgSU1ldHJpYyB7XG4gIC8qKlxuICAgKiBHcmFudCBwZXJtaXNzaW9ucyB0byB0aGUgZ2l2ZW4gaWRlbnRpdHkgdG8gd3JpdGUgbWV0cmljcy5cbiAgICpcbiAgICogQHBhcmFtIGdyYW50ZWUgVGhlIElBTSBpZGVudGl0eSB0byBnaXZlIHBlcm1pc3Npb25zIHRvLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBncmFudFB1dE1ldHJpY0RhdGEoZ3JhbnRlZTogaWFtLklHcmFudGFibGUpOiBpYW0uR3JhbnQge1xuICAgIHJldHVybiBpYW0uR3JhbnQuYWRkVG9QcmluY2lwYWwoe1xuICAgICAgZ3JhbnRlZSxcbiAgICAgIGFjdGlvbnM6IFsnY2xvdWR3YXRjaDpQdXRNZXRyaWNEYXRhJ10sXG4gICAgICByZXNvdXJjZUFybnM6IFsnKiddLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqIERpbWVuc2lvbnMgb2YgdGhpcyBtZXRyaWMgKi9cbiAgcHVibGljIHJlYWRvbmx5IGRpbWVuc2lvbnM/OiBEaW1lbnNpb25IYXNoO1xuICAvKiogTmFtZXNwYWNlIG9mIHRoaXMgbWV0cmljICovXG4gIHB1YmxpYyByZWFkb25seSBuYW1lc3BhY2U6IHN0cmluZztcbiAgLyoqIE5hbWUgb2YgdGhpcyBtZXRyaWMgKi9cbiAgcHVibGljIHJlYWRvbmx5IG1ldHJpY05hbWU6IHN0cmluZztcbiAgLyoqIFBlcmlvZCBvZiB0aGlzIG1ldHJpYyAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcGVyaW9kOiBjZGsuRHVyYXRpb247XG4gIC8qKiBTdGF0aXN0aWMgb2YgdGhpcyBtZXRyaWMgKi9cbiAgcHVibGljIHJlYWRvbmx5IHN0YXRpc3RpYzogc3RyaW5nO1xuICAvKiogTGFiZWwgZm9yIHRoaXMgbWV0cmljIHdoZW4gYWRkZWQgdG8gYSBHcmFwaCBpbiBhIERhc2hib2FyZCAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbGFiZWw/OiBzdHJpbmc7XG4gIC8qKiBUaGUgaGV4IGNvbG9yIGNvZGUgdXNlZCB3aGVuIHRoaXMgbWV0cmljIGl