cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
103 lines • 17.8 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.ScaleAlarms = ScaleAlarms;
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const SupportedMetricPeriods = [
aws_cdk_lib_1.Duration.minutes(1),
aws_cdk_lib_1.Duration.minutes(5),
aws_cdk_lib_1.Duration.minutes(15),
aws_cdk_lib_1.Duration.hours(1),
aws_cdk_lib_1.Duration.hours(6),
aws_cdk_lib_1.Duration.days(1),
aws_cdk_lib_1.Duration.days(7),
];
/**
* Creates a function that clones alarms to be more scaled using the multiplication factors
* provided. This function can be provided to the `cloneAlarms` method of
* {@link MonitoringFacade}.
*
* This can be used with scaling factors less than 1.0 to create more aggressive alarms, which
* can be useful to provide early detection and trigger change rollbacks.
*
* If the datapoints to alarm would be scaled to such a small number that it can't effectively be
* alarmed, the metric period will be reduced to the next smallest duration and the required
* datapoint count will scale up accordingly.
*
* @param props The properties for configuring the function.
* @returns A function that clones alarms and applies scaling factors.
*/
function ScaleAlarms(props) {
return function (alarm) {
let thresholdMultiplierToUse = 1;
if (props.thresholdMultiplier) {
const comparisonOperator = alarm.alarmDefinition.addAlarmProps.comparisonOperator;
switch (comparisonOperator) {
case aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_OR_EQUAL_TO_THRESHOLD:
case aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD:
thresholdMultiplierToUse = props.thresholdMultiplier;
break;
case aws_cloudwatch_1.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD:
case aws_cloudwatch_1.ComparisonOperator.LESS_THAN_THRESHOLD:
thresholdMultiplierToUse = 1.0 / props.thresholdMultiplier;
break;
case aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_UPPER_THRESHOLD:
case aws_cloudwatch_1.ComparisonOperator.LESS_THAN_LOWER_THRESHOLD:
case aws_cloudwatch_1.ComparisonOperator.LESS_THAN_LOWER_OR_GREATER_THAN_UPPER_THRESHOLD:
// Don't modify thresholds for anomaly detection models.
thresholdMultiplierToUse = 1;
break;
default:
throw new Error(`Comparison operator ${comparisonOperator} is not supported by ScaleAlarms.`);
}
}
let cloneThreshold = alarm.alarmDefinition.addAlarmProps.threshold * thresholdMultiplierToUse;
let cloneEvaluationPeriods = alarm.alarmDefinition.evaluationPeriods *
(props.evaluationPeriodsMultiplier ??
props.datapointsToAlarmMultiplier ??
1);
let cloneDatapointsToAlarm = alarm.alarmDefinition.datapointsToAlarm *
(props.datapointsToAlarmMultiplier ?? 1);
// If the tightened datapoints to alarm is now so small that we can't effectively alarm on it,
// reduce the metric period to the next smallest duration and scale up the datapoint count accordingly.
let clonePeriod = alarm.alarmDefinition.addAlarmProps.period;
if (cloneEvaluationPeriods < 2 || cloneDatapointsToAlarm < 2) {
const originalPeriod = alarm.alarmDefinition.addAlarmProps.period ??
alarm.alarmDefinition.metric.period;
const nextSmallestPeriod = findNextSmallestPeriod(originalPeriod);
if (nextSmallestPeriod) {
clonePeriod = nextSmallestPeriod;
const datapointScaleFactor = originalPeriod.toSeconds() / nextSmallestPeriod.toSeconds();
cloneEvaluationPeriods = cloneEvaluationPeriods * datapointScaleFactor;
cloneDatapointsToAlarm = cloneDatapointsToAlarm * datapointScaleFactor;
// If the metric uses SUM or N, we also need to scale the threshold down.
if ("statistic" in alarm.alarmDefinition.metric) {
if (alarm.alarmDefinition.metric.statistic === aws_cloudwatch_1.Stats.SUM ||
alarm.alarmDefinition.metric.statistic === aws_cloudwatch_1.Stats.SAMPLE_COUNT) {
cloneThreshold = cloneThreshold / datapointScaleFactor;
}
}
}
}
cloneEvaluationPeriods = Math.max(1, Math.round(cloneEvaluationPeriods));
cloneDatapointsToAlarm = Math.max(1, Math.round(cloneDatapointsToAlarm));
return {
...alarm.alarmDefinition.addAlarmProps,
disambiguator: props.disambiguator,
threshold: cloneThreshold,
evaluationPeriods: cloneEvaluationPeriods,
datapointsToAlarm: cloneDatapointsToAlarm,
period: clonePeriod,
};
};
}
function findNextSmallestPeriod(originalPeriod) {
for (let index = SupportedMetricPeriods.length - 1; index >= 0; index--) {
const current = SupportedMetricPeriods[index];
if (current.toSeconds() < originalPeriod.toSeconds()) {
return current;
}
}
return undefined;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiU2NhbGVBbGFybXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyJTY2FsZUFsYXJtcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQW1FQSxrQ0ErRUM7QUFsSkQsNkNBQXVDO0FBQ3ZDLCtEQUF1RTtBQUd2RSxNQUFNLHNCQUFzQixHQUFHO0lBQzdCLHNCQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNuQixzQkFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7SUFDbkIsc0JBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO0lBQ3BCLHNCQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUNqQixzQkFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUM7SUFDakIsc0JBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQ2hCLHNCQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztDQUNqQixDQUFDO0FBd0NGOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLEtBQXVCO0lBQ2pELE9BQU8sVUFBVSxLQUEwQjtRQUN6QyxJQUFJLHdCQUF3QixHQUFXLENBQUMsQ0FBQztRQUN6QyxJQUFJLEtBQUssQ0FBQyxtQkFBbUIsRUFBRSxDQUFDO1lBQzlCLE1BQU0sa0JBQWtCLEdBQ3RCLEtBQUssQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLGtCQUFrQixDQUFDO1lBQ3pELFFBQVEsa0JBQWtCLEVBQUUsQ0FBQztnQkFDM0IsS0FBSyxtQ0FBa0IsQ0FBQyxrQ0FBa0MsQ0FBQztnQkFDM0QsS0FBSyxtQ0FBa0IsQ0FBQyxzQkFBc0I7b0JBQzVDLHdCQUF3QixHQUFHLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQztvQkFDckQsTUFBTTtnQkFDUixLQUFLLG1DQUFrQixDQUFDLCtCQUErQixDQUFDO2dCQUN4RCxLQUFLLG1DQUFrQixDQUFDLG1CQUFtQjtvQkFDekMsd0JBQXdCLEdBQUcsR0FBRyxHQUFHLEtBQUssQ0FB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LElBQUksS0FBSyxHQUFHLHNCQUFzQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ3hFLE1BQU0sT0FBTyxHQUFHLHNCQUFzQixDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQzlDLElBQUksT0FBTyxDQUFDLFNBQVMsRUFBRSxHQUFHLGNBQWMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQ3JELE9BQU8sT0FBTyxDQUFDO1FBQ2pCLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxTQUFTLENBQUM7QUFDbkIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IER1cmF0aW9uIH0gZnJvbSBcImF3cy1jZGstbGliXCI7XG5pbXBvcnQgeyBDb21wYXJpc29uT3BlcmF0b3IsIFN0YXRzIH0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1jbG91ZHdhdGNoXCI7XG5pbXBvcnQgeyBBbGFybUNsb25lRnVuY3Rpb24sIEFsYXJtV2l0aEFubm90YXRpb24gfSBmcm9tIFwiLi4vLi5cIjtcblxuY29uc3QgU3VwcG9ydGVkTWV0cmljUGVyaW9kcyA9IFtcbiAgRHVyYXRpb24ubWludXRlcygxKSxcbiAgRHVyYXRpb24ubWludXRlcyg1KSxcbiAgRHVyYXRpb24ubWludXRlcygxNSksXG4gIER1cmF0aW9uLmhvdXJzKDEpLFxuICBEdXJhdGlvbi5ob3Vycyg2KSxcbiAgRHVyYXRpb24uZGF5cygxKSxcbiAgRHVyYXRpb24uZGF5cyg3KSxcbl07XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgY29uZmlndXJpbmcgYSBmdW5jdGlvbiB0aGF0IGNsb25lcyBhbGFybXMgdG8gYmUgc2NhbGVkIGJ5IG11bHRpcGxpY2F0aW9uIGZhY3RvcnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NhbGVBbGFybXNQcm9wcyB7XG4gIC8qKlxuICAgKiBUaGUgZGlzYW1iaWd1YXRvciB0byBhc3NpZ24gdG8gdGhlIGFsYXJtcyBjbG9uZWQgYnkgdGhlIGZ1bmN0aW9uLlxuICAgKi9cbiAgcmVhZG9ubHkgZGlzYW1iaWd1YXRvcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBIG11bHRpcGxpY2F0aW9uIGZhY3RvciB0byBhcHBseSB0byB0aGUgdGhyZXNob2xkIG9mIHRoZSBjbG9uZWQgYWxhcm1zLlxuICAgKlxuICAgKiBUaHJlc2hvbGQgc2NhbGluZyBkb2VzIG5vdCBhcHBseSB0byB0aHJlc2hvbGRzIG9uIGFub21hbHkgZGV0ZWN0aW9uIGFsYXJtcy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSAxLjBcbiAgICovXG4gIHJlYWRvbmx5IHRocmVzaG9sZE11bHRpcGxpZXI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEEgbXVsdGlwbGljYXRpb24gZmFjdG9yIHRvIGFwcGx5IHRvIHRoZSBkYXRhcG9pbnRzVG9BbGFybSBwcm9wZXJ0eSBvZiB0aGUgY2xvbmVkIGFsYXJtcy5cbiAgICpcbiAgICogV2hlbiBjb25maWd1cmVkIHdpdGggYSB2YWx1ZSBsZXNzIHRoYXQgMS4wLCB0aGUgY2xvbmVkIGFsYXJtICptYXkqIHVzZSBhIG1ldHJpYyB3aXRoIGEgbW9yZVxuICAgKiBncmFudWxhciBwZXJpb2Qgc28gdGhhdCB0aGUgcmVzdWx0IHdpbGwgdXNlIGEgcmVhc29uYWJsZSBudW1iZXIgb2YgZGF0YXBvaW50cy4gSW4gdGhpcyBjYXNlLFxuICAgKiB0aGUgYGRhdGFwb2ludHNUb0FsYXJtYCBhbmQgYGV2YWx1YXRpb25QZXJpb2RzYCBhcmUgaW5jcmVhc2VkIGJ5IHRoZSBzYW1lIGZhY3RvciB0aGF0IHRoZVxuICAgKiBwZXJpb2QgaXMgZGVjcmVhc2VkLiBJdCB3aWxsIGFsc28gc2NhbGUgYHRocmVzaG9sZGAgZm9yIG1ldHJpY3MgdXNpbmcgdGhlIFNVTSBvciBTQU1QTEVfQ09VTlRcbiAgICogc3RhdHMuXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gMS4wXG4gICAqL1xuICByZWFkb25seSBkYXRhcG9pbnRzVG9BbGFybU11bHRpcGxpZXI/OiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIEEgbXVsdGlwbGljYXRpb24gZmFjdG9yIHRvIGFwcGx5IHRvIHRoZSBgZXZhbHVhdGlvblBlcmlvZHNgIHByb3BlcnR5IG9mIHRoZSBjbG9uZWQgYWxhcm1zLlxuICAgKiBAZGVmYXVsdCAtIFNhbWUgYXMgZGF0YXBvaW50c1RvQWxhcm1NdWx0aXBsaWVyLlxuICAgKi9cbiAgcmVhZG9ubHkgZXZhbHVhdGlvblBlcmlvZHNNdWx0aXBsaWVyPzogbnVtYmVyO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBmdW5jdGlvbiB0aGF0IGNsb25lcyBhbGFybXMgdG8gYmUgbW9yZSBzY2FsZWQgdXNpbmcgdGhlIG11bHRpcGxpY2F0aW9uIGZhY3RvcnNcbiAqIHByb3ZpZGVkLiBUaGlzIGZ1bmN0aW9uIGNhbiBiZSBwcm92aWRlZCB0byB0aGUgYGNsb25lQWxhcm1zYCBtZXRob2Qgb2ZcbiAqIHtAbGluayBNb25pdG9yaW5nRmFjYWRlfS5cbiAqXG4gKiBUaGlzIGNhbiBiZSB1c2VkIHdpdGggc2NhbGluZyBmYWN0b3JzIGxlc3MgdGhhbiAxLjAgdG8gY3JlYXRlIG1vcmUgYWdncmVzc2l2ZSBhbGFybXMsIHdoaWNoXG4gKiBjYW4gYmUgdXNlZnVsIHRvIHByb3ZpZGUgZWFybHkgZGV0ZWN0aW9uIGFuZCB0cmlnZ2VyIGNoYW5nZSByb2xsYmFja3MuXG4gKlxuICogSWYgdGhlIGRhdGFwb2ludHMgdG8gYWxhcm0gd291bGQgYmUgc2NhbGVkIHRvIHN1Y2ggYSBzbWFsbCBudW1iZXIgdGhhdCBpdCBjYW4ndCBlZmZlY3RpdmVseSBiZVxuICogYWxhcm1lZCwgdGhlIG1ldHJpYyBwZXJpb2Qgd2lsbCBiZSByZWR1Y2VkIHRvIHRoZSBuZXh0IHNtYWxsZXN0IGR1cmF0aW9uIGFuZCB0aGUgcmVxdWlyZWRcbiAqIGRhdGFwb2ludCBjb3VudCB3aWxsIHNjYWxlIHVwIGFjY29yZGluZ2x5LlxuICpcbiAqIEBwYXJhbSBwcm9wcyBUaGUgcHJvcGVydGllcyBmb3IgY29uZmlndXJpbmcgdGhlIGZ1bmN0aW9uLlxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0IGNsb25lcyBhbGFybXMgYW5kIGFwcGxpZXMgc2NhbGluZyBmYWN0b3JzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2NhbGVBbGFybXMocHJvcHM6IFNjYWxlQWxhcm1zUHJvcHMpOiBBbGFybUNsb25lRnVuY3Rpb24ge1xuICByZXR1cm4gZnVuY3Rpb24gKGFsYXJtOiBBbGFybVdpdGhBbm5vdGF0aW9uKSB7XG4gICAgbGV0IHRocmVzaG9sZE11bHRpcGxpZXJUb1VzZTogbnVtYmVyID0gMTtcbiAgICBpZiAocHJvcHMudGhyZXNob2xkTXVsdGlwbGllcikge1xuICAgICAgY29uc3QgY29tcGFyaXNvbk9wZXJhdG9yID1cbiAgICAgICAgYWxhcm0uYWxhcm1EZWZpbml0aW9uLmFkZEFsYXJtUHJvcHMuY29tcGFyaXNvbk9wZXJhdG9yO1xuICAgICAgc3dpdGNoIChjb21wYXJpc29uT3BlcmF0b3IpIHtcbiAgICAgICAgY2FzZSBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX09SX0VRVUFMX1RPX1RIUkVTSE9MRDpcbiAgICAgICAgY2FzZSBDb21wYXJpc29uT3BlcmF0b3IuR1JFQVRFUl9USEFOX1RIUkVTSE9MRDpcbiAgICAgICAgICB0aHJlc2hvbGRNdWx0aXBsaWVyVG9Vc2UgPSBwcm9wcy50aHJlc2hvbGRNdWx0aXBsaWVyO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIENvbXBhcmlzb25PcGVyYXRvci5MRVNTX1RIQU5fT1JfRVFVQUxfVE9fVEhSRVNIT0xEOlxuICAgICAgICBjYXNlIENvbXBhcmlzb25PcGVyYXRvci5MRVNTX1RIQU5fVEhSRVNIT0xEOlxuICAgICAgICAgIHRocmVzaG9sZE11bHRpcGxpZXJUb1VzZSA9IDEuMCAvIHByb3BzLnRocmVzaG9sZE11bHRpcGxpZXI7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgQ29tcGFyaXNvbk9wZXJhdG9yLkdSRUFURVJfVEhBTl9VUFBFUl9USFJFU0hPTEQ6XG4gICAgICAgIGNhc2UgQ29tcGFyaXNvbk9wZXJhdG9yLkxFU1NfVEhBTl9MT1dFUl9USFJFU0hPTEQ6XG4gICAgICAgIGNhc2UgQ29tcGFyaXNvbk9wZXJhdG9yLkxFU1NfVEhBTl9MT1dFUl9PUl9HUkVBVEVSX1RIQU5fVVBQRVJfVEhSRVNIT0xEOlxuICAgICAgICAgIC8vIERvbid0IG1vZGlmeSB0aHJlc2hvbGRzIGZvciBhbm9tYWx5IGRldGVjdGlvbiBtb2RlbHMuXG4gICAgICAgICAgdGhyZXNob2xkTXVsdGlwbGllclRvVXNlID0gMTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICBgQ29tcGFyaXNvbiBvcGVyYXRvciAke2NvbXBhcmlzb25PcGVyYXRvcn0gaXMgbm90IHN1cHBvcnRlZCBieSBTY2FsZUFsYXJtcy5gLFxuICAgICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIGxldCBjbG9uZVRocmVzaG9sZCA9XG4gICAgICBhbGFybS5hbGFybURlZmluaXRpb24uYWRkQWxhcm1Qcm9wcy50aHJlc2hvbGQgKiB0aHJlc2hvbGRNdWx0aXBsaWVyVG9Vc2U7XG5cbiAgICBsZXQgY2xvbmVFdmFsdWF0aW9uUGVyaW9kcyA9XG4gICAgICBhbGFybS5hbGFybURlZmluaXRpb24uZXZhbHVhdGlvblBlcmlvZHMgKlxuICAgICAgKHByb3BzLmV2YWx1YXRpb25QZXJpb2RzTXVsdGlwbGllciA/P1xuICAgICAgICBwcm9wcy5kYXRhcG9pbnRzVG9BbGFybU11bHRpcGxpZXIgPz9cbiAgICAgICAgMSk7XG4gICAgbGV0IGNsb25lRGF0YXBvaW50c1RvQWxhcm0gPVxuICAgICAgYWxhcm0uYWxhcm1EZWZpbml0aW9uLmRhdGFwb2ludHNUb0FsYXJtICpcbiAgICAgIChwcm9wcy5kYXRhcG9pbnRzVG9BbGFybU11bHRpcGxpZXIgPz8gMSk7XG5cbiAgICAvLyBJZiB0aGUgdGlnaHRlbmVkIGRhdGFwb2ludHMgdG8gYWxhcm0gaXMgbm93IHNvIHNtYWxsIHRoYXQgd2UgY2FuJ3QgZWZmZWN0aXZlbHkgYWxhcm0gb24gaXQsXG4gICAgLy8gcmVkdWNlIHRoZSBtZXRyaWMgcGVyaW9kIHRvIHRoZSBuZXh0IHNtYWxsZXN0IGR1cmF0aW9uIGFuZCBzY2FsZSB1cCB0aGUgZGF0YXBvaW50IGNvdW50IGFjY29yZGluZ2x5LlxuICAgIGxldCBjbG9uZVBlcmlvZCA9IGFsYXJtLmFsYXJtRGVmaW5pdGlvbi5hZGRBbGFybVByb3BzLnBlcmlvZDtcbiAgICBpZiAoY2xvbmVFdmFsdWF0aW9uUGVyaW9kcyA8IDIgfHwgY2xvbmVEYXRhcG9pbnRzVG9BbGFybSA8IDIpIHtcbiAgICAgIGNvbnN0IG9yaWdpbmFsUGVyaW9kID1cbiAgICAgICAgYWxhcm0uYWxhcm1EZWZpbml0aW9uLmFkZEFsYXJtUHJvcHMucGVyaW9kID8/XG4gICAgICAgIGFsYXJtLmFsYXJtRGVmaW5pdGlvbi5tZXRyaWMucGVyaW9kO1xuXG4gICAgICBjb25zdCBuZXh0U21hbGxlc3RQZXJpb2QgPSBmaW5kTmV4dFNtYWxsZXN0UGVyaW9kKG9yaWdpbmFsUGVyaW9kKTtcbiAgICAgIGlmIChuZXh0U21hbGxlc3RQZXJpb2QpIHtcbiAgICAgICAgY2xvbmVQZXJpb2QgPSBuZXh0U21hbGxlc3RQZXJpb2Q7XG4gICAgICAgIGNvbnN0IGRhdGFwb2ludFNjYWxlRmFjdG9yID1cbiAgICAgICAgICBvcmlnaW5hbFBlcmlvZC50b1NlY29uZHMoKSAvIG5leHRTbWFsbGVzdFBlcmlvZC50b1NlY29uZHMoKTtcbiAgICAgICAgY2xvbmVFdmFsdWF0aW9uUGVyaW9kcyA9IGNsb25lRXZhbHVhdGlvblBlcmlvZHMgKiBkYXRhcG9pbnRTY2FsZUZhY3RvcjtcbiAgICAgICAgY2xvbmVEYXRhcG9pbnRzVG9BbGFybSA9IGNsb25lRGF0YXBvaW50c1RvQWxhcm0gKiBkYXRhcG9pbnRTY2FsZUZhY3RvcjtcblxuICAgICAgICAvLyBJZiB0aGUgbWV0cmljIHVzZXMgU1VNIG9yIE4sIHdlIGFsc28gbmVlZCB0byBzY2FsZSB0aGUgdGhyZXNob2xkIGRvd24uXG4gICAgICAgIGlmIChcInN0YXRpc3RpY1wiIGluIGFsYXJtLmFsYXJtRGVmaW5pdGlvbi5tZXRyaWMpIHtcbiAgICAgICAgICBpZiAoXG4gICAgICAgICAgICBhbGFybS5hbGFybURlZmluaXRpb24ubWV0cmljLnN0YXRpc3RpYyA9PT0gU3RhdHMuU1VNIHx8XG4gICAgICAgICAgICBhbGFybS5hbGFybURlZmluaXRpb24ubWV0cmljLnN0YXRpc3RpYyA9PT0gU3RhdHMuU0FNUExFX0NPVU5UXG4gICAgICAgICAgKSB7XG4gICAgICAgICAgICBjbG9uZVRocmVzaG9sZCA9IGNsb25lVGhyZXNob2xkIC8gZGF0YXBvaW50U2NhbGVGYWN0b3I7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgY2xvbmVFdmFsdWF0aW9uUGVyaW9kcyA9IE1hdGgubWF4KDEsIE1hdGgucm91bmQoY2xvbmVFdmFsdWF0aW9uUGVyaW9kcykpO1xuICAgIGNsb25lRGF0YXBvaW50c1RvQWxhcm0gPSBNYXRoLm1heCgxLCBNYXRoLnJvdW5kKGNsb25lRGF0YXBvaW50c1RvQWxhcm0pKTtcblxuICAgIHJldHVybiB7XG4gICAgICAuLi5hbGFybS5hbGFybURlZmluaXRpb24uYWRkQWxhcm1Qcm9wcyxcbiAgICAgIGRpc2FtYmlndWF0b3I6IHByb3BzLmRpc2FtYmlndWF0b3IsXG4gICAgICB0aHJlc2hvbGQ6IGNsb25lVGhyZXNob2xkLFxuICAgICAgZXZhbHVhdGlvblBlcmlvZHM6IGNsb25lRXZhbHVhdGlvblBlcmlvZHMsXG4gICAgICBkYXRhcG9pbnRzVG9BbGFybTogY2xvbmVEYXRhcG9pbnRzVG9BbGFybSxcbiAgICAgIHBlcmlvZDogY2xvbmVQZXJpb2QsXG4gICAgfTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gZmluZE5leHRTbWFsbGVzdFBlcmlvZChvcmlnaW5hbFBlcmlvZDogRHVyYXRpb24pIHtcbiAgZm9yIChsZXQgaW5kZXggPSBTdXBwb3J0ZWRNZXRyaWNQZXJpb2RzLmxlbmd0aCAtIDE7IGluZGV4ID49IDA7IGluZGV4LS0pIHtcbiAgICBjb25zdCBjdXJyZW50ID0gU3VwcG9ydGVkTWV0cmljUGVyaW9kc1tpbmRleF07XG4gICAgaWYgKGN1cnJlbnQudG9TZWNvbmRzKCkgPCBvcmlnaW5hbFBlcmlvZC50b1NlY29uZHMoKSkge1xuICAgICAgcmV0dXJuIGN1cnJlbnQ7XG4gICAgfVxuICB9XG4gIHJldHVybiB1bmRlZmluZWQ7XG59XG4iXX0=