cdk-monitoring-constructs
Version:
[](https://badge.fury.io/js/cdk-monitoring-constructs) [](https://m
258 lines • 50.2 kB
JavaScript
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.DynamoTableMonitoring = void 0;
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
const aws_dynamodb_1 = require("aws-cdk-lib/aws-dynamodb");
const DynamoTableMetricFactory_1 = require("./DynamoTableMetricFactory");
const common_1 = require("../../common");
const dashboard_1 = require("../../dashboard");
class DynamoTableMonitoring extends common_1.Monitoring {
constructor(scope, props) {
super(scope, props);
const namingStrategy = new dashboard_1.MonitoringNamingStrategy({
...props,
namedConstruct: props.table,
fallbackConstructName: this.resolveTableName(props.table),
});
this.title = namingStrategy.resolveHumanReadableName();
this.tableUrl = scope
.createAwsConsoleUrlFactory()
.getDynamoTableUrl(props.table.tableName);
this.tableBillingMode =
props.billingMode ?? this.resolveTableBillingMode(props.table);
this.alarmFactory = this.createAlarmFactory(namingStrategy.resolveAlarmFriendlyName());
this.errorAlarmFactory = new common_1.ErrorAlarmFactory(this.alarmFactory);
this.latencyAlarmFactory = new common_1.LatencyAlarmFactory(this.alarmFactory);
this.dynamoCapacityAlarmFactory = new common_1.DynamoAlarmFactory(this.alarmFactory);
this.usageAlarmFactory = new common_1.UsageAlarmFactory(this.alarmFactory);
this.errorCountAnnotations = [];
this.latencyAnnotations = [];
this.dynamoReadCapacityAnnotations = [];
this.dynamoWriteCapacityAnnotations = [];
this.throttledEventsAnnotations = [];
const metricFactory = new DynamoTableMetricFactory_1.DynamoTableMetricFactory(scope.createMetricFactory(), props);
this.provisionedReadUnitsMetric =
metricFactory.metricProvisionedReadCapacityUnits();
this.provisionedWriteUnitsMetric =
metricFactory.metricProvisionedWriteCapacityUnits();
this.consumedReadUnitsMetric =
metricFactory.metricConsumedReadCapacityUnits();
this.consumedWriteUnitsMetric =
metricFactory.metricConsumedWriteCapacityUnits();
this.readThrottleCountMetric =
metricFactory.metricThrottledReadRequestCount();
this.writeThrottleCountMetric =
metricFactory.metricThrottledWriteRequestCount();
this.systemErrorMetric = metricFactory.metricSystemErrorsCount();
this.timeToLiveDeletedItemCountMetric =
metricFactory.metricTimeToLiveDeletedItemCount();
this.latencyAverageSearchMetrics =
metricFactory.metricSearchAverageSuccessfulRequestLatencyInMillis();
this.averagePerOperationLatencyMetrics = {
[aws_dynamodb_1.Operation.GET_RECORDS]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.GET_RECORDS),
[aws_dynamodb_1.Operation.QUERY]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.QUERY),
[aws_dynamodb_1.Operation.SCAN]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.SCAN),
[aws_dynamodb_1.Operation.PUT_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.PUT_ITEM),
[aws_dynamodb_1.Operation.GET_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.GET_ITEM),
[aws_dynamodb_1.Operation.UPDATE_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.UPDATE_ITEM),
[aws_dynamodb_1.Operation.DELETE_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.DELETE_ITEM),
[aws_dynamodb_1.Operation.BATCH_GET_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.BATCH_GET_ITEM),
[aws_dynamodb_1.Operation.BATCH_WRITE_ITEM]: metricFactory.metricAverageSuccessfulRequestLatencyInMillis(aws_dynamodb_1.Operation.BATCH_WRITE_ITEM),
};
this.readCapacityUsageMetric =
metricFactory.metricReadCapacityUtilizationPercentage();
this.writeCapacityUsageMetric =
metricFactory.metricWriteCapacityUtilizationPercentage();
for (const disambiguator in props.addConsumedReadCapacityAlarm) {
const alarmProps = props.addConsumedReadCapacityAlarm[disambiguator];
const createdAlarm = this.dynamoCapacityAlarmFactory.addConsumedCapacityAlarm(this.consumedReadUnitsMetric, common_1.CapacityType.READ, alarmProps, disambiguator);
this.dynamoReadCapacityAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addConsumedWriteCapacityAlarm) {
const alarmProps = props.addConsumedWriteCapacityAlarm[disambiguator];
const createdAlarm = this.dynamoCapacityAlarmFactory.addConsumedCapacityAlarm(this.consumedWriteUnitsMetric, common_1.CapacityType.WRITE, alarmProps, disambiguator);
this.dynamoWriteCapacityAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addReadThrottledEventsCountAlarm) {
const alarmProps = props.addReadThrottledEventsCountAlarm[disambiguator];
const createdAlarm = this.dynamoCapacityAlarmFactory.addThrottledEventsAlarm(this.readThrottleCountMetric, common_1.CapacityType.READ, alarmProps, disambiguator);
this.throttledEventsAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addWriteThrottledEventsCountAlarm) {
const alarmProps = props.addWriteThrottledEventsCountAlarm[disambiguator];
const createdAlarm = this.dynamoCapacityAlarmFactory.addThrottledEventsAlarm(this.writeThrottleCountMetric, common_1.CapacityType.WRITE, alarmProps, disambiguator);
this.throttledEventsAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addSystemErrorCountAlarm) {
const alarmProps = props.addSystemErrorCountAlarm[disambiguator];
const createdAlarm = this.errorAlarmFactory.addErrorCountAlarm(this.systemErrorMetric, common_1.ErrorType.SYSTEM_ERROR, alarmProps, disambiguator);
this.errorCountAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
for (const disambiguator in props.addMinTimeToLiveDeletedItemCountAlarm) {
const alarmProps = {
// Missing data is bad if we expect TTL to be enabled
treatMissingDataOverride: aws_cloudwatch_1.TreatMissingData.BREACHING,
...props.addMinTimeToLiveDeletedItemCountAlarm[disambiguator],
};
const createdAlarm = this.usageAlarmFactory.addMinCountAlarm(this.timeToLiveDeletedItemCountMetric, alarmProps, disambiguator);
this.addAlarm(createdAlarm);
}
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.GET_RECORDS, props.addAverageSuccessfulGetRecordsLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.QUERY, props.addAverageSuccessfulQueryLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.SCAN, props.addAverageSuccessfulScanLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.PUT_ITEM, props.addAverageSuccessfulPutItemLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.GET_ITEM, props.addAverageSuccessfulGetItemLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.UPDATE_ITEM, props.addAverageSuccessfulUpdateItemLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.DELETE_ITEM, props.addAverageSuccessfulDeleteItemLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.BATCH_GET_ITEM, props.addAverageSuccessfulBatchGetItemLatencyAlarm);
this.forEachOperationLatencyAlarmDefinition(aws_dynamodb_1.Operation.BATCH_WRITE_ITEM, props.addAverageSuccessfulBatchWriteItemLatencyAlarm);
props.useCreatedAlarms?.consume(this.createdAlarms());
}
forEachOperationLatencyAlarmDefinition(operation, alarm) {
for (const disambiguator in alarm) {
const alarmProps = alarm[disambiguator];
const createdAlarm = this.latencyAlarmFactory.addLatencyAlarm(
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
this.averagePerOperationLatencyMetrics[operation], common_1.LatencyType.AVERAGE, alarmProps, disambiguator, operation);
this.latencyAnnotations.push(createdAlarm.annotation);
this.addAlarm(createdAlarm);
}
}
summaryWidgets() {
return [
// Title
this.createTitleWidget(),
// Read units
this.createReadCapacityWidget(common_1.HalfWidth, common_1.DefaultSummaryWidgetHeight),
// Write units
this.createWriteCapacityWidget(common_1.HalfWidth, common_1.DefaultSummaryWidgetHeight),
];
}
widgets() {
return [
// Title
this.createTitleWidget(),
new aws_cloudwatch_1.Column(
// Read units
this.createReadCapacityWidget(common_1.QuarterWidth, common_1.DefaultTwoLinerGraphWidgetHalfHeight),
// Write units
this.createWriteCapacityWidget(common_1.QuarterWidth, common_1.DefaultTwoLinerGraphWidgetHalfHeight)),
// Latency
this.createLatencyWidget(common_1.QuarterWidth + common_1.HalfQuarterWidth, common_1.DefaultTwoLinerGraphWidgetHeight),
// Throttles
this.createThrottlesWidget(common_1.HalfQuarterWidth, common_1.DefaultTwoLinerGraphWidgetHeight),
// Errors
this.createErrorsWidget(common_1.QuarterWidth, common_1.DefaultTwoLinerGraphWidgetHeight),
];
}
createLatencyWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Latency (Average)",
left: [this.latencyAverageSearchMetrics],
leftYAxis: common_1.TimeAxisMillisFromZero,
leftAnnotations: this.latencyAnnotations,
legendPosition: aws_cloudwatch_1.LegendPosition.RIGHT,
});
}
createThrottlesWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Throttles",
left: [this.readThrottleCountMetric, this.writeThrottleCountMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.throttledEventsAnnotations,
});
}
createErrorsWidget(width, height) {
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Errors",
left: [this.systemErrorMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.errorCountAnnotations,
});
}
createReadCapacityWidget(width, height) {
if (this.tableBillingMode === aws_dynamodb_1.BillingMode.PAY_PER_REQUEST) {
// simplified view for on-demand table
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Read Usage",
left: [this.consumedReadUnitsMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.dynamoReadCapacityAnnotations,
});
}
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Read Usage",
left: [this.consumedReadUnitsMetric, this.provisionedReadUnitsMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.dynamoReadCapacityAnnotations,
right: [this.readCapacityUsageMetric],
rightYAxis: common_1.PercentageAxisFromZeroToHundred,
legendPosition: aws_cloudwatch_1.LegendPosition.RIGHT,
});
}
createWriteCapacityWidget(width, height) {
if (this.tableBillingMode === aws_dynamodb_1.BillingMode.PAY_PER_REQUEST) {
// simplified view for on-demand table
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Write Usage",
left: [this.consumedWriteUnitsMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.dynamoWriteCapacityAnnotations,
});
}
return new aws_cloudwatch_1.GraphWidget({
width,
height,
title: "Write Usage",
left: [this.consumedWriteUnitsMetric, this.provisionedWriteUnitsMetric],
leftYAxis: common_1.CountAxisFromZero,
leftAnnotations: this.dynamoWriteCapacityAnnotations,
right: [this.writeCapacityUsageMetric],
rightYAxis: common_1.PercentageAxisFromZeroToHundred,
legendPosition: aws_cloudwatch_1.LegendPosition.RIGHT,
});
}
createTitleWidget() {
return new dashboard_1.MonitoringHeaderWidget({
family: "Dynamo Table",
title: this.title,
goToLinkUrl: this.tableUrl,
});
}
resolveTableName(dynamoTable) {
// try to take the name (if specified) instead of token
return dynamoTable.node.defaultChild?.tableName;
}
resolveTableBillingMode(dynamoTable) {
const billingMode = dynamoTable.node.defaultChild
?.billingMode;
if (billingMode) {
return billingMode;
}
// fallback to default (for backwards compatibility)
return aws_dynamodb_1.BillingMode.PROVISIONED;
}
}
exports.DynamoTableMonitoring = DynamoTableMonitoring;
_a = JSII_RTTI_SYMBOL_1;
DynamoTableMonitoring[_a] = { fqn: "cdk-monitoring-constructs.DynamoTableMonitoring", version: "10.0.0" };
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRHluYW1vVGFibGVNb25pdG9yaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiRHluYW1vVGFibGVNb25pdG9yaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7O0FBQUEsK0RBUW9DO0FBQ3BDLDJEQUtrQztBQUVsQyx5RUFHb0M7QUFDcEMseUNBMkJzQjtBQUN0QiwrQ0FHeUI7QUFxRXpCLE1BQWEscUJBQXNCLFNBQVEsbUJBQVU7SUFrQ25ELFlBQVksS0FBc0IsRUFBRSxLQUFpQztRQUNuRSxLQUFLLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBRXBCLE1BQU0sY0FBYyxHQUFHLElBQUksb0NBQXdCLENBQUM7WUFDbEQsR0FBRyxLQUFLO1lBQ1IsY0FBYyxFQUFFLEtBQUssQ0FBQyxLQUFLO1lBQzNCLHFCQUFxQixFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO1NBQzFELENBQUMsQ0FBQztRQUVILElBQUksQ0FBQyxLQUFLLEdBQUcsY0FBYyxDQUFDLHdCQUF3QixFQUFFLENBQUM7UUFDdkQsSUFBSSxDQUFDLFFBQVEsR0FBRyxLQUFLO2FBQ2xCLDBCQUEwQixFQUFFO2FBQzVCLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUM7UUFFNUMsSUFBSSxDQUFDLGdCQUFnQjtZQUNuQixLQUFLLENBQUMsV0FBVyxJQUFJLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFakUsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsa0JBQWtCLENBQ3pDLGNBQWMsQ0FBQyx3QkFBd0IsRUFBRSxDQUMxQyxDQUFDO1FBQ0YsSUFBSSxDQUFDLGlCQUFpQixHQUFHLElBQUksMEJBQWlCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ2xFLElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLDRCQUFtQixDQUFD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cEQsT0FBTywwQkFBVyxDQUFDLFdBQVcsQ0FBQztJQUNqQyxDQUFDOztBQXRaSCxzREF1WkMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb2x1bW4sXG4gIEdyYXBoV2lkZ2V0LFxuICBIb3Jpem9udGFsQW5ub3RhdGlvbixcbiAgSU1ldHJpYyxcbiAgSVdpZGdldCxcbiAgTGVnZW5kUG9zaXRpb24sXG4gIFRyZWF0TWlzc2luZ0RhdGEsXG59IGZyb20gXCJhd3MtY2RrLWxpYi9hd3MtY2xvdWR3YXRjaFwiO1xuaW1wb3J0IHtcbiAgQmlsbGluZ01vZGUsXG4gIENmblRhYmxlLFxuICBJVGFibGUsXG4gIE9wZXJhdGlvbixcbn0gZnJvbSBcImF3cy1jZGstbGliL2F3cy1keW5hbW9kYlwiO1xuXG5pbXBvcnQge1xuICBEeW5hbW9UYWJsZU1ldHJpY0ZhY3RvcnksXG4gIER5bmFtb1RhYmxlTWV0cmljRmFjdG9yeVByb3BzLFxufSBmcm9tIFwiLi9EeW5hbW9UYWJsZU1ldHJpY0ZhY3RvcnlcIjtcbmltcG9ydCB7XG4gIEFsYXJtRmFjdG9yeSxcbiAgQmFzZU1vbml0b3JpbmdQcm9wcyxcbiAgQ2FwYWNpdHlUeXBlLFxuICBDb25zdW1lZENhcGFjaXR5VGhyZXNob2xkLFxuICBDb3VudEF4aXNGcm9tWmVybyxcbiAgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQsXG4gIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGFsZkhlaWdodCxcbiAgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIZWlnaHQsXG4gIER5bmFtb0FsYXJtRmFjdG9yeSxcbiAgRXJyb3JBbGFybUZhY3RvcnksXG4gIEVycm9yQ291bnRUaHJlc2hvbGQsXG4gIEVycm9yVHlwZSxcbiAgSGFsZlF1YXJ0ZXJXaWR0aCxcbiAgSGFsZldpZHRoLFxuICBMYXRlbmN5QWxhcm1GYWN0b3J5LFxuICBMYXRlbmN5VGhyZXNob2xkLFxuICBMYXRlbmN5VHlwZSxcbiAgTWV0cmljV2l0aEFsYXJtU3VwcG9ydCxcbiAgTWluVXNhZ2VDb3VudFRocmVzaG9sZCxcbiAgTW9uaXRvcmluZyxcbiAgTW9uaXRvcmluZ1Njb3BlLFxuICBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICBRdWFydGVyV2lkdGgsXG4gIFRocm90dGxlZEV2ZW50c1RocmVzaG9sZCxcbiAgVGltZUF4aXNNaWxsaXNGcm9tWmVybyxcbiAgVXNhZ2VBbGFybUZhY3RvcnksXG59IGZyb20gXCIuLi8uLi9jb21tb25cIjtcbmltcG9ydCB7XG4gIE1vbml0b3JpbmdIZWFkZXJXaWRnZXQsXG4gIE1vbml0b3JpbmdOYW1pbmdTdHJhdGVneSxcbn0gZnJvbSBcIi4uLy4uL2Rhc2hib2FyZFwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIER5bmFtb1RhYmxlTW9uaXRvcmluZ09wdGlvbnMgZXh0ZW5kcyBCYXNlTW9uaXRvcmluZ1Byb3BzIHtcbiAgcmVhZG9ubHkgYWRkQ29uc3VtZWRSZWFkQ2FwYWNpdHlBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgQ29uc3VtZWRDYXBhY2l0eVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRDb25zdW1lZFdyaXRlQ2FwYWNpdHlBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgQ29uc3VtZWRDYXBhY2l0eVRocmVzaG9sZFxuICA+O1xuXG4gIHJlYWRvbmx5IGFkZFJlYWRUaHJvdHRsZWRFdmVudHNDb3VudEFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBUaHJvdHRsZWRFdmVudHNUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkV3JpdGVUaHJvdHRsZWRFdmVudHNDb3VudEFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBUaHJvdHRsZWRFdmVudHNUaHJlc2hvbGRcbiAgPjtcblxuICByZWFkb25seSBhZGRTeXN0ZW1FcnJvckNvdW50QWxhcm0/OiBSZWNvcmQ8c3RyaW5nLCBFcnJvckNvdW50VGhyZXNob2xkPjtcbiAgcmVhZG9ubHkgYWRkTWluVGltZVRvTGl2ZURlbGV0ZWRJdGVtQ291bnRBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTWluVXNhZ2VDb3VudFRocmVzaG9sZFxuICA+O1xuXG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsR2V0UmVjb3Jkc0xhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bFF1ZXJ5TGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsU2NhbkxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bFB1dEl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxHZXRJdGVtTGF0ZW5jeUFsYXJtPzogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBMYXRlbmN5VGhyZXNob2xkXG4gID47XG4gIHJlYWRvbmx5IGFkZEF2ZXJhZ2VTdWNjZXNzZnVsVXBkYXRlSXRlbUxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xuICByZWFkb25seSBhZGRBdmVyYWdlU3VjY2Vzc2Z1bERlbGV0ZUl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxCYXRjaEdldEl0ZW1MYXRlbmN5QWxhcm0/OiBSZWNvcmQ8XG4gICAgc3RyaW5nLFxuICAgIExhdGVuY3lUaHJlc2hvbGRcbiAgPjtcbiAgcmVhZG9ubHkgYWRkQXZlcmFnZVN1Y2Nlc3NmdWxCYXRjaFdyaXRlSXRlbUxhdGVuY3lBbGFybT86IFJlY29yZDxcbiAgICBzdHJpbmcsXG4gICAgTGF0ZW5jeVRocmVzaG9sZFxuICA+O1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIER5bmFtb1RhYmxlTW9uaXRvcmluZ1Byb3BzXG4gIGV4dGVuZHMgRHluYW1vVGFibGVNZXRyaWNGYWN0b3J5UHJvcHMsXG4gICAgRHluYW1vVGFibGVNb25pdG9yaW5nT3B0aW9ucyB7fVxuXG5leHBvcnQgY2xhc3MgRHluYW1vVGFibGVNb25pdG9yaW5nIGV4dGVuZHMgTW9uaXRvcmluZyB7XG4gIHJlYWRvbmx5IHRpdGxlOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHRhYmxlVXJsPzogc3RyaW5nO1xuICByZWFkb25seSB0YWJsZUJpbGxpbmdNb2RlOiBCaWxsaW5nTW9kZTtcblxuICByZWFkb25seSBhbGFybUZhY3Rvcnk6IEFsYXJtRmFjdG9yeTtcbiAgcmVhZG9ubHkgZXJyb3JBbGFybUZhY3Rvcnk6IEVycm9yQWxhcm1GYWN0b3J5O1xuICByZWFkb25seSBsYXRlbmN5QWxhcm1GYWN0b3J5OiBMYXRlbmN5QWxhcm1GYWN0b3J5O1xuICByZWFkb25seSBkeW5hbW9DYXBhY2l0eUFsYXJtRmFjdG9yeTogRHluYW1vQWxhcm1GYWN0b3J5O1xuICByZWFkb25seSB1c2FnZUFsYXJtRmFjdG9yeTogVXNhZ2VBbGFybUZhY3Rvcnk7XG5cbiAgcmVhZG9ubHkgbGF0ZW5jeUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSBlcnJvckNvdW50QW5ub3RhdGlvbnM6IEhvcml6b250YWxBbm5vdGF0aW9uW107XG4gIHJlYWRvbmx5IGR5bmFtb1JlYWRDYXBhY2l0eUFubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuICByZWFkb25seSBkeW5hbW9Xcml0ZUNhcGFjaXR5QW5ub3RhdGlvbnM6IEhvcml6b250YWxBbm5vdGF0aW9uW107XG4gIHJlYWRvbmx5IHRocm90dGxlZEV2ZW50c0Fubm90YXRpb25zOiBIb3Jpem9udGFsQW5ub3RhdGlvbltdO1xuXG4gIHJlYWRvbmx5IHByb3Zpc2lvbmVkUmVhZFVuaXRzTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBwcm92aXNpb25lZFdyaXRlVW5pdHNNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IGNvbnN1bWVkUmVhZFVuaXRzTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSBjb25zdW1lZFdyaXRlVW5pdHNNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IHJlYWRUaHJvdHRsZUNvdW50TWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSB3cml0ZVRocm90dGxlQ291bnRNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG4gIHJlYWRvbmx5IHN5c3RlbUVycm9yTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSB0aW1lVG9MaXZlRGVsZXRlZEl0ZW1Db3VudE1ldHJpYzogTWV0cmljV2l0aEFsYXJtU3VwcG9ydDtcbiAgcmVhZG9ubHkgbGF0ZW5jeUF2ZXJhZ2VTZWFyY2hNZXRyaWNzOiBJTWV0cmljO1xuICAvLyBrZXlzIGFyZSBPcGVyYXRpb24sIGJ1dCBKU0lJIGRvZXNuJ3QgbGlrZSBub24tc3RyaW5nIHR5cGVzXG4gIHJlYWRvbmx5IGF2ZXJhZ2VQZXJPcGVyYXRpb25MYXRlbmN5TWV0cmljczogUmVjb3JkPFxuICAgIHN0cmluZyxcbiAgICBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0XG4gID47XG4gIHJlYWRvbmx5IHJlYWRDYXBhY2l0eVVzYWdlTWV0cmljOiBNZXRyaWNXaXRoQWxhcm1TdXBwb3J0O1xuICByZWFkb25seSB3cml0ZUNhcGFjaXR5VXNhZ2VNZXRyaWM6IE1ldHJpY1dpdGhBbGFybVN1cHBvcnQ7XG5cbiAgY29uc3RydWN0b3Ioc2NvcGU6IE1vbml0b3JpbmdTY29wZSwgcHJvcHM6IER5bmFtb1RhYmxlTW9uaXRvcmluZ1Byb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIHByb3BzKTtcblxuICAgIGNvbnN0IG5hbWluZ1N0cmF0ZWd5ID0gbmV3IE1vbml0b3JpbmdOYW1pbmdTdHJhdGVneSh7XG4gICAgICAuLi5wcm9wcyxcbiAgICAgIG5hbWVkQ29uc3RydWN0OiBwcm9wcy50YWJsZSxcbiAgICAgIGZhbGxiYWNrQ29uc3RydWN0TmFtZTogdGhpcy5yZXNvbHZlVGFibGVOYW1lKHByb3BzLnRhYmxlKSxcbiAgICB9KTtcblxuICAgIHRoaXMudGl0bGUgPSBuYW1pbmdTdHJhdGVneS5yZXNvbHZlSHVtYW5SZWFkYWJsZU5hbWUoKTtcbiAgICB0aGlzLnRhYmxlVXJsID0gc2NvcGVcbiAgICAgIC5jcmVhdGVBd3NDb25zb2xlVXJsRmFjdG9yeSgpXG4gICAgICAuZ2V0RHluYW1vVGFibGVVcmwocHJvcHMudGFibGUudGFibGVOYW1lKTtcblxuICAgIHRoaXMudGFibGVCaWxsaW5nTW9kZSA9XG4gICAgICBwcm9wcy5iaWxsaW5nTW9kZSA/PyB0aGlzLnJlc29sdmVUYWJsZUJpbGxpbmdNb2RlKHByb3BzLnRhYmxlKTtcblxuICAgIHRoaXMuYWxhcm1GYWN0b3J5ID0gdGhpcy5jcmVhdGVBbGFybUZhY3RvcnkoXG4gICAgICBuYW1pbmdTdHJhdGVneS5yZXNvbHZlQWxhcm1GcmllbmRseU5hbWUoKSxcbiAgICApO1xuICAgIHRoaXMuZXJyb3JBbGFybUZhY3RvcnkgPSBuZXcgRXJyb3JBbGFybUZhY3RvcnkodGhpcy5hbGFybUZhY3RvcnkpO1xuICAgIHRoaXMubGF0ZW5jeUFsYXJtRmFjdG9yeSA9IG5ldyBMYXRlbmN5QWxhcm1GYWN0b3J5KHRoaXMuYWxhcm1GYWN0b3J5KTtcbiAgICB0aGlzLmR5bmFtb0NhcGFjaXR5QWxhcm1GYWN0b3J5ID0gbmV3IER5bmFtb0FsYXJtRmFjdG9yeSh0aGlzLmFsYXJtRmFjdG9yeSk7XG4gICAgdGhpcy51c2FnZUFsYXJtRmFjdG9yeSA9IG5ldyBVc2FnZUFsYXJtRmFjdG9yeSh0aGlzLmFsYXJtRmFjdG9yeSk7XG5cbiAgICB0aGlzLmVycm9yQ291bnRBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMubGF0ZW5jeUFubm90YXRpb25zID0gW107XG4gICAgdGhpcy5keW5hbW9SZWFkQ2FwYWNpdHlBbm5vdGF0aW9ucyA9IFtdO1xuICAgIHRoaXMuZHluYW1vV3JpdGVDYXBhY2l0eUFubm90YXRpb25zID0gW107XG4gICAgdGhpcy50aHJvdHRsZWRFdmVudHNBbm5vdGF0aW9ucyA9IFtdO1xuXG4gICAgY29uc3QgbWV0cmljRmFjdG9yeSA9IG5ldyBEeW5hbW9UYWJsZU1ldHJpY0ZhY3RvcnkoXG4gICAgICBzY29wZS5jcmVhdGVNZXRyaWNGYWN0b3J5KCksXG4gICAgICBwcm9wcyxcbiAgICApO1xuICAgIHRoaXMucHJvdmlzaW9uZWRSZWFkVW5pdHNNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNQcm92aXNpb25lZFJlYWRDYXBhY2l0eVVuaXRzKCk7XG4gICAgdGhpcy5wcm92aXNpb25lZFdyaXRlVW5pdHNNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNQcm92aXNpb25lZFdyaXRlQ2FwYWNpdHlVbml0cygpO1xuICAgIHRoaXMuY29uc3VtZWRSZWFkVW5pdHNNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNDb25zdW1lZFJlYWRDYXBhY2l0eVVuaXRzKCk7XG4gICAgdGhpcy5jb25zdW1lZFdyaXRlVW5pdHNNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNDb25zdW1lZFdyaXRlQ2FwYWNpdHlVbml0cygpO1xuICAgIHRoaXMucmVhZFRocm90dGxlQ291bnRNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNUaHJvdHRsZWRSZWFkUmVxdWVzdENvdW50KCk7XG4gICAgdGhpcy53cml0ZVRocm90dGxlQ291bnRNZXRyaWMgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNUaHJvdHRsZWRXcml0ZVJlcXVlc3RDb3VudCgpO1xuICAgIHRoaXMuc3lzdGVtRXJyb3JNZXRyaWMgPSBtZXRyaWNGYWN0b3J5Lm1ldHJpY1N5c3RlbUVycm9yc0NvdW50KCk7XG4gICAgdGhpcy50aW1lVG9MaXZlRGVsZXRlZEl0ZW1Db3VudE1ldHJpYyA9XG4gICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY1RpbWVUb0xpdmVEZWxldGVkSXRlbUNvdW50KCk7XG4gICAgdGhpcy5sYXRlbmN5QXZlcmFnZVNlYXJjaE1ldHJpY3MgPVxuICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNTZWFyY2hBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoKTtcbiAgICB0aGlzLmF2ZXJhZ2VQZXJPcGVyYXRpb25MYXRlbmN5TWV0cmljcyA9IHtcbiAgICAgIFtPcGVyYXRpb24uR0VUX1JFQ09SRFNdOlxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lJbk1pbGxpcyhcbiAgICAgICAgICBPcGVyYXRpb24uR0VUX1JFQ09SRFMsXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLlFVRVJZXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLlFVRVJZLFxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5TQ0FOXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLlNDQU4sXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLlBVVF9JVEVNXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLlBVVF9JVEVNLFxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5HRVRfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5HRVRfSVRFTSxcbiAgICAgICAgKSxcbiAgICAgIFtPcGVyYXRpb24uVVBEQVRFX0lURU1dOlxuICAgICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY0F2ZXJhZ2VTdWNjZXNzZnVsUmVxdWVzdExhdGVuY3lJbk1pbGxpcyhcbiAgICAgICAgICBPcGVyYXRpb24uVVBEQVRFX0lURU0sXG4gICAgICAgICksXG4gICAgICBbT3BlcmF0aW9uLkRFTEVURV9JVEVNXTpcbiAgICAgICAgbWV0cmljRmFjdG9yeS5tZXRyaWNBdmVyYWdlU3VjY2Vzc2Z1bFJlcXVlc3RMYXRlbmN5SW5NaWxsaXMoXG4gICAgICAgICAgT3BlcmF0aW9uLkRFTEVURV9JVEVNLFxuICAgICAgICApLFxuICAgICAgW09wZXJhdGlvbi5CQVRDSF9HRVRfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5CQVRDSF9HRVRfSVRFTSxcbiAgICAgICAgKSxcbiAgICAgIFtPcGVyYXRpb24uQkFUQ0hfV1JJVEVfSVRFTV06XG4gICAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljQXZlcmFnZVN1Y2Nlc3NmdWxSZXF1ZXN0TGF0ZW5jeUluTWlsbGlzKFxuICAgICAgICAgIE9wZXJhdGlvbi5CQVRDSF9XUklURV9JVEVNLFxuICAgICAgICApLFxuICAgIH07XG4gICAgdGhpcy5yZWFkQ2FwYWNpdHlVc2FnZU1ldHJpYyA9XG4gICAgICBtZXRyaWNGYWN0b3J5Lm1ldHJpY1JlYWRDYXBhY2l0eVV0aWxpemF0aW9uUGVyY2VudGFnZSgpO1xuICAgIHRoaXMud3JpdGVDYXBhY2l0eVVzYWdlTWV0cmljID1cbiAgICAgIG1ldHJpY0ZhY3RvcnkubWV0cmljV3JpdGVDYXBhY2l0eVV0aWxpemF0aW9uUGVyY2VudGFnZSgpO1xuXG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZENvbnN1bWVkUmVhZENhcGFjaXR5QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRDb25zdW1lZFJlYWRDYXBhY2l0eUFsYXJtW2Rpc2FtYmlndWF0b3JdO1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID1cbiAgICAgICAgdGhpcy5keW5hbW9DYXBhY2l0eUFsYXJtRmFjdG9yeS5hZGRDb25zdW1lZENhcGFjaXR5QWxhcm0oXG4gICAgICAgICAgdGhpcy5jb25zdW1lZFJlYWRVbml0c01ldHJpYyxcbiAgICAgICAgICBDYXBhY2l0eVR5cGUuUkVBRCxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICk7XG4gICAgICB0aGlzLmR5bmFtb1JlYWRDYXBhY2l0eUFubm90YXRpb25zLnB1c2goY3JlYXRlZEFsYXJtLmFubm90YXRpb24pO1xuICAgICAgdGhpcy5hZGRBbGFybShjcmVhdGVkQWxhcm0pO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gcHJvcHMuYWRkQ29uc3VtZWRXcml0ZUNhcGFjaXR5QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRDb25zdW1lZFdyaXRlQ2FwYWNpdHlBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuZHluYW1vQ2FwYWNpdHlBbGFybUZhY3RvcnkuYWRkQ29uc3VtZWRDYXBhY2l0eUFsYXJtKFxuICAgICAgICAgIHRoaXMuY29uc3VtZWRXcml0ZVVuaXRzTWV0cmljLFxuICAgICAgICAgIENhcGFjaXR5VHlwZS5XUklURSxcbiAgICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICAgIGRpc2FtYmlndWF0b3IsXG4gICAgICAgICk7XG4gICAgICB0aGlzLmR5bmFtb1dyaXRlQ2FwYWNpdHlBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZFJlYWRUaHJvdHRsZWRFdmVudHNDb3VudEFsYXJtKSB7XG4gICAgICBjb25zdCBhbGFybVByb3BzID0gcHJvcHMuYWRkUmVhZFRocm90dGxlZEV2ZW50c0NvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPVxuICAgICAgICB0aGlzLmR5bmFtb0NhcGFjaXR5QWxhcm1GYWN0b3J5LmFkZFRocm90dGxlZEV2ZW50c0FsYXJtKFxuICAgICAgICAgIHRoaXMucmVhZFRocm90dGxlQ291bnRNZXRyaWMsXG4gICAgICAgICAgQ2FwYWNpdHlUeXBlLlJFQUQsXG4gICAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICApO1xuICAgICAgdGhpcy50aHJvdHRsZWRFdmVudHNBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZFdyaXRlVGhyb3R0bGVkRXZlbnRzQ291bnRBbGFybSkge1xuICAgICAgY29uc3QgYWxhcm1Qcm9wcyA9IHByb3BzLmFkZFdyaXRlVGhyb3R0bGVkRXZlbnRzQ291bnRBbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9XG4gICAgICAgIHRoaXMuZHluYW1vQ2FwYWNpdHlBbGFybUZhY3RvcnkuYWRkVGhyb3R0bGVkRXZlbnRzQWxhcm0oXG4gICAgICAgICAgdGhpcy53cml0ZVRocm90dGxlQ291bnRNZXRyaWMsXG4gICAgICAgICAgQ2FwYWNpdHlUeXBlLldSSVRFLFxuICAgICAgICAgIGFsYXJtUHJvcHMsXG4gICAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICAgKTtcbiAgICAgIHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICAgIGZvciAoY29uc3QgZGlzYW1iaWd1YXRvciBpbiBwcm9wcy5hZGRTeXN0ZW1FcnJvckNvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBwcm9wcy5hZGRTeXN0ZW1FcnJvckNvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl07XG4gICAgICBjb25zdCBjcmVhdGVkQWxhcm0gPSB0aGlzLmVycm9yQWxhcm1GYWN0b3J5LmFkZEVycm9yQ291bnRBbGFybShcbiAgICAgICAgdGhpcy5zeXN0ZW1FcnJvck1ldHJpYyxcbiAgICAgICAgRXJyb3JUeXBlLlNZU1RFTV9FUlJPUixcbiAgICAgICAgYWxhcm1Qcm9wcyxcbiAgICAgICAgZGlzYW1iaWd1YXRvcixcbiAgICAgICk7XG4gICAgICB0aGlzLmVycm9yQ291bnRBbm5vdGF0aW9ucy5wdXNoKGNyZWF0ZWRBbGFybS5hbm5vdGF0aW9uKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBkaXNhbWJpZ3VhdG9yIGluIHByb3BzLmFkZE1pblRpbWVUb0xpdmVEZWxldGVkSXRlbUNvdW50QWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSB7XG4gICAgICAgIC8vIE1pc3NpbmcgZGF0YSBpcyBiYWQgaWYgd2UgZXhwZWN0IFRUTCB0byBiZSBlbmFibGVkXG4gICAgICAgIHRyZWF0TWlzc2luZ0RhdGFPdmVycmlkZTogVHJlYXRNaXNzaW5nRGF0YS5CUkVBQ0hJTkcsXG4gICAgICAgIC4uLnByb3BzLmFkZE1pblRpbWVUb0xpdmVEZWxldGVkSXRlbUNvdW50QWxhcm1bZGlzYW1iaWd1YXRvcl0sXG4gICAgICB9O1xuICAgICAgY29uc3QgY3JlYXRlZEFsYXJtID0gdGhpcy51c2FnZUFsYXJtRmFjdG9yeS5hZGRNaW5Db3VudEFsYXJtKFxuICAgICAgICB0aGlzLnRpbWVUb0xpdmVEZWxldGVkSXRlbUNvdW50TWV0cmljLFxuICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgKTtcbiAgICAgIHRoaXMuYWRkQWxhcm0oY3JlYXRlZEFsYXJtKTtcbiAgICB9XG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICAgIE9wZXJhdGlvbi5HRVRfUkVDT1JEUyxcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsR2V0UmVjb3Jkc0xhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uUVVFUlksXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bFF1ZXJ5TGF0ZW5jeUFsYXJtLFxuICAgICk7XG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICAgIE9wZXJhdGlvbi5TQ0FOLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxTY2FuTGF0ZW5jeUFsYXJtLFxuICAgICk7XG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICAgIE9wZXJhdGlvbi5QVVRfSVRFTSxcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsUHV0SXRlbUxhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uR0VUX0lURU0sXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bEdldEl0ZW1MYXRlbmN5QWxhcm0sXG4gICAgKTtcbiAgICB0aGlzLmZvckVhY2hPcGVyYXRpb25MYXRlbmN5QWxhcm1EZWZpbml0aW9uKFxuICAgICAgT3BlcmF0aW9uLlVQREFURV9JVEVNLFxuICAgICAgcHJvcHMuYWRkQXZlcmFnZVN1Y2Nlc3NmdWxVcGRhdGVJdGVtTGF0ZW5jeUFsYXJtLFxuICAgICk7XG4gICAgdGhpcy5mb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICAgIE9wZXJhdGlvbi5ERUxFVEVfSVRFTSxcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsRGVsZXRlSXRlbUxhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uQkFUQ0hfR0VUX0lURU0sXG4gICAgICBwcm9wcy5hZGRBdmVyYWdlU3VjY2Vzc2Z1bEJhdGNoR2V0SXRlbUxhdGVuY3lBbGFybSxcbiAgICApO1xuICAgIHRoaXMuZm9yRWFjaE9wZXJhdGlvbkxhdGVuY3lBbGFybURlZmluaXRpb24oXG4gICAgICBPcGVyYXRpb24uQkFUQ0hfV1JJVEVfSVRFTSxcbiAgICAgIHByb3BzLmFkZEF2ZXJhZ2VTdWNjZXNzZnVsQmF0Y2hXcml0ZUl0ZW1MYXRlbmN5QWxhcm0sXG4gICAgKTtcbiAgICBwcm9wcy51c2VDcmVhdGVkQWxhcm1zPy5jb25zdW1lKHRoaXMuY3JlYXRlZEFsYXJtcygpKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBmb3JFYWNoT3BlcmF0aW9uTGF0ZW5jeUFsYXJtRGVmaW5pdGlvbihcbiAgICBvcGVyYXRpb246IE9wZXJhdGlvbixcbiAgICBhbGFybT86IFJlY29yZDxzdHJpbmcsIExhdGVuY3lUaHJlc2hvbGQ+LFxuICApIHtcbiAgICBmb3IgKGNvbnN0IGRpc2FtYmlndWF0b3IgaW4gYWxhcm0pIHtcbiAgICAgIGNvbnN0IGFsYXJtUHJvcHMgPSBhbGFybVtkaXNhbWJpZ3VhdG9yXTtcbiAgICAgIGNvbnN0IGNyZWF0ZWRBbGFybSA9IHRoaXMubGF0ZW5jeUFsYXJtRmFjdG9yeS5hZGRMYXRlbmN5QWxhcm0oXG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICAgIHRoaXMuYXZlcmFnZVBlck9wZXJhdGlvbkxhdGVuY3lNZXRyaWNzW29wZXJhdGlvbl0hLFxuICAgICAgICBMYXRlbmN5VHlwZS5BVkVSQUdFLFxuICAgICAgICBhbGFybVByb3BzLFxuICAgICAgICBkaXNhbWJpZ3VhdG9yLFxuICAgICAgICBvcGVyYXRpb24sXG4gICAgICApO1xuICAgICAgdGhpcy5sYXRlbmN5QW5ub3RhdGlvbnMucHVzaChjcmVhdGVkQWxhcm0uYW5ub3RhdGlvbik7XG4gICAgICB0aGlzLmFkZEFsYXJtKGNyZWF0ZWRBbGFybSk7XG4gICAgfVxuICB9XG5cbiAgc3VtbWFyeVdpZGdldHMoKTogSVdpZGdldFtdIHtcbiAgICByZXR1cm4gW1xuICAgICAgLy8gVGl0bGVcbiAgICAgIHRoaXMuY3JlYXRlVGl0bGVXaWRnZXQoKSxcbiAgICAgIC8vIFJlYWQgdW5pdHNcbiAgICAgIHRoaXMuY3JlYXRlUmVhZENhcGFjaXR5V2lkZ2V0KEhhbGZXaWR0aCwgRGVmYXVsdFN1bW1hcnlXaWRnZXRIZWlnaHQpLFxuICAgICAgLy8gV3JpdGUgdW5pdHNcbiAgICAgIHRoaXMuY3JlYXRlV3JpdGVDYXBhY2l0eVdpZGdldChIYWxmV2lkdGgsIERlZmF1bHRTdW1tYXJ5V2lkZ2V0SGVpZ2h0KSxcbiAgICBdO1xuICB9XG5cbiAgd2lkZ2V0cygpOiBJV2lkZ2V0W10ge1xuICAgIHJldHVybiBbXG4gICAgICAvLyBUaXRsZVxuICAgICAgdGhpcy5jcmVhdGVUaXRsZVdpZGdldCgpLFxuICAgICAgbmV3IENvbHVtbihcbiAgICAgICAgLy8gUmVhZCB1bml0c1xuICAgICAgICB0aGlzLmNyZWF0ZVJlYWRDYXBhY2l0eVdpZGdldChcbiAgICAgICAgICBRdWFydGVyV2lkdGgsXG4gICAgICAgICAgRGVmYXVsdFR3b0xpbmVyR3JhcGhXaWRnZXRIYWxmSGVpZ2h0LFxuICAgICAgICApLFxuICAgICAgICAvLyBXcml0ZSB1bml0c1xuICAgICAgICB0aGlzLmNyZWF0ZVdyaXRlQ2FwYWNpdHlXaWRnZXQoXG4gICAgICAgICAgUXVhcnRlcldpZHRoLFxuICAgICAgICAgIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGFsZkhlaWdodCxcbiAgICAgICAgKSxcbiAgICAgICksXG4gICAgICAvLyBMYXRlbmN5XG4gICAgICB0aGlzLmNyZWF0ZUxhdGVuY3lXaWRnZXQoXG4gICAgICAgIFF1YXJ0ZXJXaWR0aCArIEhhbGZRdWFydGVyV2lkdGgsXG4gICAgICAgIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGVpZ2h0LFxuICAgICAgKSxcbiAgICAgIC8vIFRocm90dGxlc1xuICAgICAgdGhpcy5jcmVhdGVUaHJvdHRsZXNXaWRnZXQoXG4gICAgICAgIEhhbGZRdWFydGVyV2lkdGgsXG4gICAgICAgIERlZmF1bHRUd29MaW5lckdyYXBoV2lkZ2V0SGVpZ2h0LFxuICAgICAgKSxcbiAgICAgIC8vIEVycm9yc1xuICAgICAgdGhpcy5jcmVhdGVFcnJvcnNXaWRnZXQoUXVhcnRlcldpZHRoLCBEZWZhdWx0VHdvTGluZXJHcmFwaFdpZGdldEhlaWdodCksXG4gICAgXTtcbiAgfVxuXG4gIGNyZWF0ZUxhdGVuY3lXaWRnZXQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiTGF0ZW5jeSAoQXZlcmFnZSlcIixcbiAgICAgIGxlZnQ6IFt0aGlzLmxhdGVuY3lBdmVyYWdlU2VhcmNoTWV0cmljc10sXG4gICAgICBsZWZ0WUF4aXM6IFRpbWVBeGlzTWlsbGlzRnJvbVplcm8sXG4gICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMubGF0ZW5jeUFubm90YXRpb25zLFxuICAgICAgbGVnZW5kUG9zaXRpb246IExlZ2VuZFBvc2l0aW9uLlJJR0hULFxuICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlVGhyb3R0bGVzV2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIlRocm90dGxlc1wiLFxuICAgICAgbGVmdDogW3RoaXMucmVhZFRocm90dGxlQ291bnRNZXRyaWMsIHRoaXMud3JpdGVUaHJvdHRsZUNvdW50TWV0cmljXSxcbiAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMudGhyb3R0bGVkRXZlbnRzQW5ub3RhdGlvbnMsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVFcnJvcnNXaWRnZXQod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICByZXR1cm4gbmV3IEdyYXBoV2lkZ2V0KHtcbiAgICAgIHdpZHRoLFxuICAgICAgaGVpZ2h0LFxuICAgICAgdGl0bGU6IFwiRXJyb3JzXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5zeXN0ZW1FcnJvck1ldHJpY10sXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmVycm9yQ291bnRBbm5vdGF0aW9ucyxcbiAgICB9KTtcbiAgfVxuXG4gIGNyZWF0ZVJlYWRDYXBhY2l0eVdpZGdldCh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcikge1xuICAgIGlmICh0aGlzLnRhYmxlQmlsbGluZ01vZGUgPT09IEJpbGxpbmdNb2RlLlBBWV9QRVJfUkVRVUVTVCkge1xuICAgICAgLy8gc2ltcGxpZmllZCB2aWV3IGZvciBvbi1kZW1hbmQgdGFibGVcbiAgICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgICB3aWR0aCxcbiAgICAgICAgaGVpZ2h0LFxuICAgICAgICB0aXRsZTogXCJSZWFkIFVzYWdlXCIsXG4gICAgICAgIGxlZnQ6IFt0aGlzLmNvbnN1bWVkUmVhZFVuaXRzTWV0cmljXSxcbiAgICAgICAgbGVmdFlBeGlzOiBDb3VudEF4aXNGcm9tWmVybyxcbiAgICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmR5bmFtb1JlYWRDYXBhY2l0eUFubm90YXRpb25zLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgR3JhcGhXaWRnZXQoe1xuICAgICAgd2lkdGgsXG4gICAgICBoZWlnaHQsXG4gICAgICB0aXRsZTogXCJSZWFkIFVzYWdlXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5jb25zdW1lZFJlYWRVbml0c01ldHJpYywgdGhpcy5wcm92aXNpb25lZFJlYWRVbml0c01ldHJpY10sXG4gICAgICBsZWZ0WUF4aXM6IENvdW50QXhpc0Zyb21aZXJvLFxuICAgICAgbGVmdEFubm90YXRpb25zOiB0aGlzLmR5bmFtb1JlYWRDYXBhY2l0eUFubm90YXRpb25zLFxuICAgICAgcmlnaHQ6IFt0aGlzLnJlYWRDYXBhY2l0eVVzYWdlTWV0cmljXSxcbiAgICAgIHJpZ2h0WUF4aXM6IFBlcmNlbnRhZ2VBeGlzRnJvbVplcm9Ub0h1bmRyZWQsXG4gICAgICBsZWdlbmRQb3NpdGlvbjogTGVnZW5kUG9zaXRpb24uUklHSFQsXG4gICAgfSk7XG4gIH1cblxuICBjcmVhdGVXcml0ZUNhcGFjaXR5V2lkZ2V0KHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMudGFibGVCaWxsaW5nTW9kZSA9PT0gQmlsbGluZ01vZGUuUEFZX1BFUl9SRVFVRVNUKSB7XG4gICAgICAvLyBzaW1wbGlmaWVkIHZpZXcgZm9yIG9uLWRlbWFuZCB0YWJsZVxuICAgICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICAgIHdpZHRoLFxuICAgICAgICBoZWlnaHQsXG4gICAgICAgIHRpdGxlOiBcIldyaXRlIFVzYWdlXCIsXG4gICAgICAgIGxlZnQ6IFt0aGlzLmNvbnN1bWVkV3JpdGVVbml0c01ldHJpY10sXG4gICAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICAgIGxlZnRBbm5vdGF0aW9uczogdGhpcy5keW5hbW9Xcml0ZUNhcGFjaXR5QW5ub3RhdGlvbnMsXG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBHcmFwaFdpZGdldCh7XG4gICAgICB3aWR0aCxcbiAgICAgIGhlaWdodCxcbiAgICAgIHRpdGxlOiBcIldyaXRlIFVzYWdlXCIsXG4gICAgICBsZWZ0OiBbdGhpcy5jb25zdW1lZFdyaXRlVW5pdHNNZXRyaWMsIHRoaXMucHJvdmlzaW9uZWRXcml0ZVVuaXRzTWV0cmljXSxcbiAgICAgIGxlZnRZQXhpczogQ291bnRBeGlzRnJvbVplcm8sXG4gICAgICBsZWZ0QW5ub3RhdGlvbnM6IHRoaXMuZHluYW1vV3JpdGVDYXBhY2l0eUFubm90YXRpb25zLFxuICAgICAgcmlnaHQ6IFt0aGlzLndyaXRlQ2FwYWNpdHlVc2FnZU1ldHJpY10sXG4gICAgICByaWdodFlBeGlzOiBQZXJjZW50YWdlQXhpc0Zyb21aZXJvVG9IdW5kcmVkLFxuICAgICAgbGVnZW5kUG9zaXRpb246IExlZ2VuZFBvc2l0aW9uLlJJR0hULFxuICAgIH0pO1xuICB9XG5cbiAgY3JlYXRlVGl0bGVXaWRnZXQoKSB7XG4gICAgcmV0dXJuIG5ldyBNb25pdG9yaW5nSGVhZGVyV2lkZ2V0KHtcbiAgICAgIGZhbWlseTogXCJEeW5hbW8gVGFibGVcIixcbiAgICAgIHRpdGxlOiB0aGlzLnRpdGxlLFxuICAgICAgZ29Ub0xpbmtVcmw6IHRoaXMudGFibGVVcmwsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlc29sdmVUYWJsZU5hbWUoZHluYW1vVGFibGU6IElUYWJsZSk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgLy8gdHJ5IHRvIHRha2UgdGhlIG5hbWUgKGlmIHNwZWNpZmllZCkgaW5zdGVhZCBvZiB0b2tlblxuICAgIHJldHVybiAoZHluYW1vVGFibGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuVGFibGUpPy50YWJsZU5hbWU7XG4gIH1cblxuICBwcml2YXRlIHJlc29sdmVUYWJsZUJpbGxpbmdNb2RlKGR5bmFtb1RhYmxlOiBJVGFibGUpOiBCaWxsaW5nTW9kZSB7XG4gICAgY29uc3QgYmlsbGluZ01vZGUgPSAoZHluYW1vVGFibGUubm9kZS5kZWZhdWx0Q2hpbGQgYXMgQ2ZuVGFibGUpXG4gICAgICA/LmJpbGxpbmdNb2RlO1xuICAgIGl