@aws-cdk/aws-cloudwatch
Version:
The CDK Construct Library for AWS::CloudWatch
180 lines • 21.8 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetricSet = exports.allMetricsGraphJson = void 0;
const drop_empty_object_at_the_end_of_an_array_token_1 = require("./drop-empty-object-at-the-end-of-an-array-token");
const env_tokens_1 = require("./env-tokens");
const metric_util_1 = require("./metric-util");
const object_1 = require("./object");
/**
* Return the JSON structure which represents these metrics in a graph.
*
* Depending on the metric type (stat or expression), one `Metric` object
* can render to multiple time series.
*
* - Top-level metrics will be rendered visibly, additionally added metrics will
* be rendered invisibly.
* - IDs used in math expressions need to be either globally unique, or refer to the same
* metric object.
*
* This will be called by GraphWidget, no need for clients to call this.
*/
function allMetricsGraphJson(left, right) {
// Add metrics to a set which will automatically expand them recursively,
// making sure to retain conflicting the visible one on conflicting metrics objects.
const mset = new MetricSet();
mset.addTopLevel('left', ...left);
mset.addTopLevel('right', ...right);
// Render all metrics from the set.
return mset.entries.map(entry => new drop_empty_object_at_the_end_of_an_array_token_1.DropEmptyObjectAtTheEndOfAnArray(metricGraphJson(entry.metric, entry.tag, entry.id)));
}
exports.allMetricsGraphJson = allMetricsGraphJson;
function metricGraphJson(metric, yAxis, id) {
const config = metric.toMetricConfig();
const ret = [];
const options = { ...config.renderingProperties };
metric_util_1.dispatchMetric(metric, {
withStat(stat) {
ret.push(stat.namespace, stat.metricName);
// Dimensions
for (const dim of (stat.dimensions || [])) {
ret.push(dim.name, dim.value);
}
// Metric attributes that are rendered to graph options
if (stat.account) {
options.accountId = env_tokens_1.accountIfDifferentFromStack(stat.account);
}
if (stat.region) {
options.region = env_tokens_1.regionIfDifferentFromStack(stat.region);
}
if (stat.period && stat.period.toSeconds() !== 300) {
options.period = stat.period.toSeconds();
}
if (stat.statistic && stat.statistic !== 'Average') {
options.stat = stat.statistic;
}
},
withExpression(expr) {
options.expression = expr.expression;
if (expr.searchAccount) {
options.accountId = env_tokens_1.accountIfDifferentFromStack(expr.searchAccount);
}
if (expr.searchRegion) {
options.region = env_tokens_1.regionIfDifferentFromStack(expr.searchRegion);
}
if (expr.period && expr.period !== 300) {
options.period = expr.period;
}
},
});
// Options
if (!yAxis) {
options.visible = false;
}
if (yAxis !== 'left') {
options.yAxis = yAxis;
}
if (id) {
options.id = id;
}
if (options.visible !== false && options.expression && !options.label) {
// Label may be '' or undefined.
//
// If undefined, we'll render the expression as the label, to suppress
// the default behavior of CW where it would render the metric
// id as label, which we (inelegantly) generate to be something like "metric_alias0".
//
// For array expressions (returning more than 1 TS) users may sometimes want to
// suppress the label completely. For those cases, we'll accept the empty string,
// and not render a label at all.
options.label = options.label === '' ? undefined : metric.toString();
}
const renderedOpts = object_1.dropUndefined(options);
if (Object.keys(renderedOpts).length !== 0) {
ret.push(renderedOpts);
}
return ret;
}
/**
* Contain a set of metrics, expanding math expressions
*
* "Primary" metrics (added via a top-level call) can be tagged with an additional value.
*/
class MetricSet {
constructor() {
this.metrics = new Array();
this.metricById = new Map();
this.metricByKey = new Map();
}
/**
* Add the given set of metrics to this set
*/
addTopLevel(tag, ...metrics) {
for (const metric of metrics) {
this.addOne(metric, tag);
}
}
/**
* Access all the accumulated timeseries entries
*/
get entries() {
return this.metrics;
}
/**
* Add a metric into the set
*
* The id may not be the same as a previous metric added, unless it's the same metric.
*
* It can be made visible, in which case the new "metric" object replaces the old
* one (and the new ones "renderingPropertieS" will be honored instead of the old
* one's).
*/
addOne(metric, tag, id) {
const key = metric_util_1.metricKey(metric);
let existingEntry;
// Try lookup existing by id if we have one
if (id) {
existingEntry = this.metricById.get(id);
if (existingEntry && metric_util_1.metricKey(existingEntry.metric) !== key) {
throw new Error(`Cannot have two different metrics share the same id ('${id}') in one Alarm or Graph. Rename one of them.`);
}
}
if (!existingEntry) {
// Try lookup by metric if we didn't find one by id
existingEntry = this.metricByKey.get(key);
// If the one we found already has an id, it must be different from the id
// we're trying to add and we want to add a new metric. Pretend we didn't
// find one.
if ((existingEntry === null || existingEntry === void 0 ? void 0 : existingEntry.id) && id) {
existingEntry = undefined;
}
}
// Create a new entry if we didn't find one so far
let entry;
if (existingEntry) {
entry = existingEntry;
}
else {
entry = { metric };
this.metrics.push(entry);
this.metricByKey.set(key, entry);
}
// If it didn't have an id but now we do, add one
if (!entry.id && id) {
entry.id = id;
this.metricById.set(id, entry);
}
// If it didn't have a tag but now we do, add one
if (!entry.tag && tag) {
entry.tag = tag;
}
// Recurse and add children
const conf = metric.toMetricConfig();
if (conf.mathExpression) {
for (const [subId, subMetric] of Object.entries(conf.mathExpression.usingMetrics)) {
this.addOne(subMetric, undefined, subId);
}
}
}
}
exports.MetricSet = MetricSet;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVuZGVyaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFIQUFvRztBQUNwRyw2Q0FBdUY7QUFDdkYsK0NBQTBEO0FBQzFELHFDQUF5QztBQUV6Qzs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxTQUFnQixtQkFBbUIsQ0FBQyxJQUFlLEVBQUUsS0FBZ0I7SUFDbkUseUVBQXlFO0lBQ3pFLG9GQUFvRjtJQUNwRixNQUFNLElBQUksR0FBRyxJQUFJLFNBQVMsRUFBVSxDQUFDO0lBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUVwQyxtQ0FBbUM7SUFDbkMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksaUZBQWdDLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzdILENBQUM7QUFURCxrREFTQztBQUVELFNBQVMsZUFBZSxDQUFDLE1BQWUsRUFBRSxLQUFjLEVBQUUsRUFBVztJQUNuRSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7SUFFdkMsTUFBTSxHQUFHLEdBQVUsRUFBRSxDQUFDO0lBQ3RCLE1BQU0sT0FBTyxHQUFRLEVBQUUsR0FBRyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUV2RCw0QkFBYyxDQUFDLE1BQU0sRUFBRTtRQUNyQixRQUFRLENBQUMsSUFBSTtZQUNYLEdBQUcsQ0FBQyxJQUFJLENBQ04sSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsVUFBVSxDQUNoQixDQUFDO1lBRUYsYUFBYTtZQUNiLEtBQUssTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxFQUFFO2dCQUN6QyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDO2FBQy9CO1lBRUQsdURBQXVEO1lBQ3ZELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFBRSxPQUFPLENBQUMsU0FBUyxHQUFHLHdDQUEyQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQzthQUFFO1lBQ3BGLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFBRSxPQUFPLENBQUMsTUFBTSxHQUFHLHVDQUEwQixDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQzthQUFFO1lBQzlFLElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxLQUFLLEdBQUcsRUFBRTtnQkFBRSxPQUFPLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7YUFBRTtZQUNqRyxJQUFJLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUU7Z0JBQUUsT0FBTyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDO2FBQUU7U0FDdkY7UUFFRCxjQUFjLENBQUMsSUFBSTtZQUNqQixPQUFPLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUM7WUFDckMsSUFBSSxJQUFJLENBQUMsYUFBYSxFQUFFO2dCQUFFLE9BQU8sQ0FBQyxTQUFTLEdBQUcsd0NBQTJCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2FBQUU7WUFDaEcsSUFBSSxJQUFJLENBQUMsWUFBWSxFQUFFO2dCQUFFLE9BQU8sQ0FBQyxNQUFNLEdBQUcsdUNBQTBCLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDO2FBQUU7WUFDMUYsSUFBSSxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssR0FBRyxFQUFFO2dCQUFFLE9BQU8sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQzthQUFFO1NBQzFFO0tBQ0YsQ0FBQyxDQUFDO0lBRUgsVUFBVTtJQUNWLElBQUksQ0FBQyxLQUFLLEVBQUU7UUFBRSxPQUFPLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQztLQUFFO0lBQ3hDLElBQUksS0FBSyxLQUFLLE1BQU0sRUFBRTtRQUFFLE9BQU8sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO0tBQUU7SUFDaEQsSUFBSSxFQUFFLEVBQUU7UUFBRSxPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztLQUFFO0lBRTVCLElBQUksT0FBTyxDQUFDLE9BQU8sS0FBSyxLQUFLLElBQUksT0FBTyxDQUFDLFVBQVUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUU7UUFDckUsZ0NBQWdDO1FBQ2hDLEVBQUU7UUFDRixzRUFBc0U7UUFDdEUsOERBQThEO1FBQzlELHFGQUFxRjtRQUNyRixFQUFFO1FBQ0YsK0VBQStFO1FBQy9FLGlGQUFpRjtRQUNqRixpQ0FBaUM7UUFDakMsT0FBTyxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7S0FDdEU7SUFFRCxNQUFNLFlBQVksR0FBRyxzQkFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBRTVDLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFO1FBQzFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7S0FDeEI7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFzQkQ7Ozs7R0FJRztBQUNILE1BQWEsU0FBUztJQUF0QjtRQUNtQixZQUFPLEdBQUcsSUFBSSxLQUFLLEVBQWtCLENBQUM7UUFDdEMsZUFBVSxHQUFHLElBQUksR0FBRyxFQUEwQixDQUFDO1FBQy9DLGdCQUFXLEdBQUcsSUFBSSxHQUFHLEVBQTBCLENBQUM7SUErRW5FLENBQUM7SUE3RUM7O09BRUc7SUFDSSxXQUFXLENBQUMsR0FBTSxFQUFFLEdBQUcsT0FBa0I7UUFDOUMsS0FBSyxNQUFNLE1BQU0sSUFBSSxPQUFPLEVBQUU7WUFDNUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDMUI7S0FDRjtJQUVEOztPQUVHO0lBQ0gsSUFBVyxPQUFPO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQztLQUNyQjtJQUVEOzs7Ozs7OztPQVFHO0lBQ0ssTUFBTSxDQUFDLE1BQWUsRUFBRSxHQUFPLEVBQUUsRUFBVztRQUNsRCxNQUFNLEdBQUcsR0FBRyx1QkFBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTlCLElBQUksYUFBeUMsQ0FBQztRQUU5QywyQ0FBMkM7UUFDM0MsSUFBSSxFQUFFLEVBQUU7WUFDTixhQUFhLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7WUFDeEMsSUFBSSxhQUFhLElBQUksdUJBQVMsQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLEtBQUssR0FBRyxFQUFFO2dCQUM1RCxNQUFNLElBQUksS0FBSyxDQUFDLHlEQUF5RCxFQUFFLCtDQUErQyxDQUFDLENBQUM7YUFDN0g7U0FDRjtRQUVELElBQUksQ0FBQyxhQUFhLEVBQUU7WUFDbEIsbURBQW1EO1lBQ25ELGFBQWEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUUxQywwRUFBMEU7WUFDMUUseUVBQXlFO1lBQ3pFLFlBQVk7WUFDWixJQUFJLENBQUEsYUFBYSxhQUFiLGFBQWEsdUJBQWIsYUFBYSxDQUFFLEVBQUUsS0FBSSxFQUFFLEVBQUU7Z0JBQUUsYUFBYSxHQUFHLFNBQVMsQ0FBQzthQUFFO1NBQzVEO1FBRUQsa0RBQWtEO1FBQ2xELElBQUksS0FBSyxDQUFDO1FBQ1YsSUFBSSxhQUFhLEVBQUU7WUFDakIsS0FBSyxHQUFHLGFBQWEsQ0FBQztTQUN2QjthQUFNO1lBQ0wsS0FBSyxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDekIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ2xDO1FBRUQsaURBQWlEO1FBQ2pELElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUNuQixLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNoQztRQUVELGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxHQUFHLEVBQUU7WUFDckIsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7U0FDakI7UUFFRCwyQkFBMkI7UUFDM0IsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN2QixLQUFLLE1BQU0sQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxFQUFFO2dCQUNqRixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDMUM7U0FDRjtLQUNGO0NBQ0Y7QUFsRkQsOEJBa0ZDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSU1ldHJpYyB9IGZyb20gJy4uL21ldHJpYy10eXBlcyc7XG5pbXBvcnQgeyBEcm9wRW1wdHlPYmplY3RBdFRoZUVuZE9mQW5BcnJheSB9IGZyb20gJy4vZHJvcC1lbXB0eS1vYmplY3QtYXQtdGhlLWVuZC1vZi1hbi1hcnJheS10b2tlbic7XG5pbXBvcnQgeyBhY2NvdW50SWZEaWZmZXJlbnRGcm9tU3RhY2ssIHJlZ2lvbklmRGlmZmVyZW50RnJvbVN0YWNrIH0gZnJvbSAnLi9lbnYtdG9rZW5zJztcbmltcG9ydCB7IGRpc3BhdGNoTWV0cmljLCBtZXRyaWNLZXkgfSBmcm9tICcuL21ldHJpYy11dGlsJztcbmltcG9ydCB7IGRyb3BVbmRlZmluZWQgfSBmcm9tICcuL29iamVjdCc7XG5cbi8qKlxuICogUmV0dXJuIHRoZSBKU09OIHN0cnVjdHVyZSB3aGljaCByZXByZXNlbnRzIHRoZXNlIG1ldHJpY3MgaW4gYSBncmFwaC5cbiAqXG4gKiBEZXBlbmRpbmcgb24gdGhlIG1ldHJpYyB0eXBlIChzdGF0IG9yIGV4cHJlc3Npb24pLCBvbmUgYE1ldHJpY2Agb2JqZWN0XG4gKiBjYW4gcmVuZGVyIHRvIG11bHRpcGxlIHRpbWUgc2VyaWVzLlxuICpcbiAqIC0gVG9wLWxldmVsIG1ldHJpY3Mgd2lsbCBiZSByZW5kZXJlZCB2aXNpYmx5LCBhZGRpdGlvbmFsbHkgYWRkZWQgbWV0cmljcyB3aWxsXG4gKiAgIGJlIHJlbmRlcmVkIGludmlzaWJseS5cbiAqIC0gSURzIHVzZWQgaW4gbWF0aCBleHByZXNzaW9ucyBuZWVkIHRvIGJlIGVpdGhlciBnbG9iYWxseSB1bmlxdWUsIG9yIHJlZmVyIHRvIHRoZSBzYW1lXG4gKiAgIG1ldHJpYyBvYmplY3QuXG4gKlxuICogVGhpcyB3aWxsIGJlIGNhbGxlZCBieSBHcmFwaFdpZGdldCwgbm8gbmVlZCBmb3IgY2xpZW50cyB0byBjYWxsIHRoaXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGxNZXRyaWNzR3JhcGhKc29uKGxlZnQ6IElNZXRyaWNbXSwgcmlnaHQ6IElNZXRyaWNbXSk6IGFueVtdIHtcbiAgLy8gQWRkIG1ldHJpY3MgdG8gYSBzZXQgd2hpY2ggd2lsbCBhdXRvbWF0aWNhbGx5IGV4cGFuZCB0aGVtIHJlY3Vyc2l2ZWx5LFxuICAvLyBtYWtpbmcgc3VyZSB0byByZXRhaW4gY29uZmxpY3RpbmcgdGhlIHZpc2libGUgb25lIG9uIGNvbmZsaWN0aW5nIG1ldHJpY3Mgb2JqZWN0cy5cbiAgY29uc3QgbXNldCA9IG5ldyBNZXRyaWNTZXQ8c3RyaW5nPigpO1xuICBtc2V0LmFkZFRvcExldmVsKCdsZWZ0JywgLi4ubGVmdCk7XG4gIG1zZXQuYWRkVG9wTGV2ZWwoJ3JpZ2h0JywgLi4ucmlnaHQpO1xuXG4gIC8vIFJlbmRlciBhbGwgbWV0cmljcyBmcm9tIHRoZSBzZXQuXG4gIHJldHVybiBtc2V0LmVudHJpZXMubWFwKGVudHJ5ID0+IG5ldyBEcm9wRW1wdHlPYmplY3RBdFRoZUVuZE9mQW5BcnJheShtZXRyaWNHcmFwaEpzb24oZW50cnkubWV0cmljLCBlbnRyeS50YWcsIGVudHJ5LmlkKSkpO1xufVxuXG5mdW5jdGlvbiBtZXRyaWNHcmFwaEpzb24obWV0cmljOiBJTWV0cmljLCB5QXhpcz86IHN0cmluZywgaWQ/OiBzdHJpbmcpIHtcbiAgY29uc3QgY29uZmlnID0gbWV0cmljLnRvTWV0cmljQ29uZmlnKCk7XG5cbiAgY29uc3QgcmV0OiBhbnlbXSA9IFtdO1xuICBjb25zdCBvcHRpb25zOiBhbnkgPSB7IC4uLmNvbmZpZy5yZW5kZXJpbmdQcm9wZXJ0aWVzIH07XG5cbiAgZGlzcGF0Y2hNZXRyaWMobWV0cmljLCB7XG4gICAgd2l0aFN0YXQoc3RhdCkge1xuICAgICAgcmV0LnB1c2goXG4gICAgICAgIHN0YXQubmFtZXNwYWNlLFxuICAgICAgICBzdGF0Lm1ldHJpY05hbWUsXG4gICAgICApO1xuXG4gICAgICAvLyBEaW1lbnNpb25zXG4gICAgICBmb3IgKGNvbnN0IGRpbSBvZiAoc3RhdC5kaW1lbnNpb25zIHx8IFtdKSkge1xuICAgICAgICByZXQucHVzaChkaW0ubmFtZSwgZGltLnZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgLy8gTWV0cmljIGF0dHJpYnV0ZXMgdGhhdCBhcmUgcmVuZGVyZWQgdG8gZ3JhcGggb3B0aW9uc1xuICAgICAgaWYgKHN0YXQuYWNjb3VudCkgeyBvcHRpb25zLmFjY291bnRJZCA9IGFjY291bnRJZkRpZmZlcmVudEZyb21TdGFjayhzdGF0LmFjY291bnQpOyB9XG4gICAgICBpZiAoc3RhdC5yZWdpb24pIHsgb3B0aW9ucy5yZWdpb24gPSByZWdpb25JZkRpZmZlcmVudEZyb21TdGFjayhzdGF0LnJlZ2lvbik7IH1cbiAgICAgIGlmIChzdGF0LnBlcmlvZCAmJiBzdGF0LnBlcmlvZC50b1NlY29uZHMoKSAhPT0gMzAwKSB7IG9wdGlvbnMucGVyaW9kID0gc3RhdC5wZXJpb2QudG9TZWNvbmRzKCk7IH1cbiAgICAgIGlmIChzdGF0LnN0YXRpc3RpYyAmJiBzdGF0LnN0YXRpc3RpYyAhPT0gJ0F2ZXJhZ2UnKSB7IG9wdGlvbnMuc3RhdCA9IHN0YXQuc3RhdGlzdGljOyB9XG4gICAgfSxcblxuICAgIHdpdGhFeHByZXNzaW9uKGV4cHIpIHtcbiAgICAgIG9wdGlvbnMuZXhwcmVzc2lvbiA9IGV4cHIuZXhwcmVzc2lvbjtcbiAgICAgIGlmIChleHByLnNlYXJjaEFjY291bnQpIHsgb3B0aW9ucy5hY2NvdW50SWQgPSBhY2NvdW50SWZEaWZmZXJlbnRGcm9tU3RhY2soZXhwci5zZWFyY2hBY2NvdW50KTsgfVxuICAgICAgaWYgKGV4cHIuc2VhcmNoUmVnaW9uKSB7IG9wdGlvbnMucmVnaW9uID0gcmVnaW9uSWZEaWZmZXJlbnRGcm9tU3RhY2soZXhwci5zZWFyY2hSZWdpb24pOyB9XG4gICAgICBpZiAoZXhwci5wZXJpb2QgJiYgZXhwci5wZXJpb2QgIT09IDMwMCkgeyBvcHRpb25zLnBlcmlvZCA9IGV4cHIucGVyaW9kOyB9XG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gT3B0aW9uc1xuICBpZiAoIXlBeGlzKSB7IG9wdGlvbnMudmlzaWJsZSA9IGZhbHNlOyB9XG4gIGlmICh5QXhpcyAhPT0gJ2xlZnQnKSB7IG9wdGlvbnMueUF4aXMgPSB5QXhpczsgfVxuICBpZiAoaWQpIHsgb3B0aW9ucy5pZCA9IGlkOyB9XG5cbiAgaWYgKG9wdGlvbnMudmlzaWJsZSAhPT0gZmFsc2UgJiYgb3B0aW9ucy5leHByZXNzaW9uICYmICFvcHRpb25zLmxhYmVsKSB7XG4gICAgLy8gTGFiZWwgbWF5IGJlICcnIG9yIHVuZGVmaW5lZC5cbiAgICAvL1xuICAgIC8vIElmIHVuZGVmaW5lZCwgd2UnbGwgcmVuZGVyIHRoZSBleHByZXNzaW9uIGFzIHRoZSBsYWJlbCwgdG8gc3VwcHJlc3NcbiAgICAvLyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiBDVyB3aGVyZSBpdCB3b3VsZCByZW5kZXIgdGhlIG1ldHJpY1xuICAgIC8vIGlkIGFzIGxhYmVsLCB3aGljaCB3ZSAoaW5lbGVnYW50bHkpIGdlbmVyYXRlIHRvIGJlIHNvbWV0aGluZyBsaWtlIFwibWV0cmljX2FsaWFzMFwiLlxuICAgIC8vXG4gICAgLy8gRm9yIGFycmF5IGV4cHJlc3Npb25zIChyZXR1cm5pbmcgbW9yZSB0aGFuIDEgVFMpIHVzZXJzIG1heSBzb21ldGltZXMgd2FudCB0b1xuICAgIC8vIHN1cHByZXNzIHRoZSBsYWJlbCBjb21wbGV0ZWx5LiBGb3IgdGhvc2UgY2FzZXMsIHdlJ2xsIGFjY2VwdCB0aGUgZW1wdHkgc3RyaW5nLFxuICAgIC8vIGFuZCBub3QgcmVuZGVyIGEgbGFiZWwgYXQgYWxsLlxuICAgIG9wdGlvbnMubGFiZWwgPSBvcHRpb25zLmxhYmVsID09PSAnJyA/IHVuZGVmaW5lZCA6IG1ldHJpYy50b1N0cmluZygpO1xuICB9XG5cbiAgY29uc3QgcmVuZGVyZWRPcHRzID0gZHJvcFVuZGVmaW5lZChvcHRpb25zKTtcblxuICBpZiAoT2JqZWN0LmtleXMocmVuZGVyZWRPcHRzKS5sZW5ndGggIT09IDApIHtcbiAgICByZXQucHVzaChyZW5kZXJlZE9wdHMpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQSBzaW5nbGUgbWV0cmljIGluIGEgTWV0cmljU2V0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0cmljRW50cnk8QT4ge1xuICAvKipcbiAgICogVGhlIG1ldHJpYyBvYmplY3RcbiAgICovXG4gIHJlYWRvbmx5IG1ldHJpYzogSU1ldHJpYztcblxuICAvKipcbiAgICogVGhlIHRhZywgYWRkZWQgaWYgdGhlIG9iamVjdCBpcyBhIHByaW1hcnkgbWV0cmljXG4gICAqL1xuICB0YWc/OiBBO1xuXG4gIC8qKlxuICAgKiBJRCBmb3IgdGhpcyBtZXRyaWMgb2JqZWN0XG4gICAqL1xuICBpZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb250YWluIGEgc2V0IG9mIG1ldHJpY3MsIGV4cGFuZGluZyBtYXRoIGV4cHJlc3Npb25zXG4gKlxuICogXCJQcmltYXJ5XCIgbWV0cmljcyAoYWRkZWQgdmlhIGEgdG9wLWxldmVsIGNhbGwpIGNhbiBiZSB0YWdnZWQgd2l0aCBhbiBhZGRpdGlvbmFsIHZhbHVlLlxuICovXG5leHBvcnQgY2xhc3MgTWV0cmljU2V0PEE+IHtcbiAgcHJpdmF0ZSByZWFkb25seSBtZXRyaWNzID0gbmV3IEFycmF5PE1ldHJpY0VudHJ5PEE+PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IG1ldHJpY0J5SWQgPSBuZXcgTWFwPHN0cmluZywgTWV0cmljRW50cnk8QT4+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWV0cmljQnlLZXkgPSBuZXcgTWFwPHN0cmluZywgTWV0cmljRW50cnk8QT4+KCk7XG5cbiAgLyoqXG4gICAqIEFkZCB0aGUgZ2l2ZW4gc2V0IG9mIG1ldHJpY3MgdG8gdGhpcyBzZXRcbiAgICovXG4gIHB1YmxpYyBhZGRUb3BMZXZlbCh0YWc6IEEsIC4uLm1ldHJpY3M6IElNZXRyaWNbXSkge1xuICAgIGZvciAoY29uc3QgbWV0cmljIG9mIG1ldHJpY3MpIHtcbiAgICAgIHRoaXMuYWRkT25lKG1ldHJpYywgdGFnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWNjZXNzIGFsbCB0aGUgYWNjdW11bGF0ZWQgdGltZXNlcmllcyBlbnRyaWVzXG4gICAqL1xuICBwdWJsaWMgZ2V0IGVudHJpZXMoKTogUmVhZG9ubHlBcnJheTxNZXRyaWNFbnRyeTxBPj4ge1xuICAgIHJldHVybiB0aGlzLm1ldHJpY3M7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbWV0cmljIGludG8gdGhlIHNldFxuICAgKlxuICAgKiBUaGUgaWQgbWF5IG5vdCBiZSB0aGUgc2FtZSBhcyBhIHByZXZpb3VzIG1ldHJpYyBhZGRlZCwgdW5sZXNzIGl0J3MgdGhlIHNhbWUgbWV0cmljLlxuICAgKlxuICAgKiBJdCBjYW4gYmUgbWFkZSB2aXNpYmxlLCBpbiB3aGljaCBjYXNlIHRoZSBuZXcgXCJtZXRyaWNcIiBvYmplY3QgcmVwbGFjZXMgdGhlIG9sZFxuICAgKiBvbmUgKGFuZCB0aGUgbmV3IG9uZXMgXCJyZW5kZXJpbmdQcm9wZXJ0aWVTXCIgd2lsbCBiZSBob25vcmVkIGluc3RlYWQgb2YgdGhlIG9sZFxuICAgKiBvbmUncykuXG4gICAqL1xuICBwcml2YXRlIGFkZE9uZShtZXRyaWM6IElNZXRyaWMsIHRhZz86IEEsIGlkPzogc3RyaW5nKSB7XG4gICAgY29uc3Qga2V5ID0gbWV0cmljS2V5KG1ldHJpYyk7XG5cbiAgICBsZXQgZXhpc3RpbmdFbnRyeTogTWV0cmljRW50cnk8QT4gfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBUcnkgbG9va3VwIGV4aXN0aW5nIGJ5IGlkIGlmIHdlIGhhdmUgb25lXG4gICAgaWYgKGlkKSB7XG4gICAgICBleGlzdGluZ0VudHJ5ID0gdGhpcy5tZXRyaWNCeUlkLmdldChpZCk7XG4gICAgICBpZiAoZXhpc3RpbmdFbnRyeSAmJiBtZXRyaWNLZXkoZXhpc3RpbmdFbnRyeS5tZXRyaWMpICE9PSBrZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgaGF2ZSB0d28gZGlmZmVyZW50IG1ldHJpY3Mgc2hhcmUgdGhlIHNhbWUgaWQgKCcke2lkfScpIGluIG9uZSBBbGFybSBvciBHcmFwaC4gUmVuYW1lIG9uZSBvZiB0aGVtLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghZXhpc3RpbmdFbnRyeSkge1xuICAgICAgLy8gVHJ5IGxvb2t1cCBieSBtZXRyaWMgaWYgd2UgZGlkbid0IGZpbmQgb25lIGJ5IGlkXG4gICAgICBleGlzdGluZ0VudHJ5ID0gdGhpcy5tZXRyaWNCeUtleS5nZXQoa2V5KTtcblxuICAgICAgLy8gSWYgdGhlIG9uZSB3ZSBmb3VuZCBhbHJlYWR5IGhhcyBhbiBpZCwgaXQgbXVzdCBiZSBkaWZmZXJlbnQgZnJvbSB0aGUgaWRcbiAgICAgIC8vIHdlJ3JlIHRyeWluZyB0byBhZGQgYW5kIHdlIHdhbnQgdG8gYWRkIGEgbmV3IG1ldHJpYy4gUHJldGVuZCB3ZSBkaWRuJ3RcbiAgICAgIC8vIGZpbmQgb25lLlxuICAgICAgaWYgKGV4aXN0aW5nRW50cnk/LmlkICYmIGlkKSB7IGV4aXN0aW5nRW50cnkgPSB1bmRlZmluZWQ7IH1cbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBuZXcgZW50cnkgaWYgd2UgZGlkbid0IGZpbmQgb25lIHNvIGZhclxuICAgIGxldCBlbnRyeTtcbiAgICBpZiAoZXhpc3RpbmdFbnRyeSkge1xuICAgICAgZW50cnkgPSBleGlzdGluZ0VudHJ5O1xuICAgIH0gZWxzZSB7XG4gICAgICBlbnRyeSA9IHsgbWV0cmljIH07XG4gICAgICB0aGlzLm1ldHJpY3MucHVzaChlbnRyeSk7XG4gICAgICB0aGlzLm1ldHJpY0J5S2V5LnNldChrZXksIGVudHJ5KTtcbiAgICB9XG5cbiAgICAvLyBJZiBpdCBkaWRuJ3QgaGF2ZSBhbiBpZCBidXQgbm93IHdlIGRvLCBhZGQgb25lXG4gICAgaWYgKCFlbnRyeS5pZCAmJiBpZCkge1xuICAgICAgZW50cnkuaWQgPSBpZDtcbiAgICAgIHRoaXMubWV0cmljQnlJZC5zZXQoaWQsIGVudHJ5KTtcbiAgICB9XG5cbiAgICAvLyBJZiBpdCBkaWRuJ3QgaGF2ZSBhIHRhZyBidXQgbm93IHdlIGRvLCBhZGQgb25lXG4gICAgaWYgKCFlbnRyeS50YWcgJiYgdGFnKSB7XG4gICAgICBlbnRyeS50YWcgPSB0YWc7XG4gICAgfVxuXG4gICAgLy8gUmVjdXJzZSBhbmQgYWRkIGNoaWxkcmVuXG4gICAgY29uc3QgY29uZiA9IG1ldHJpYy50b01ldHJpY0NvbmZpZygpO1xuICAgIGlmIChjb25mLm1hdGhFeHByZXNzaW9uKSB7XG4gICAgICBmb3IgKGNvbnN0IFtzdWJJZCwgc3ViTWV0cmljXSBvZiBPYmplY3QuZW50cmllcyhjb25mLm1hdGhFeHByZXNzaW9uLnVzaW5nTWV0cmljcykpIHtcbiAgICAgICAgdGhpcy5hZGRPbmUoc3ViTWV0cmljLCB1bmRlZmluZWQsIHN1YklkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==
;