cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
250 lines • 33 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.LatencyAlarmFactory = exports.getLatencyTypeLabel = exports.getLatencyTypeExpressionId = exports.getLatencyTypeStatistic = exports.LatencyType = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const metric_1 = require("../../metric");
var LatencyType;
(function (LatencyType) {
LatencyType["P50"] = "P50";
LatencyType["P70"] = "P70";
LatencyType["P90"] = "P90";
LatencyType["P95"] = "P95";
LatencyType["P99"] = "P99";
LatencyType["P999"] = "P999";
LatencyType["P9999"] = "P9999";
LatencyType["P100"] = "P100";
LatencyType["TM50"] = "TM50";
LatencyType["TM70"] = "TM70";
LatencyType["TM90"] = "TM90";
LatencyType["TM95"] = "TM95";
LatencyType["TM99"] = "TM99";
LatencyType["TM999"] = "TM999";
LatencyType["TM9999"] = "TM9999";
LatencyType["TM95_TOP"] = "TM(95%:100%)";
LatencyType["TM99_TOP"] = "TM(99%:100%)";
LatencyType["TM999_TOP"] = "TM(99.9%:100%)";
LatencyType["TM9999_TOP"] = "TM(99.99%:100%)";
LatencyType["AVERAGE"] = "Average";
LatencyType["MAX"] = "Maximum";
})(LatencyType = exports.LatencyType || (exports.LatencyType = {}));
function getLatencyTypeStatistic(latencyType) {
switch (latencyType) {
case LatencyType.P50:
return metric_1.MetricStatistic.P50;
case LatencyType.P70:
return metric_1.MetricStatistic.P70;
case LatencyType.P90:
return metric_1.MetricStatistic.P90;
case LatencyType.P95:
return metric_1.MetricStatistic.P95;
case LatencyType.P99:
return metric_1.MetricStatistic.P99;
case LatencyType.P999:
return metric_1.MetricStatistic.P999;
case LatencyType.P9999:
return metric_1.MetricStatistic.P9999;
case LatencyType.P100:
return metric_1.MetricStatistic.P100;
case LatencyType.TM50:
return metric_1.MetricStatistic.TM50;
case LatencyType.TM70:
return metric_1.MetricStatistic.TM70;
case LatencyType.TM90:
return metric_1.MetricStatistic.TM90;
case LatencyType.TM95:
return metric_1.MetricStatistic.TM95;
case LatencyType.TM99:
return metric_1.MetricStatistic.TM99;
case LatencyType.TM999:
return metric_1.MetricStatistic.TM999;
case LatencyType.TM9999:
return metric_1.MetricStatistic.TM9999;
case LatencyType.TM95_TOP:
return metric_1.MetricStatistic.TM95_TOP;
case LatencyType.TM99_TOP:
return metric_1.MetricStatistic.TM99_TOP;
case LatencyType.TM999_TOP:
return metric_1.MetricStatistic.TM999_TOP;
case LatencyType.TM9999_TOP:
return metric_1.MetricStatistic.TM9999_TOP;
case LatencyType.AVERAGE:
return metric_1.MetricStatistic.AVERAGE;
case LatencyType.MAX:
return metric_1.MetricStatistic.MAX;
default:
throw new Error("Unsupported latency type (unknown statistic): " + latencyType);
}
}
exports.getLatencyTypeStatistic = getLatencyTypeStatistic;
function getLatencyTypeExpressionId(latencyType) {
switch (latencyType) {
case LatencyType.P50:
case LatencyType.P70:
case LatencyType.P90:
case LatencyType.P95:
case LatencyType.P99:
case LatencyType.P999:
case LatencyType.P9999:
case LatencyType.P100:
// remove the P prefix
return latencyType.substring(1);
case LatencyType.AVERAGE:
// making it shorter for backwards compatibility
return "Avg";
case LatencyType.MAX:
return "Max";
default:
// use as-is
return latencyType;
}
}
exports.getLatencyTypeExpressionId = getLatencyTypeExpressionId;
function getLatencyTypeLabel(latencyType) {
const averageSuffix = " (avg: ${AVG})";
switch (latencyType) {
case LatencyType.P999:
case LatencyType.TM999:
// we need proper decimal here
return latencyType.replace("999", "99.9") + averageSuffix;
case LatencyType.P9999:
case LatencyType.TM9999:
case LatencyType.TM95_TOP:
case LatencyType.TM99_TOP:
case LatencyType.TM999_TOP:
case LatencyType.TM9999_TOP:
// we need proper decimal here
return latencyType.replace("9999", "99.99") + averageSuffix;
case LatencyType.AVERAGE:
// no suffix here, since we already have average
return "Average";
case LatencyType.MAX:
return "Maximum";
default:
// use as-is
return latencyType + averageSuffix;
}
}
exports.getLatencyTypeLabel = getLatencyTypeLabel;
class LatencyAlarmFactory {
constructor(alarmFactory) {
this.alarmFactory = alarmFactory;
}
addLatencyAlarm(metric, latencyType, props, disambiguator, additionalAlarmNameSuffix = undefined) {
const alarmNameSuffix = ["Latency", latencyType, additionalAlarmNameSuffix]
.filter((i) => i !== undefined)
.join("-");
return this.alarmFactory.addAlarm(metric, {
treatMissingData: props.treatMissingDataOverride ?? aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
comparisonOperator: props.comparisonOperatorOverride ??
aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxLatency.toMilliseconds({ integral: false }),
alarmNameSuffix,
// we will dedupe any kind of latency issue to the same ticket
alarmDedupeStringSuffix: this.alarmFactory
.shouldUseDefaultDedupeForLatency
? "AnyLatency"
: alarmNameSuffix,
alarmDescription: `${latencyType} latency is too high.`,
});
}
addIntegrationLatencyAlarm(metric, latencyType, props, disambiguator, additionalAlarmNameSuffix = undefined) {
const alarmNameSuffix = [
"IntegrationLatency",
latencyType,
additionalAlarmNameSuffix,
]
.filter((i) => i !== undefined)
.join("-");
return this.alarmFactory.addAlarm(metric, {
treatMissingData: props.treatMissingDataOverride ?? aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
comparisonOperator: props.comparisonOperatorOverride ??
aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxLatency.toMilliseconds({ integral: false }),
alarmNameSuffix,
// we will dedupe any kind of latency issue to the same alarm
alarmDedupeStringSuffix: this.alarmFactory
.shouldUseDefaultDedupeForLatency
? "AnyLatency"
: alarmNameSuffix,
alarmDescription: `${latencyType} integration latency is too high.`,
});
}
addDurationAlarm(metric, latencyType, props, disambiguator, additionalAlarmNameSuffix = undefined) {
const alarmNameSuffix = ["Duration", latencyType, additionalAlarmNameSuffix]
.filter((i) => i !== undefined)
.join("-");
return this.alarmFactory.addAlarm(metric, {
treatMissingData: props.treatMissingDataOverride ?? aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
comparisonOperator: props.comparisonOperatorOverride ??
aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxDuration.toMilliseconds({ integral: false }),
alarmNameSuffix,
// we will dedupe any kind of latency issue to the same ticket
alarmDedupeStringSuffix: this.alarmFactory
.shouldUseDefaultDedupeForLatency
? "AnyDuration"
: alarmNameSuffix,
alarmDescription: `${latencyType} duration is too long.`,
});
}
addCustomDurationAlarm(metric, latencyType, props, durationName, disambiguator, additionalAlarmNameSuffix = undefined) {
const alarmNameSuffix = [
durationName,
latencyType,
additionalAlarmNameSuffix,
]
.filter((i) => i !== undefined)
.join("-");
return this.alarmFactory.addAlarm(metric, {
treatMissingData: props.treatMissingDataOverride ?? aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
comparisonOperator: props.comparisonOperatorOverride ??
aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxDuration.toMilliseconds({ integral: false }),
alarmNameSuffix,
// we will dedupe any kind of latency issue to the same ticket
alarmDedupeStringSuffix: this.alarmFactory
.shouldUseDefaultDedupeForLatency
? `Any${durationName}`
: alarmNameSuffix,
alarmDescription: `${latencyType} ${durationName} is too long.`,
});
}
addJvmGarbageCollectionDurationAlarm(metric, latencyType, props, disambiguator, additionalAlarmNameSuffix = undefined) {
const alarmNameSuffix = [
"Garbage-Collection-Time",
latencyType,
additionalAlarmNameSuffix,
]
.filter((i) => i !== undefined)
.join("-");
return this.alarmFactory.addAlarm(metric, {
treatMissingData: props.treatMissingDataOverride ?? aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
comparisonOperator: props.comparisonOperatorOverride ??
aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
...props,
disambiguator,
threshold: props.maxDuration.toMilliseconds({ integral: false }),
alarmNameSuffix,
// we will dedupe any kind of latency issue to the same ticket
alarmDedupeStringSuffix: this.alarmFactory
.shouldUseDefaultDedupeForLatency
? "AnyDuration"
: alarmNameSuffix,
alarmDescription: `${latencyType} duration is too long.`,
});
}
}
exports.LatencyAlarmFactory = LatencyAlarmFactory;
_a = JSII_RTTI_SYMBOL_1;
LatencyAlarmFactory[_a] = { fqn: "cdk-monitoring-constructs.LatencyAlarmFactory", version: "9.15.2" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiTGF0ZW5jeUFsYXJtRmFjdG9yeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIkxhdGVuY3lBbGFybUZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7QUFDQSwrREFHb0M7QUFHcEMseUNBQXVFO0FBRXZFLElBQVksV0FzQlg7QUF0QkQsV0FBWSxXQUFXO0lBQ3JCLDBCQUFXLENBQUE7SUFDWCwwQkFBVyxDQUFBO0lBQ1gsMEJBQVcsQ0FBQTtJQUNYLDBCQUFXLENBQUE7SUFDWCwwQkFBVyxDQUFBO0lBQ1gsNEJBQWEsQ0FBQTtJQUNiLDhCQUFlLENBQUE7SUFDZiw0QkFBYSxDQUFBO0lBQ2IsNEJBQWEsQ0FBQTtJQUNiLDRCQUFhLENBQUE7SUFDYiw0QkFBYSxDQUFBO0lBQ2IsNEJBQWEsQ0FBQTtJQUNiLDRCQUFhLENBQUE7SUFDYiw4QkFBZSxDQUFBO0lBQ2YsZ0NBQWlCLENBQUE7SUFDakIsd0NBQXlCLENBQUE7SUFDekIsd0NBQXlCLENBQUE7SUFDekIsMkNBQTRCLENBQUE7SUFDNUIsNkNBQThCLENBQUE7SUFDOUIsa0NBQW1CLENBQUE7SUFDbkIsOEJBQWUsQ0FBQTtBQUNqQixDQUFDLEVBdEJXLFdBQVcsR0FBWCxtQkFBVyxLQUFYLG1CQUFXLFFBc0J0QjtBQUVELFNBQWdCLHVCQUF1QixDQUFDLFdBQXdCO0lBQzlELFFBQVEsV0FBVyxFQUFFO1FBQ25CLEtBQUssV0FBVyxDQUFDLEdBQUc7WUFDbEIsT0FBTyx3QkFBZSxDQUFDLEdBQUcsQ0FBQztRQUM3QixLQUFLLFdBQVcsQ0FBQyxHQUFHO1lBQ2xCLE9BQU8sd0JBQWUsQ0FBQyxHQUFHLENBQUM7UUFDN0IsS0FBSyxXQUFXLENBQUMsR0FBRztZQUNsQixPQUFPLHdCQUFlLENBQUMsR0FBRyxDQUFDO1FBQzdCLEtBQUssV0FBVyxDQUFDLEdBQUc7WUFDbEIsT0FBTyx3QkFBZSxDQUFDLEdBQUcsQ0FBQztRQUM3QixLQUFLLFdBQVcsQ0FBQyxHQUFHO1lBQ2xCLE9B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QUNoQyxtQ0FBa0IsQ0FBQyxzQkFBc0I7WUFDM0MsR0FBRyxLQUFLO1lBQ1IsYUFBYTtZQUNiLFNBQVMsRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDLGNBQWMsQ0FBQyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztZQUNoRSxlQUFlO1lBQ2YsOERBQThEO1lBQzlELHVCQUF1QixFQUFFLElBQUksQ0FBQyxZQUFZO2lCQUN2QyxnQ0FBZ0M7Z0JBQ2pDLENBQUMsQ0FBQyxhQUFhO2dCQUNmLENBQUMsQ0FBQyxlQUFlO1lBQ25CLGdCQUFnQixFQUFFLEdBQUcsV0FBVyx3QkFBd0I7U0FDekQsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7QUF4S0gsa0RBeUtDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgRHVyYXRpb24gfSBmcm9tIFwiYXdzLWNkay1saWJcIjtcbmltcG9ydCB7XG4gIENvbXBhcmlzb25PcGVyYXRvcixcbiAgVHJlYXRNaXNzaW5nRGF0YSxcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoXCI7XG5cbmltcG9ydCB7IEFsYXJtRmFjdG9yeSwgQ3VzdG9tQWxhcm1UaHJlc2hvbGQgfSBmcm9tIFwiLi4vLi4vYWxhcm1cIjtcbmltcG9ydCB7IE1ldHJpY1N0YXRpc3RpYywgTWV0cmljV2l0aEFsYXJtU3VwcG9ydCB9IGZyb20gXCIuLi8uLi9tZXRyaWNcIjtcblxuZXhwb3J0IGVudW0gTGF0ZW5jeVR5cGUge1xuICBQNTAgPSBcIlA1MFwiLFxuICBQNzAgPSBcIlA3MFwiLFxuICBQOTAgPSBcIlA5MFwiLFxuICBQOTUgPSBcIlA5NVwiLFxuICBQOTkgPSBcIlA5OVwiLFxuICBQOTk5ID0gXCJQOTk5XCIsXG4gIFA5OTk5ID0gXCJQOTk5OVwiLFxuICBQMTAwID0gXCJQMTAwXCIsXG4gIFRNNTAgPSBcIlRNNTBcIixcbiAgVE03MCA9IFwiVE03MFwiLFxuICBUTTkwID0gXCJUTTkwXCIsXG4gIFRNOTUgPSBcIlRNOTVcIixcbiAgVE05OSA9IFwiVE05OVwiLFxuICBUTTk5OSA9IFwiVE05OTlcIixcbiAgVE05OTk5ID0gXCJUTTk5OTlcIixcbiAgVE05NV9UT1AgPSBcIlRNKDk1JToxMDAlKVwiLFxuICBUTTk5X1RPUCA9IFwiVE0oOTklOjEwMCUpXCIsXG4gIFRNOTk5X1RPUCA9IFwiVE0oOTkuOSU6MTAwJSlcIixcbiAgVE05OTk5X1RPUCA9IFwiVE0oOTkuOTklOjEwMCUpXCIsXG4gIEFWRVJBR0UgPSBcIkF2ZXJhZ2VcIixcbiAgTUFYID0gXCJNYXhpbXVtXCIsXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRMYXRlbmN5VHlwZVN0YXRpc3RpYyhsYXRlbmN5VHlwZTogTGF0ZW5jeVR5cGUpIHtcbiAgc3dpdGNoIChsYXRlbmN5VHlwZSkge1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuUDUwOlxuICAgICAgcmV0dXJuIE1ldHJpY1N0YXRpc3RpYy5QNTA7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5QNzA6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLlA3MDtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA5MDpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuUDkwO1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuUDk1OlxuICAgICAgcmV0dXJuIE1ldHJpY1N0YXRpc3RpYy5QOTU7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5QOTk6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLlA5OTtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA5OTk6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLlA5OTk7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5QOTk5OTpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuUDk5OTk7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5QMTAwOlxuICAgICAgcmV0dXJuIE1ldHJpY1N0YXRpc3RpYy5QMTAwO1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuVE01MDpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuVE01MDtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNNzA6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLlRNNzA7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5UTTkwOlxuICAgICAgcmV0dXJuIE1ldHJpY1N0YXRpc3RpYy5UTTkwO1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuVE05NTpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuVE05NTtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNOTk6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLlRNOTk7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5UTTk5OTpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuVE05OTk7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5UTTk5OTk6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLlRNOTk5OTtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNOTVfVE9QOlxuICAgICAgcmV0dXJuIE1ldHJpY1N0YXRpc3RpYy5UTTk1X1RPUDtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNOTlfVE9QOlxuICAgICAgcmV0dXJuIE1ldHJpY1N0YXRpc3RpYy5UTTk5X1RPUDtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNOTk5X1RPUDpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuVE05OTlfVE9QO1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuVE05OTk5X1RPUDpcbiAgICAgIHJldHVybiBNZXRyaWNTdGF0aXN0aWMuVE05OTk5X1RPUDtcbiAgICBjYXNlIExhdGVuY3lUeXBlLkFWRVJBR0U6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLkFWRVJBR0U7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5NQVg6XG4gICAgICByZXR1cm4gTWV0cmljU3RhdGlzdGljLk1BWDtcbiAgICBkZWZhdWx0OlxuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIlVuc3VwcG9ydGVkIGxhdGVuY3kgdHlwZSAodW5rbm93biBzdGF0aXN0aWMpOiBcIiArIGxhdGVuY3lUeXBlLFxuICAgICAgKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TGF0ZW5jeVR5cGVFeHByZXNzaW9uSWQobGF0ZW5jeVR5cGU6IExhdGVuY3lUeXBlKSB7XG4gIHN3aXRjaCAobGF0ZW5jeVR5cGUpIHtcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA1MDpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA3MDpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA5MDpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA5NTpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA5OTpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlA5OTk6XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5QOTk5OTpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlAxMDA6XG4gICAgICAvLyByZW1vdmUgdGhlIFAgcHJlZml4XG4gICAgICByZXR1cm4gbGF0ZW5jeVR5cGUuc3Vic3RyaW5nKDEpO1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuQVZFUkFHRTpcbiAgICAgIC8vIG1ha2luZyBpdCBzaG9ydGVyIGZvciBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eVxuICAgICAgcmV0dXJuIFwiQXZnXCI7XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5NQVg6XG4gICAgICByZXR1cm4gXCJNYXhcIjtcbiAgICBkZWZhdWx0OlxuICAgICAgLy8gdXNlIGFzLWlzXG4gICAgICByZXR1cm4gbGF0ZW5jeVR5cGU7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldExhdGVuY3lUeXBlTGFiZWwobGF0ZW5jeVR5cGU6IExhdGVuY3lUeXBlKSB7XG4gIGNvbnN0IGF2ZXJhZ2VTdWZmaXggPSBcIiAoYXZnOiAke0FWR30pXCI7XG5cbiAgc3dpdGNoIChsYXRlbmN5VHlwZSkge1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuUDk5OTpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNOTk5OlxuICAgICAgLy8gd2UgbmVlZCBwcm9wZXIgZGVjaW1hbCBoZXJlXG4gICAgICByZXR1cm4gbGF0ZW5jeVR5cGUucmVwbGFjZShcIjk5OVwiLCBcIjk5LjlcIikgKyBhdmVyYWdlU3VmZml4O1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuUDk5OTk6XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5UTTk5OTk6XG4gICAgY2FzZSBMYXRlbmN5VHlwZS5UTTk1X1RPUDpcbiAgICBjYXNlIExhdGVuY3lUeXBlLlRNOTlfVE9QOlxuICAgIGNhc2UgTGF0ZW5jeVR5cGUuVE05OTlfVE9QOlxuICAgIGNhc2UgTGF0ZW5jeVR5cGUuVE05OTk5X1RPUDpcbiAgICAgIC8vIHdlIG5lZWQgcHJvcGVyIGRlY2ltYWwgaGVyZVxuICAgICAgcmV0dXJuIGxhdGVuY3lUeXBlLnJlcGxhY2UoXCI5OTk5XCIsIFwiOTkuOTlcIikgKyBhdmVyYWdlU3VmZml4O1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuQVZFUkFHRTpcbiAgICAgIC8vIG5vIHN1ZmZpeCBoZXJlLCBzaW5jZSB3ZSBhbHJlYWR5IGhhdmUgYXZlcmFnZVxuICAgICAgcmV0dXJuIFwiQXZlcmFnZVwiO1xuICAgIGNhc2UgTGF0ZW5jeVR5cGUuTUFYOlxuICAgICAgcmV0dXJuIFwiTWF4aW11bVwiO1xuICAgIGRlZmF1bHQ6XG4gICAgICAvLyB1c2UgYXMtaXNcbiAgICAgIHJldHVybiBsYXRlbmN5VHlwZSArIGF2ZXJhZ2VTdWZmaXg7XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBMYXRlbmN5VGhyZXNob2xkIGV4dGVuZHMgQ3VzdG9tQWxhcm1UaHJlc2hvbGQge1xuICByZWFkb25seSBtYXhMYXRlbmN5OiBEdXJhdGlvbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBMYXRlbmN5VGltZW91dFBlcmNlbnRhZ2VUaHJlc2hvbGRcbiAgZXh0ZW5kcyBDdXN0b21BbGFybVRocmVzaG9sZCB7XG4gIHJlYWRvbmx5IG1heExhdGVuY3lQZXJjZW50YWdlT2ZUaW1lb3V0OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRHVyYXRpb25UaHJlc2hvbGQgZXh0ZW5kcyBDdXN0b21BbGFybVRocmVzaG9sZCB7XG4gIHJlYWRvbmx5IG1heER1cmF0aW9uOiBEdXJhdGlvbjtcbn1cblxuZXhwb3J0IGNsYXNzIExhdGVuY3lBbGFybUZhY3Rvcnkge1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgYWxhcm1GYWN0b3J5OiBBbGFybUZhY3Rvcnk7XG5cbiAgY29uc3RydWN0b3IoYWxhcm1GYWN0b3J5OiBBbGFybUZhY3RvcnkpIHtcbiAgICB0aGlzLmFsYXJtRmFjdG9yeSA9IGFsYXJtRmFjdG9yeTtcbiAgfVxuXG4gIGFkZExhdGVuY3lBbGFybShcbiAgICBtZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gICAgbGF0ZW5jeVR5cGU6IExhdGVuY3lUeXBlLFxuICAgIHByb3BzOiBMYXRlbmN5VGhyZXNob2xkLFxuICAgIGRpc2FtYmlndWF0b3I/OiBzdHJpbmcsXG4gICAgYWRkaXRpb25hbEFsYXJtTmFtZVN1ZmZpeDogc3RyaW5nIHwgdW5kZWZpbmVkID0gdW5kZWZpbmVkLFxuICApIHtcbiAgICBjb25zdCBhbGFybU5hbWVTdWZmaXggPSBbXCJMYXRlbmN5XCIsIGxhdGVuY3lUeXBlLCBhZGRpdGlvbmFsQWxhcm1OYW1lU3VmZml4XVxuICAgICAgLmZpbHRlcigoaSkgPT4gaSAhPT0gdW5kZWZpbmVkKVxuICAgICAgLmpvaW4oXCItXCIpO1xuXG4gICAgcmV0dXJuIHRoaXMuYWxhcm1GYWN0b3J5LmFkZEFsYXJtKG1ldHJpYywge1xuICAgICAgdHJlYXRNaXNzaW5nRGF0YTpcbiAgICAgICAgcHJvcHMudHJlYXRNaXNzaW5nRGF0YU92ZXJyaWRlID8/IFRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjpcbiAgICAgICAgcHJvcHMuY29tcGFyaXNvbk9wZXJhdG9yT3ZlcnJpZGUgPz9cbiAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9USFJFU0hPTEQsXG4gICAgICAuLi5wcm9wcyxcbiAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICB0aHJlc2hvbGQ6IHByb3BzLm1heExhdGVuY3kudG9NaWxsaXNlY29uZHMoeyBpbnRlZ3JhbDogZmFsc2UgfSksXG4gICAgICBhbGFybU5hbWVTdWZmaXgsXG4gICAgICAvLyB3ZSB3aWxsIGRlZHVwZSBhbnkga2luZCBvZiBsYXRlbmN5IGlzc3VlIHRvIHRoZSBzYW1lIHRpY2tldFxuICAgICAgYWxhcm1EZWR1cGVTdHJpbmdTdWZmaXg6IHRoaXMuYWxhcm1GYWN0b3J5XG4gICAgICAgIC5zaG91bGRVc2VEZWZhdWx0RGVkdXBlRm9yTGF0ZW5jeVxuICAgICAgICA/IFwiQW55TGF0ZW5jeVwiXG4gICAgICAgIDogYWxhcm1OYW1lU3VmZml4LFxuICAgICAgYWxhcm1EZXNjcmlwdGlvbjogYCR7bGF0ZW5jeVR5cGV9IGxhdGVuY3kgaXMgdG9vIGhpZ2guYCxcbiAgICB9KTtcbiAgfVxuXG4gIGFkZEludGVncmF0aW9uTGF0ZW5jeUFsYXJtKFxuICAgIG1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydCxcbiAgICBsYXRlbmN5VHlwZTogTGF0ZW5jeVR5cGUsXG4gICAgcHJvcHM6IExhdGVuY3lUaHJlc2hvbGQsXG4gICAgZGlzYW1iaWd1YXRvcj86IHN0cmluZyxcbiAgICBhZGRpdGlvbmFsQWxhcm1OYW1lU3VmZml4OiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gICkge1xuICAgIGNvbnN0IGFsYXJtTmFtZVN1ZmZpeCA9IFtcbiAgICAgIFwiSW50ZWdyYXRpb25MYXRlbmN5XCIsXG4gICAgICBsYXRlbmN5VHlwZSxcbiAgICAgIGFkZGl0aW9uYWxBbGFybU5hbWVTdWZmaXgsXG4gICAgXVxuICAgICAgLmZpbHRlcigoaSkgPT4gaSAhPT0gdW5kZWZpbmVkKVxuICAgICAgLmpvaW4oXCItXCIpO1xuXG4gICAgcmV0dXJuIHRoaXMuYWxhcm1GYWN0b3J5LmFkZEFsYXJtKG1ldHJpYywge1xuICAgICAgdHJlYXRNaXNzaW5nRGF0YTpcbiAgICAgICAgcHJvcHMudHJlYXRNaXNzaW5nRGF0YU92ZXJyaWRlID8/IFRyZWF0TWlzc2luZ0RhdGEuTk9UX0JSRUFDSElORyxcbiAgICAgIGNvbXBhcmlzb25PcGVyYXRvcjpcbiAgICAgICAgcHJvcHMuY29tcGFyaXNvbk9wZXJhdG9yT3ZlcnJpZGUgPz9cbiAgICAgICAgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9USFJFU0hPTEQsXG4gICAgICAuLi5wcm9wcyxcbiAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICB0aHJlc2hvbGQ6IHByb3BzLm1heExhdGVuY3kudG9NaWxsaXNlY29uZHMoeyBpbnRlZ3JhbDogZmFsc2UgfSksXG4gICAgICBhbGFybU5hbWVTdWZmaXgsXG4gICAgICAvLyB3ZSB3aWxsIGRlZHVwZSBhbnkga2luZCBvZiBsYXRlbmN5IGlzc3VlIHRvIHRoZSBzYW1lIGFsYXJtXG4gICAgICBhbGFybURlZHVwZVN0cmluZ1N1ZmZpeDogdGhpcy5hbGFybUZhY3RvcnlcbiAgICAgICAgLnNob3VsZFVzZURlZmF1bHREZWR1cGVGb3JMYXRlbmN5XG4gICAgICAgID8gXCJBbnlMYXRlbmN5XCJcbiAgICAgICAgOiBhbGFybU5hbWVTdWZmaXgsXG4gICAgICBhbGFybURlc2NyaXB0aW9uOiBgJHtsYXRlbmN5VHlwZX0gaW50ZWdyYXRpb24gbGF0ZW5jeSBpcyB0b28gaGlnaC5gLFxuICAgIH0pO1xuICB9XG5cbiAgYWRkRHVyYXRpb25BbGFybShcbiAgICBtZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gICAgbGF0ZW5jeVR5cGU6IExhdGVuY3lUeXBlLFxuICAgIHByb3BzOiBEdXJhdGlvblRocmVzaG9sZCxcbiAgICBkaXNhbWJpZ3VhdG9yPzogc3RyaW5nLFxuICAgIGFkZGl0aW9uYWxBbGFybU5hbWVTdWZmaXg6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgKSB7XG4gICAgY29uc3QgYWxhcm1OYW1lU3VmZml4ID0gW1wiRHVyYXRpb25cIiwgbGF0ZW5jeVR5cGUsIGFkZGl0aW9uYWxBbGFybU5hbWVTdWZmaXhdXG4gICAgICAuZmlsdGVyKChpKSA9PiBpICE9PSB1bmRlZmluZWQpXG4gICAgICAuam9pbihcIi1cIik7XG5cbiAgICByZXR1cm4gdGhpcy5hbGFybUZhY3RvcnkuYWRkQWxhcm0obWV0cmljLCB7XG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOlxuICAgICAgICBwcm9wcy50cmVhdE1pc3NpbmdEYXRhT3ZlcnJpZGUgPz8gVHJlYXRNaXNzaW5nRGF0YS5OT1RfQlJFQUNISU5HLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOlxuICAgICAgICBwcm9wcy5jb21wYXJpc29uT3BlcmF0b3JPdmVycmlkZSA/P1xuICAgICAgICBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgIHRocmVzaG9sZDogcHJvcHMubWF4RHVyYXRpb24udG9NaWxsaXNlY29uZHMoeyBpbnRlZ3JhbDogZmFsc2UgfSksXG4gICAgICBhbGFybU5hbWVTdWZmaXgsXG4gICAgICAvLyB3ZSB3aWxsIGRlZHVwZSBhbnkga2luZCBvZiBsYXRlbmN5IGlzc3VlIHRvIHRoZSBzYW1lIHRpY2tldFxuICAgICAgYWxhcm1EZWR1cGVTdHJpbmdTdWZmaXg6IHRoaXMuYWxhcm1GYWN0b3J5XG4gICAgICAgIC5zaG91bGRVc2VEZWZhdWx0RGVkdXBlRm9yTGF0ZW5jeVxuICAgICAgICA/IFwiQW55RHVyYXRpb25cIlxuICAgICAgICA6IGFsYXJtTmFtZVN1ZmZpeCxcbiAgICAgIGFsYXJtRGVzY3JpcHRpb246IGAke2xhdGVuY3lUeXBlfSBkdXJhdGlvbiBpcyB0b28gbG9uZy5gLFxuICAgIH0pO1xuICB9XG5cbiAgYWRkQ3VzdG9tRHVyYXRpb25BbGFybShcbiAgICBtZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQsXG4gICAgbGF0ZW5jeVR5cGU6IExhdGVuY3lUeXBlLFxuICAgIHByb3BzOiBEdXJhdGlvblRocmVzaG9sZCxcbiAgICBkdXJhdGlvbk5hbWU6IHN0cmluZyxcbiAgICBkaXNhbWJpZ3VhdG9yPzogc3RyaW5nLFxuICAgIGFkZGl0aW9uYWxBbGFybU5hbWVTdWZmaXg6IHN0cmluZyB8IHVuZGVmaW5lZCA9IHVuZGVmaW5lZCxcbiAgKSB7XG4gICAgY29uc3QgYWxhcm1OYW1lU3VmZml4ID0gW1xuICAgICAgZHVyYXRpb25OYW1lLFxuICAgICAgbGF0ZW5jeVR5cGUsXG4gICAgICBhZGRpdGlvbmFsQWxhcm1OYW1lU3VmZml4LFxuICAgIF1cbiAgICAgIC5maWx0ZXIoKGkpID0+IGkgIT09IHVuZGVmaW5lZClcbiAgICAgIC5qb2luKFwiLVwiKTtcblxuICAgIHJldHVybiB0aGlzLmFsYXJtRmFjdG9yeS5hZGRBbGFybShtZXRyaWMsIHtcbiAgICAgIHRyZWF0TWlzc2luZ0RhdGE6XG4gICAgICAgIHByb3BzLnRyZWF0TWlzc2luZ0RhdGFPdmVycmlkZSA/PyBUcmVhdE1pc3NpbmdEYXRhLk5PVF9CUkVBQ0hJTkcsXG4gICAgICBjb21wYXJpc29uT3BlcmF0b3I6XG4gICAgICAgIHByb3BzLmNvbXBhcmlzb25PcGVyYXRvck92ZXJyaWRlID8/XG4gICAgICAgIENvbXBhcmlzb25PcGVyYXRvci5HUkVBVEVSX1RIQU5fVEhSRVNIT0xELFxuICAgICAgLi4ucHJvcHMsXG4gICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgdGhyZXNob2xkOiBwcm9wcy5tYXhEdXJhdGlvbi50b01pbGxpc2Vjb25kcyh7IGludGVncmFsOiBmYWxzZSB9KSxcbiAgICAgIGFsYXJtTmFtZVN1ZmZpeCxcbiAgICAgIC8vIHdlIHdpbGwgZGVkdXBlIGFueSBraW5kIG9mIGxhdGVuY3kgaXNzdWUgdG8gdGhlIHNhbWUgdGlja2V0XG4gICAgICBhbGFybURlZHVwZVN0cmluZ1N1ZmZpeDogdGhpcy5hbGFybUZhY3RvcnlcbiAgICAgICAgLnNob3VsZFVzZURlZmF1bHREZWR1cGVGb3JMYXRlbmN5XG4gICAgICAgID8gYEFueSR7ZHVyYXRpb25OYW1lfWBcbiAgICAgICAgOiBhbGFybU5hbWVTdWZmaXgsXG4gICAgICBhbGFybURlc2NyaXB0aW9uOiBgJHtsYXRlbmN5VHlwZX0gJHtkdXJhdGlvbk5hbWV9IGlzIHRvbyBsb25nLmAsXG4gICAgfSk7XG4gIH1cblxuICBhZGRKdm1HYXJiYWdlQ29sbGVjdGlvbkR1cmF0aW9uQWxhcm0oXG4gICAgbWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0LFxuICAgIGxhdGVuY3lUeXBlOiBMYXRlbmN5VHlwZSxcbiAgICBwcm9wczogRHVyYXRpb25UaHJlc2hvbGQsXG4gICAgZGlzYW1iaWd1YXRvcj86IHN0cmluZyxcbiAgICBhZGRpdGlvbmFsQWxhcm1OYW1lU3VmZml4OiBzdHJpbmcgfCB1bmRlZmluZWQgPSB1bmRlZmluZWQsXG4gICkge1xuICAgIGNvbnN0IGFsYXJtTmFtZVN1ZmZpeCA9IFtcbiAgICAgIFwiR2FyYmFnZS1Db2xsZWN0aW9uLVRpbWVcIixcbiAgICAgIGxhdGVuY3lUeXBlLFxuICAgICAgYWRkaXRpb25hbEFsYXJtTmFtZVN1ZmZpeCxcbiAgICBdXG4gICAgICAuZmlsdGVyKChpKSA9PiBpICE9PSB1bmRlZmluZWQpXG4gICAgICAuam9pbihcIi1cIik7XG5cbiAgICByZXR1cm4gdGhpcy5hbGFybUZhY3RvcnkuYWRkQWxhcm0obWV0cmljLCB7XG4gICAgICB0cmVhdE1pc3NpbmdEYXRhOlxuICAgICAgICBwcm9wcy50cmVhdE1pc3NpbmdEYXRhT3ZlcnJpZGUgPz8gVHJlYXRNaXNzaW5nRGF0YS5OT1RfQlJFQUNISU5HLFxuICAgICAgY29tcGFyaXNvbk9wZXJhdG9yOlxuICAgICAgICBwcm9wcy5jb21wYXJpc29uT3BlcmF0b3JPdmVycmlkZSA/P1xuICAgICAgICBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRCxcbiAgICAgIC4uLnByb3BzLFxuICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgIHRocmVzaG9sZDogcHJvcHMubWF4RHVyYXRpb24udG9NaWxsaXNlY29uZHMoeyBpbnRlZ3JhbDogZmFsc2UgfSksXG4gICAgICBhbGFybU5hbWVTdWZmaXgsXG4gICAgICAvLyB3ZSB3aWxsIGRlZHVwZSBhbnkga2luZCBvZiBsYXRlbmN5IGlzc3VlIHRvIHRoZSBzYW1lIHRpY2tldFxuICAgICAgYWxhcm1EZWR1cGVTdHJpbmdTdWZmaXg6IHRoaXMuYWxhcm1GYWN0b3J5XG4gICAgICAgIC5zaG91bGRVc2VEZWZhdWx0RGVkdXBlRm9yTGF0ZW5jeVxuICAgICAgICA/IFwiQW55RHVyYXRpb25cIlxuICAgICAgICA6IGFsYXJtTmFtZVN1ZmZpeCxcbiAgICAgIGFsYXJtRGVzY3JpcHRpb246IGAke2xhdGVuY3lUeXBlfSBkdXJhdGlvbiBpcyB0b28gbG9uZy5gLFxuICAgIH0pO1xuICB9XG59XG4iXX0=