@aws-cdk/aws-cloudwatch
Version:
The CDK Construct Library for AWS::CloudWatch
546 lines • 78.6 kB
JavaScript
"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