UNPKG

21.8 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.MetricSet = exports.allMetricsGraphJson = void 0;
4const drop_empty_object_at_the_end_of_an_array_token_1 = require("./drop-empty-object-at-the-end-of-an-array-token");
5const env_tokens_1 = require("./env-tokens");
6const metric_util_1 = require("./metric-util");
7const object_1 = require("./object");
8/**
9 * Return the JSON structure which represents these metrics in a graph.
10 *
11 * Depending on the metric type (stat or expression), one `Metric` object
12 * can render to multiple time series.
13 *
14 * - Top-level metrics will be rendered visibly, additionally added metrics will
15 * be rendered invisibly.
16 * - IDs used in math expressions need to be either globally unique, or refer to the same
17 * metric object.
18 *
19 * This will be called by GraphWidget, no need for clients to call this.
20 */
21function allMetricsGraphJson(left, right) {
22 // Add metrics to a set which will automatically expand them recursively,
23 // making sure to retain conflicting the visible one on conflicting metrics objects.
24 const mset = new MetricSet();
25 mset.addTopLevel('left', ...left);
26 mset.addTopLevel('right', ...right);
27 // Render all metrics from the set.
28 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)));
29}
30exports.allMetricsGraphJson = allMetricsGraphJson;
31function metricGraphJson(metric, yAxis, id) {
32 const config = metric.toMetricConfig();
33 const ret = [];
34 const options = { ...config.renderingProperties };
35 metric_util_1.dispatchMetric(metric, {
36 withStat(stat) {
37 ret.push(stat.namespace, stat.metricName);
38 // Dimensions
39 for (const dim of (stat.dimensions || [])) {
40 ret.push(dim.name, dim.value);
41 }
42 // Metric attributes that are rendered to graph options
43 if (stat.account) {
44 options.accountId = env_tokens_1.accountIfDifferentFromStack(stat.account);
45 }
46 if (stat.region) {
47 options.region = env_tokens_1.regionIfDifferentFromStack(stat.region);
48 }
49 if (stat.period && stat.period.toSeconds() !== 300) {
50 options.period = stat.period.toSeconds();
51 }
52 if (stat.statistic && stat.statistic !== 'Average') {
53 options.stat = stat.statistic;
54 }
55 },
56 withExpression(expr) {
57 options.expression = expr.expression;
58 if (expr.searchAccount) {
59 options.accountId = env_tokens_1.accountIfDifferentFromStack(expr.searchAccount);
60 }
61 if (expr.searchRegion) {
62 options.region = env_tokens_1.regionIfDifferentFromStack(expr.searchRegion);
63 }
64 if (expr.period && expr.period !== 300) {
65 options.period = expr.period;
66 }
67 },
68 });
69 // Options
70 if (!yAxis) {
71 options.visible = false;
72 }
73 if (yAxis !== 'left') {
74 options.yAxis = yAxis;
75 }
76 if (id) {
77 options.id = id;
78 }
79 if (options.visible !== false && options.expression && !options.label) {
80 // Label may be '' or undefined.
81 //
82 // If undefined, we'll render the expression as the label, to suppress
83 // the default behavior of CW where it would render the metric
84 // id as label, which we (inelegantly) generate to be something like "metric_alias0".
85 //
86 // For array expressions (returning more than 1 TS) users may sometimes want to
87 // suppress the label completely. For those cases, we'll accept the empty string,
88 // and not render a label at all.
89 options.label = options.label === '' ? undefined : metric.toString();
90 }
91 const renderedOpts = object_1.dropUndefined(options);
92 if (Object.keys(renderedOpts).length !== 0) {
93 ret.push(renderedOpts);
94 }
95 return ret;
96}
97/**
98 * Contain a set of metrics, expanding math expressions
99 *
100 * "Primary" metrics (added via a top-level call) can be tagged with an additional value.
101 */
102class MetricSet {
103 constructor() {
104 this.metrics = new Array();
105 this.metricById = new Map();
106 this.metricByKey = new Map();
107 }
108 /**
109 * Add the given set of metrics to this set
110 */
111 addTopLevel(tag, ...metrics) {
112 for (const metric of metrics) {
113 this.addOne(metric, tag);
114 }
115 }
116 /**
117 * Access all the accumulated timeseries entries
118 */
119 get entries() {
120 return this.metrics;
121 }
122 /**
123 * Add a metric into the set
124 *
125 * The id may not be the same as a previous metric added, unless it's the same metric.
126 *
127 * It can be made visible, in which case the new "metric" object replaces the old
128 * one (and the new ones "renderingPropertieS" will be honored instead of the old
129 * one's).
130 */
131 addOne(metric, tag, id) {
132 const key = metric_util_1.metricKey(metric);
133 let existingEntry;
134 // Try lookup existing by id if we have one
135 if (id) {
136 existingEntry = this.metricById.get(id);
137 if (existingEntry && metric_util_1.metricKey(existingEntry.metric) !== key) {
138 throw new Error(`Cannot have two different metrics share the same id ('${id}') in one Alarm or Graph. Rename one of them.`);
139 }
140 }
141 if (!existingEntry) {
142 // Try lookup by metric if we didn't find one by id
143 existingEntry = this.metricByKey.get(key);
144 // If the one we found already has an id, it must be different from the id
145 // we're trying to add and we want to add a new metric. Pretend we didn't
146 // find one.
147 if ((existingEntry === null || existingEntry === void 0 ? void 0 : existingEntry.id) && id) {
148 existingEntry = undefined;
149 }
150 }
151 // Create a new entry if we didn't find one so far
152 let entry;
153 if (existingEntry) {
154 entry = existingEntry;
155 }
156 else {
157 entry = { metric };
158 this.metrics.push(entry);
159 this.metricByKey.set(key, entry);
160 }
161 // If it didn't have an id but now we do, add one
162 if (!entry.id && id) {
163 entry.id = id;
164 this.metricById.set(id, entry);
165 }
166 // If it didn't have a tag but now we do, add one
167 if (!entry.tag && tag) {
168 entry.tag = tag;
169 }
170 // Recurse and add children
171 const conf = metric.toMetricConfig();
172 if (conf.mathExpression) {
173 for (const [subId, subMetric] of Object.entries(conf.mathExpression.usingMetrics)) {
174 this.addOne(subMetric, undefined, subId);
175 }
176 }
177 }
178}
179exports.MetricSet = MetricSet;
180//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVuZGVyaW5nLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsicmVuZGVyaW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFIQUFvRztBQUNwRyw2Q0FBdUY7QUFDdkYsK0NBQTBEO0FBQzFELHFDQUF5QztBQUV6Qzs7Ozs7Ozs7Ozs7O0dBWUc7QUFDSCxTQUFnQixtQkFBbUIsQ0FBQyxJQUFlLEVBQUUsS0FBZ0I7SUFDbkUseUVBQXlFO0lBQ3pFLG9GQUFvRjtJQUNwRixNQUFNLElBQUksR0FBRyxJQUFJLFNBQVMsRUFBVSxDQUFDO0lBQ3JDLElBQUksQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLENBQUMsQ0FBQztJQUVwQyxtQ0FBbUM7SUFDbkMsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLElBQUksaUZBQWdDLENBQUMsZUFBZSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQzdILENBQUM7QUFURCxrREFTQztBQUVELFNBQVMsZUFBZSxDQUFDLE1BQWUsRUFBRSxLQUFjLEVBQUUsRUFBVztJQUNuRSxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7SUFFdkMsTUFBTSxHQUFHLEdBQVUsRUFBRSxDQUFDO0lBQ3RCLE1BQU0sT0FBTyxHQUFRLEVBQUUsR0FBRyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztJQUV2RCw0QkFBYyxDQUFDLE1BQU0sRUFBRTtRQUNyQixRQUFRLENBQUMsSUFBSTtZQUNYLEdBQUcsQ0FBQyxJQUFJLENBQ04sSUFBSSxDQUFDLFNBQVMsRUFDZCxJQUFJLENBQUMsVUFBVSxDQUNoQixDQUFDO1lBRUYsYUFB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LElBQUksS0FBSyxDQUFDO1FBQ1YsSUFBSSxhQUFhLEVBQUU7WUFDakIsS0FBSyxHQUFHLGFBQWEsQ0FBQztTQUN2QjthQUFNO1lBQ0wsS0FBSyxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUM7WUFDbkIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDekIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO1NBQ2xDO1FBRUQsaURBQWlEO1FBQ2pELElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxJQUFJLEVBQUUsRUFBRTtZQUNuQixLQUFLLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQztZQUNkLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQztTQUNoQztRQUVELGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsSUFBSSxHQUFHLEVBQUU7WUFDckIsS0FBSyxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUM7U0FDakI7UUFFRCwyQkFBMkI7UUFDM0IsTUFBTSxJQUFJLEdBQUcsTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLGNBQWMsRUFBRTtZQUN2QixLQUFLLE1BQU0sQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLFlBQVksQ0FBQyxFQUFFO2dCQUNqRixJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7YUFDMUM7U0FDRjtLQUNGO0NBQ0Y7QUFsRkQsOEJBa0ZDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSU1ldHJpYyB9IGZyb20gJy4uL21ldHJpYy10eXBlcyc7XG5pbXBvcnQgeyBEcm9wRW1wdHlPYmplY3RBdFRoZUVuZE9mQW5BcnJheSB9IGZyb20gJy4vZHJvcC1lbXB0eS1vYmplY3QtYXQtdGhlLWVuZC1vZi1hbi1hcnJheS10b2tlbic7XG5pbXBvcnQgeyBhY2NvdW50SWZEaWZmZXJlbnRGcm9tU3RhY2ssIHJlZ2lvbklmRGlmZmVyZW50RnJvbVN0YWNrIH0gZnJvbSAnLi9lbnYtdG9rZW5zJztcbmltcG9ydCB7IGRpc3BhdGNoTWV0cmljLCBtZXRyaWNLZXkgfSBmcm9tICcuL21ldHJpYy11dGlsJztcbmltcG9ydCB7IGRyb3BVbmRlZmluZWQgfSBmcm9tICcuL29iamVjdCc7XG5cbi8qKlxuICogUmV0dXJuIHRoZSBKU09OIHN0cnVjdHVyZSB3aGljaCByZXByZXNlbnRzIHRoZXNlIG1ldHJpY3MgaW4gYSBncmFwaC5cbiAqXG4gKiBEZXBlbmRpbmcgb24gdGhlIG1ldHJpYyB0eXBlIChzdGF0IG9yIGV4cHJlc3Npb24pLCBvbmUgYE1ldHJpY2Agb2JqZWN0XG4gKiBjYW4gcmVuZGVyIHRvIG11bHRpcGxlIHRpbWUgc2VyaWVzLlxuICpcbiAqIC0gVG9wLWxldmVsIG1ldHJpY3Mgd2lsbCBiZSByZW5kZXJlZCB2aXNpYmx5LCBhZGRpdGlvbmFsbHkgYWRkZWQgbWV0cmljcyB3aWxsXG4gKiAgIGJlIHJlbmRlcmVkIGludmlzaWJseS5cbiAqIC0gSURzIHVzZWQgaW4gbWF0aCBleHByZXNzaW9ucyBuZWVkIHRvIGJlIGVpdGhlciBnbG9iYWxseSB1bmlxdWUsIG9yIHJlZmVyIHRvIHRoZSBzYW1lXG4gKiAgIG1ldHJpYyBvYmplY3QuXG4gKlxuICogVGhpcyB3aWxsIGJlIGNhbGxlZCBieSBHcmFwaFdpZGdldCwgbm8gbmVlZCBmb3IgY2xpZW50cyB0byBjYWxsIHRoaXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhbGxNZXRyaWNzR3JhcGhKc29uKGxlZnQ6IElNZXRyaWNbXSwgcmlnaHQ6IElNZXRyaWNbXSk6IGFueVtdIHtcbiAgLy8gQWRkIG1ldHJpY3MgdG8gYSBzZXQgd2hpY2ggd2lsbCBhdXRvbWF0aWNhbGx5IGV4cGFuZCB0aGVtIHJlY3Vyc2l2ZWx5LFxuICAvLyBtYWtpbmcgc3VyZSB0byByZXRhaW4gY29uZmxpY3RpbmcgdGhlIHZpc2libGUgb25lIG9uIGNvbmZsaWN0aW5nIG1ldHJpY3Mgb2JqZWN0cy5cbiAgY29uc3QgbXNldCA9IG5ldyBNZXRyaWNTZXQ8c3RyaW5nPigpO1xuICBtc2V0LmFkZFRvcExldmVsKCdsZWZ0JywgLi4ubGVmdCk7XG4gIG1zZXQuYWRkVG9wTGV2ZWwoJ3JpZ2h0JywgLi4ucmlnaHQpO1xuXG4gIC8vIFJlbmRlciBhbGwgbWV0cmljcyBmcm9tIHRoZSBzZXQuXG4gIHJldHVybiBtc2V0LmVudHJpZXMubWFwKGVudHJ5ID0+IG5ldyBEcm9wRW1wdHlPYmplY3RBdFRoZUVuZE9mQW5BcnJheShtZXRyaWNHcmFwaEpzb24oZW50cnkubWV0cmljLCBlbnRyeS50YWcsIGVudHJ5LmlkKSkpO1xufVxuXG5mdW5jdGlvbiBtZXRyaWNHcmFwaEpzb24obWV0cmljOiBJTWV0cmljLCB5QXhpcz86IHN0cmluZywgaWQ/OiBzdHJpbmcpIHtcbiAgY29uc3QgY29uZmlnID0gbWV0cmljLnRvTWV0cmljQ29uZmlnKCk7XG5cbiAgY29uc3QgcmV0OiBhbnlbXSA9IFtdO1xuICBjb25zdCBvcHRpb25zOiBhbnkgPSB7IC4uLmNvbmZpZy5yZW5kZXJpbmdQcm9wZXJ0aWVzIH07XG5cbiAgZGlzcGF0Y2hNZXRyaWMobWV0cmljLCB7XG4gICAgd2l0aFN0YXQoc3RhdCkge1xuICAgICAgcmV0LnB1c2goXG4gICAgICAgIHN0YXQubmFtZXNwYWNlLFxuICAgICAgICBzdGF0Lm1ldHJpY05hbWUsXG4gICAgICApO1xuXG4gICAgICAvLyBEaW1lbnNpb25zXG4gICAgICBmb3IgKGNvbnN0IGRpbSBvZiAoc3RhdC5kaW1lbnNpb25zIHx8IFtdKSkge1xuICAgICAgICByZXQucHVzaChkaW0ubmFtZSwgZGltLnZhbHVlKTtcbiAgICAgIH1cblxuICAgICAgLy8gTWV0cmljIGF0dHJpYnV0ZXMgdGhhdCBhcmUgcmVuZGVyZWQgdG8gZ3JhcGggb3B0aW9uc1xuICAgICAgaWYgKHN0YXQuYWNjb3VudCkgeyBvcHRpb25zLmFjY291bnRJZCA9IGFjY291bnRJZkRpZmZlcmVudEZyb21TdGFjayhzdGF0LmFjY291bnQpOyB9XG4gICAgICBpZiAoc3RhdC5yZWdpb24pIHsgb3B0aW9ucy5yZWdpb24gPSByZWdpb25JZkRpZmZlcmVudEZyb21TdGFjayhzdGF0LnJlZ2lvbik7IH1cbiAgICAgIGlmIChzdGF0LnBlcmlvZCAmJiBzdGF0LnBlcmlvZC50b1NlY29uZHMoKSAhPT0gMzAwKSB7IG9wdGlvbnMucGVyaW9kID0gc3RhdC5wZXJpb2QudG9TZWNvbmRzKCk7IH1cbiAgICAgIGlmIChzdGF0LnN0YXRpc3RpYyAmJiBzdGF0LnN0YXRpc3RpYyAhPT0gJ0F2ZXJhZ2UnKSB7IG9wdGlvbnMuc3RhdCA9IHN0YXQuc3RhdGlzdGljOyB9XG4gICAgfSxcblxuICAgIHdpdGhFeHByZXNzaW9uKGV4cHIpIHtcbiAgICAgIG9wdGlvbnMuZXhwcmVzc2lvbiA9IGV4cHIuZXhwcmVzc2lvbjtcbiAgICAgIGlmIChleHByLnNlYXJjaEFjY291bnQpIHsgb3B0aW9ucy5hY2NvdW50SWQgPSBhY2NvdW50SWZEaWZmZXJlbnRGcm9tU3RhY2soZXhwci5zZWFyY2hBY2NvdW50KTsgfVxuICAgICAgaWYgKGV4cHIuc2VhcmNoUmVnaW9uKSB7IG9wdGlvbnMucmVnaW9uID0gcmVnaW9uSWZEaWZmZXJlbnRGcm9tU3RhY2soZXhwci5zZWFyY2hSZWdpb24pOyB9XG4gICAgICBpZiAoZXhwci5wZXJpb2QgJiYgZXhwci5wZXJpb2QgIT09IDMwMCkgeyBvcHRpb25zLnBlcmlvZCA9IGV4cHIucGVyaW9kOyB9XG4gICAgfSxcbiAgfSk7XG5cbiAgLy8gT3B0aW9uc1xuICBpZiAoIXlBeGlzKSB7IG9wdGlvbnMudmlzaWJsZSA9IGZhbHNlOyB9XG4gIGlmICh5QXhpcyAhPT0gJ2xlZnQnKSB7IG9wdGlvbnMueUF4aXMgPSB5QXhpczsgfVxuICBpZiAoaWQpIHsgb3B0aW9ucy5pZCA9IGlkOyB9XG5cbiAgaWYgKG9wdGlvbnMudmlzaWJsZSAhPT0gZmFsc2UgJiYgb3B0aW9ucy5leHByZXNzaW9uICYmICFvcHRpb25zLmxhYmVsKSB7XG4gICAgLy8gTGFiZWwgbWF5IGJlICcnIG9yIHVuZGVmaW5lZC5cbiAgICAvL1xuICAgIC8vIElmIHVuZGVmaW5lZCwgd2UnbGwgcmVuZGVyIHRoZSBleHByZXNzaW9uIGFzIHRoZSBsYWJlbCwgdG8gc3VwcHJlc3NcbiAgICAvLyB0aGUgZGVmYXVsdCBiZWhhdmlvciBvZiBDVyB3aGVyZSBpdCB3b3VsZCByZW5kZXIgdGhlIG1ldHJpY1xuICAgIC8vIGlkIGFzIGxhYmVsLCB3aGljaCB3ZSAoaW5lbGVnYW50bHkpIGdlbmVyYXRlIHRvIGJlIHNvbWV0aGluZyBsaWtlIFwibWV0cmljX2FsaWFzMFwiLlxuICAgIC8vXG4gICAgLy8gRm9yIGFycmF5IGV4cHJlc3Npb25zIChyZXR1cm5pbmcgbW9yZSB0aGFuIDEgVFMpIHVzZXJzIG1heSBzb21ldGltZXMgd2FudCB0b1xuICAgIC8vIHN1cHByZXNzIHRoZSBsYWJlbCBjb21wbGV0ZWx5LiBGb3IgdGhvc2UgY2FzZXMsIHdlJ2xsIGFjY2VwdCB0aGUgZW1wdHkgc3RyaW5nLFxuICAgIC8vIGFuZCBub3QgcmVuZGVyIGEgbGFiZWwgYXQgYWxsLlxuICAgIG9wdGlvbnMubGFiZWwgPSBvcHRpb25zLmxhYmVsID09PSAnJyA/IHVuZGVmaW5lZCA6IG1ldHJpYy50b1N0cmluZygpO1xuICB9XG5cbiAgY29uc3QgcmVuZGVyZWRPcHRzID0gZHJvcFVuZGVmaW5lZChvcHRpb25zKTtcblxuICBpZiAoT2JqZWN0LmtleXMocmVuZGVyZWRPcHRzKS5sZW5ndGggIT09IDApIHtcbiAgICByZXQucHVzaChyZW5kZXJlZE9wdHMpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbi8qKlxuICogQSBzaW5nbGUgbWV0cmljIGluIGEgTWV0cmljU2V0XG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0cmljRW50cnk8QT4ge1xuICAvKipcbiAgICogVGhlIG1ldHJpYyBvYmplY3RcbiAgICovXG4gIHJlYWRvbmx5IG1ldHJpYzogSU1ldHJpYztcblxuICAvKipcbiAgICogVGhlIHRhZywgYWRkZWQgaWYgdGhlIG9iamVjdCBpcyBhIHByaW1hcnkgbWV0cmljXG4gICAqL1xuICB0YWc/OiBBO1xuXG4gIC8qKlxuICAgKiBJRCBmb3IgdGhpcyBtZXRyaWMgb2JqZWN0XG4gICAqL1xuICBpZD86IHN0cmluZztcbn1cblxuLyoqXG4gKiBDb250YWluIGEgc2V0IG9mIG1ldHJpY3MsIGV4cGFuZGluZyBtYXRoIGV4cHJlc3Npb25zXG4gKlxuICogXCJQcmltYXJ5XCIgbWV0cmljcyAoYWRkZWQgdmlhIGEgdG9wLWxldmVsIGNhbGwpIGNhbiBiZSB0YWdnZWQgd2l0aCBhbiBhZGRpdGlvbmFsIHZhbHVlLlxuICovXG5leHBvcnQgY2xhc3MgTWV0cmljU2V0PEE+IHtcbiAgcHJpdmF0ZSByZWFkb25seSBtZXRyaWNzID0gbmV3IEFycmF5PE1ldHJpY0VudHJ5PEE+PigpO1xuICBwcml2YXRlIHJlYWRvbmx5IG1ldHJpY0J5SWQgPSBuZXcgTWFwPHN0cmluZywgTWV0cmljRW50cnk8QT4+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgbWV0cmljQnlLZXkgPSBuZXcgTWFwPHN0cmluZywgTWV0cmljRW50cnk8QT4+KCk7XG5cbiAgLyoqXG4gICAqIEFkZCB0aGUgZ2l2ZW4gc2V0IG9mIG1ldHJpY3MgdG8gdGhpcyBzZXRcbiAgICovXG4gIHB1YmxpYyBhZGRUb3BMZXZlbCh0YWc6IEEsIC4uLm1ldHJpY3M6IElNZXRyaWNbXSkge1xuICAgIGZvciAoY29uc3QgbWV0cmljIG9mIG1ldHJpY3MpIHtcbiAgICAgIHRoaXMuYWRkT25lKG1ldHJpYywgdGFnKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQWNjZXNzIGFsbCB0aGUgYWNjdW11bGF0ZWQgdGltZXNlcmllcyBlbnRyaWVzXG4gICAqL1xuICBwdWJsaWMgZ2V0IGVudHJpZXMoKTogUmVhZG9ubHlBcnJheTxNZXRyaWNFbnRyeTxBPj4ge1xuICAgIHJldHVybiB0aGlzLm1ldHJpY3M7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGEgbWV0cmljIGludG8gdGhlIHNldFxuICAgKlxuICAgKiBUaGUgaWQgbWF5IG5vdCBiZSB0aGUgc2FtZSBhcyBhIHByZXZpb3VzIG1ldHJpYyBhZGRlZCwgdW5sZXNzIGl0J3MgdGhlIHNhbWUgbWV0cmljLlxuICAgKlxuICAgKiBJdCBjYW4gYmUgbWFkZSB2aXNpYmxlLCBpbiB3aGljaCBjYXNlIHRoZSBuZXcgXCJtZXRyaWNcIiBvYmplY3QgcmVwbGFjZXMgdGhlIG9sZFxuICAgKiBvbmUgKGFuZCB0aGUgbmV3IG9uZXMgXCJyZW5kZXJpbmdQcm9wZXJ0aWVTXCIgd2lsbCBiZSBob25vcmVkIGluc3RlYWQgb2YgdGhlIG9sZFxuICAgKiBvbmUncykuXG4gICAqL1xuICBwcml2YXRlIGFkZE9uZShtZXRyaWM6IElNZXRyaWMsIHRhZz86IEEsIGlkPzogc3RyaW5nKSB7XG4gICAgY29uc3Qga2V5ID0gbWV0cmljS2V5KG1ldHJpYyk7XG5cbiAgICBsZXQgZXhpc3RpbmdFbnRyeTogTWV0cmljRW50cnk8QT4gfCB1bmRlZmluZWQ7XG5cbiAgICAvLyBUcnkgbG9va3VwIGV4aXN0aW5nIGJ5IGlkIGlmIHdlIGhhdmUgb25lXG4gICAgaWYgKGlkKSB7XG4gICAgICBleGlzdGluZ0VudHJ5ID0gdGhpcy5tZXRyaWNCeUlkLmdldChpZCk7XG4gICAgICBpZiAoZXhpc3RpbmdFbnRyeSAmJiBtZXRyaWNLZXkoZXhpc3RpbmdFbnRyeS5tZXRyaWMpICE9PSBrZXkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3QgaGF2ZSB0d28gZGlmZmVyZW50IG1ldHJpY3Mgc2hhcmUgdGhlIHNhbWUgaWQgKCcke2lkfScpIGluIG9uZSBBbGFybSBvciBHcmFwaC4gUmVuYW1lIG9uZSBvZiB0aGVtLmApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghZXhpc3RpbmdFbnRyeSkge1xuICAgICAgLy8gVHJ5IGxvb2t1cCBieSBtZXRyaWMgaWYgd2UgZGlkbid0IGZpbmQgb25lIGJ5IGlkXG4gICAgICBleGlzdGluZ0VudHJ5ID0gdGhpcy5tZXRyaWNCeUtleS5nZXQoa2V5KTtcblxuICAgICAgLy8gSWYgdGhlIG9uZSB3ZSBmb3VuZCBhbHJlYWR5IGhhcyBhbiBpZCwgaXQgbXVzdCBiZSBkaWZmZXJlbnQgZnJvbSB0aGUgaWRcbiAgICAgIC8vIHdlJ3JlIHRyeWluZyB0byBhZGQgYW5kIHdlIHdhbnQgdG8gYWRkIGEgbmV3IG1ldHJpYy4gUHJldGVuZCB3ZSBkaWRuJ3RcbiAgICAgIC8vIGZpbmQgb25lLlxuICAgICAgaWYgKGV4aXN0aW5nRW50cnk/LmlkICYmIGlkKSB7IGV4aXN0aW5nRW50cnkgPSB1bmRlZmluZWQ7IH1cbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBuZXcgZW50cnkgaWYgd2UgZGlkbid0IGZpbmQgb25lIHNvIGZhclxuICAgIGxldCBlbnRyeTtcbiAgICBpZiAoZXhpc3RpbmdFbnRyeSkge1xuICAgICAgZW50cnkgPSBleGlzdGluZ0VudHJ5O1xuICAgIH0gZWxzZSB7XG4gICAgICBlbnRyeSA9IHsgbWV0cmljIH07XG4gICAgICB0aGlzLm1ldHJpY3MucHVzaChlbnRyeSk7XG4gICAgICB0aGlzLm1ldHJpY0J5S2V5LnNldChrZXksIGVudHJ5KTtcbiAgICB9XG5cbiAgICAvLyBJZiBpdCBkaWRuJ3QgaGF2ZSBhbiBpZCBidXQgbm93IHdlIGRvLCBhZGQgb25lXG4gICAgaWYgKCFlbnRyeS5pZCAmJiBpZCkge1xuICAgICAgZW50cnkuaWQgPSBpZDtcbiAgICAgIHRoaXMubWV0cmljQnlJZC5zZXQoaWQsIGVudHJ5KTtcbiAgICB9XG5cbiAgICAvLyBJZiBpdCBkaWRuJ3QgaGF2ZSBhIHRhZyBidXQgbm93IHdlIGRvLCBhZGQgb25lXG4gICAgaWYgKCFlbnRyeS50YWcgJiYgdGFnKSB7XG4gICAgICBlbnRyeS50YWcgPSB0YWc7XG4gICAgfVxuXG4gICAgLy8gUmVjdXJzZSBhbmQgYWRkIGNoaWxkcmVuXG4gICAgY29uc3QgY29uZiA9IG1ldHJpYy50b01ldHJpY0NvbmZpZygpO1xuICAgIGlmIChjb25mLm1hdGhFeHByZXNzaW9uKSB7XG4gICAgICBmb3IgKGNvbnN0IFtzdWJJZCwgc3ViTWV0cmljXSBvZiBPYmplY3QuZW50cmllcyhjb25mLm1hdGhFeHByZXNzaW9uLnVzaW5nTWV0cmljcykpIHtcbiAgICAgICAgdGhpcy5hZGRPbmUoc3ViTWV0cmljLCB1bmRlZmluZWQsIHN1YklkKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cbiJdfQ==
\No newline at end of file