@aws-cdk/aws-cloudwatch
Version:
The CDK Construct Library for AWS::CloudWatch
542 lines • 78 kB
JavaScript
"use strict";
var _a, _b;
Object.defineProperty(exports, "__esModule", { value: true });
exports.MathExpression = exports.Metric = void 0;
const jsiiDeprecationWarnings = require("../.warnings.jsii.js");
const JSII_RTTI_SYMBOL_1 = Symbol.for("jsii.rtti");
const iam = require("@aws-cdk/aws-iam");
const cdk = require("@aws-cdk/core");
const alarm_1 = require("./alarm");
const metric_util_1 = require("./private/metric-util");
const statistic_1 = require("./private/statistic");
/**
* A metric emitted by a service
*
* The metric is a combination of a metric identifier (namespace, name and dimensions)
* and an aggregation function (statistic, period and unit).
*
* It also contains metadata which is used only in graphs, such as color and label.
* It makes sense to embed this in here, so that compound constructs can attach
* that metadata to metrics they expose.
*
* This class does not represent a resource, so hence is not a construct. Instead,
* Metric is an abstraction that makes it easy to specify metrics for use in both
* alarms and graphs.
*/
class Metric {
constructor(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MetricProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, Metric);
}
throw error;
}
this.period = props.period || cdk.Duration.minutes(5);
const periodSec = this.period.toSeconds();
if (periodSec !== 1 && periodSec !== 5 && periodSec !== 10 && periodSec !== 30 && periodSec % 60 !== 0) {
throw new Error(`'period' must be 1, 5, 10, 30, or a multiple of 60 seconds, received ${periodSec}`);
}
this.dimensions = this.validateDimensions(props.dimensionsMap ?? props.dimensions);
this.namespace = props.namespace;
this.metricName = props.metricName;
// Try parsing, this will throw if it's not a valid stat
this.statistic = statistic_1.normalizeStatistic(props.statistic || 'Average');
this.label = props.label;
this.color = props.color;
this.unit = props.unit;
this.account = props.account;
this.region = props.region;
this.warnings = undefined;
}
/**
* Grant permissions to the given identity to write metrics.
*
* @param grantee The IAM identity to give permissions to.
*/
static grantPutMetricData(grantee) {
return iam.Grant.addToPrincipal({
grantee,
actions: ['cloudwatch:PutMetricData'],
resourceArns: ['*'],
});
}
/**
* Return a copy of Metric `with` properties changed.
*
* All properties except namespace and metricName can be changed.
*
* @param props The set of properties to change.
*/
with(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MetricOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.with);
}
throw error;
}
// Short-circuit creating a new object if there would be no effective change
if ((props.label === undefined || props.label === this.label)
&& (props.color === undefined || props.color === this.color)
&& (props.statistic === undefined || props.statistic === this.statistic)
&& (props.unit === undefined || props.unit === this.unit)
&& (props.account === undefined || props.account === this.account)
&& (props.region === undefined || props.region === this.region)
// For these we're not going to do deep equality, misses some opportunity for optimization
// but that's okay.
&& (props.dimensions === undefined)
&& (props.dimensionsMap === undefined)
&& (props.period === undefined || props.period.toSeconds() === this.period.toSeconds())) {
return this;
}
return new Metric({
dimensionsMap: props.dimensionsMap ?? props.dimensions ?? this.dimensions,
namespace: this.namespace,
metricName: this.metricName,
period: ifUndefined(props.period, this.period),
statistic: ifUndefined(props.statistic, this.statistic),
unit: ifUndefined(props.unit, this.unit),
label: ifUndefined(props.label, this.label),
color: ifUndefined(props.color, this.color),
account: ifUndefined(props.account, this.account),
region: ifUndefined(props.region, this.region),
});
}
/**
* Attach the metric object to the given construct scope
*
* Returns a Metric object that uses the account and region from the Stack
* the given construct is defined in. If the metric is subsequently used
* in a Dashboard or Alarm in a different Stack defined in a different
* account or region, the appropriate 'region' and 'account' fields
* will be added to it.
*
* If the scope we attach to is in an environment-agnostic stack,
* nothing is done and the same Metric object is returned.
*/
attachTo(scope) {
const stack = cdk.Stack.of(scope);
return this.with({
region: cdk.Token.isUnresolved(stack.region) ? undefined : stack.region,
account: cdk.Token.isUnresolved(stack.account) ? undefined : stack.account,
});
}
toMetricConfig() {
const dims = this.dimensionsAsList();
return {
metricStat: {
dimensions: dims.length > 0 ? dims : undefined,
namespace: this.namespace,
metricName: this.metricName,
period: this.period,
statistic: this.statistic,
unitFilter: this.unit,
account: this.account,
region: this.region,
},
renderingProperties: {
color: this.color,
label: this.label,
},
};
}
/** @deprecated use toMetricConfig() */
toAlarmConfig() {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.Metric#toAlarmConfig", "use toMetricConfig()");
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.toAlarmConfig);
}
throw error;
}
const metricConfig = this.toMetricConfig();
if (metricConfig.metricStat === undefined) {
throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead');
}
const stat = statistic_1.parseStatistic(metricConfig.metricStat.statistic);
return {
dimensions: metricConfig.metricStat.dimensions,
namespace: metricConfig.metricStat.namespace,
metricName: metricConfig.metricStat.metricName,
period: metricConfig.metricStat.period.toSeconds(),
statistic: stat.type === 'simple' ? stat.statistic : undefined,
extendedStatistic: stat.type === 'percentile' ? 'p' + stat.percentile : undefined,
unit: this.unit,
};
}
/**
* @deprecated use toMetricConfig()
*/
toGraphConfig() {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.Metric#toGraphConfig", "use toMetricConfig()");
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.toGraphConfig);
}
throw error;
}
const metricConfig = this.toMetricConfig();
if (metricConfig.metricStat === undefined) {
throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead');
}
return {
dimensions: metricConfig.metricStat.dimensions,
namespace: metricConfig.metricStat.namespace,
metricName: metricConfig.metricStat.metricName,
renderingProperties: {
period: metricConfig.metricStat.period.toSeconds(),
stat: metricConfig.metricStat.statistic,
color: asString(metricConfig.renderingProperties?.color),
label: asString(metricConfig.renderingProperties?.label),
},
// deprecated properties for backwards compatibility
period: metricConfig.metricStat.period.toSeconds(),
statistic: metricConfig.metricStat.statistic,
color: asString(metricConfig.renderingProperties?.color),
label: asString(metricConfig.renderingProperties?.label),
unit: this.unit,
};
}
/**
* Make a new Alarm for this metric
*
* Combines both properties that may adjust the metric (aggregation) as well
* as alarm properties.
*/
createAlarm(scope, id, props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_CreateAlarmOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.createAlarm);
}
throw error;
}
return new alarm_1.Alarm(scope, id, {
metric: this.with({
statistic: props.statistic,
period: props.period,
}),
alarmName: props.alarmName,
alarmDescription: props.alarmDescription,
comparisonOperator: props.comparisonOperator,
datapointsToAlarm: props.datapointsToAlarm,
threshold: props.threshold,
evaluationPeriods: props.evaluationPeriods,
evaluateLowSampleCountPercentile: props.evaluateLowSampleCountPercentile,
treatMissingData: props.treatMissingData,
actionsEnabled: props.actionsEnabled,
});
}
toString() {
return this.label || this.metricName;
}
/**
* Return the dimensions of this Metric as a list of Dimension.
*/
dimensionsAsList() {
const dims = this.dimensions;
if (dims === undefined) {
return [];
}
const list = Object.keys(dims).sort().map(key => ({ name: key, value: dims[key] }));
return list;
}
validateDimensions(dims) {
if (!dims) {
return dims;
}
var dimsArray = Object.keys(dims);
if (dimsArray?.length > 10) {
throw new Error(`The maximum number of dimensions is 10, received ${dimsArray.length}`);
}
dimsArray.map(key => {
if (dims[key] === undefined || dims[key] === null) {
throw new Error(`Dimension value of '${dims[key]}' is invalid`);
}
;
if (key.length < 1 || key.length > 255) {
throw new Error(`Dimension name must be at least 1 and no more than 255 characters; received ${key}`);
}
;
if (dims[key].length < 1 || dims[key].length > 255) {
throw new Error(`Dimension value must be at least 1 and no more than 255 characters; received ${dims[key]}`);
}
;
});
return dims;
}
}
exports.Metric = Metric;
_a = JSII_RTTI_SYMBOL_1;
Metric[_a] = { fqn: "@aws-cdk/aws-cloudwatch.Metric", version: "1.198.0" };
function asString(x) {
if (x === undefined) {
return undefined;
}
if (typeof x !== 'string') {
throw new Error(`Expected string, got ${x}`);
}
return x;
}
/**
* A math expression built with metric(s) emitted by a service
*
* The math expression is a combination of an expression (x+y) and metrics to apply expression on.
* It also contains metadata which is used only in graphs, such as color and label.
* It makes sense to embed this in here, so that compound constructs can attach
* that metadata to metrics they expose.
*
* MathExpression can also be used for search expressions. In this case,
* it also optionally accepts a searchRegion and searchAccount property for cross-environment
* search expressions.
*
* This class does not represent a resource, so hence is not a construct. Instead,
* MathExpression is an abstraction that makes it easy to specify metrics for use in both
* alarms and graphs.
*/
class MathExpression {
constructor(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MathExpressionProps(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, MathExpression);
}
throw error;
}
this.period = props.period || cdk.Duration.minutes(5);
this.expression = props.expression;
this.usingMetrics = changeAllPeriods(props.usingMetrics ?? {}, this.period);
this.label = props.label;
this.color = props.color;
this.searchAccount = props.searchAccount;
this.searchRegion = props.searchRegion;
const invalidVariableNames = Object.keys(this.usingMetrics).filter(x => !validVariableName(x));
if (invalidVariableNames.length > 0) {
throw new Error(`Invalid variable names in expression: ${invalidVariableNames}. Must start with lowercase letter and only contain alphanumerics.`);
}
this.validateNoIdConflicts();
// Check that all IDs used in the expression are also in the `usingMetrics` map. We
// can't throw on this anymore since we didn't use to do this validation from the start
// and now there will be loads of people who are violating the expected contract, but
// we can add warnings.
const missingIdentifiers = allIdentifiersInExpression(this.expression).filter(i => !this.usingMetrics[i]);
const warnings = [];
if (missingIdentifiers.length > 0) {
warnings.push(`Math expression '${this.expression}' references unknown identifiers: ${missingIdentifiers.join(', ')}. Please add them to the 'usingMetrics' map.`);
}
// Also copy warnings from deeper levels so graphs, alarms only have to inspect the top-level objects
for (const m of Object.values(this.usingMetrics)) {
warnings.push(...m.warnings ?? []);
}
if (warnings.length > 0) {
this.warnings = warnings;
}
}
/**
* Return a copy of Metric with properties changed.
*
* All properties except namespace and metricName can be changed.
*
* @param props The set of properties to change.
*/
with(props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_MathExpressionOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.with);
}
throw error;
}
// Short-circuit creating a new object if there would be no effective change
if ((props.label === undefined || props.label === this.label)
&& (props.color === undefined || props.color === this.color)
&& (props.period === undefined || props.period.toSeconds() === this.period.toSeconds())
&& (props.searchAccount === undefined || props.searchAccount === this.searchAccount)
&& (props.searchRegion === undefined || props.searchRegion === this.searchRegion)) {
return this;
}
return new MathExpression({
expression: this.expression,
usingMetrics: this.usingMetrics,
label: ifUndefined(props.label, this.label),
color: ifUndefined(props.color, this.color),
period: ifUndefined(props.period, this.period),
searchAccount: ifUndefined(props.searchAccount, this.searchAccount),
searchRegion: ifUndefined(props.searchRegion, this.searchRegion),
});
}
/**
* @deprecated use toMetricConfig()
*/
toAlarmConfig() {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.MathExpression#toAlarmConfig", "use toMetricConfig()");
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.toAlarmConfig);
}
throw error;
}
throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead');
}
/**
* @deprecated use toMetricConfig()
*/
toGraphConfig() {
try {
jsiiDeprecationWarnings.print("@aws-cdk/aws-cloudwatch.MathExpression#toGraphConfig", "use toMetricConfig()");
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.toGraphConfig);
}
throw error;
}
throw new Error('Using a math expression is not supported here. Pass a \'Metric\' object instead');
}
toMetricConfig() {
return {
mathExpression: {
period: this.period.toSeconds(),
expression: this.expression,
usingMetrics: this.usingMetrics,
searchAccount: this.searchAccount,
searchRegion: this.searchRegion,
},
renderingProperties: {
label: this.label,
color: this.color,
},
};
}
/**
* Make a new Alarm for this metric
*
* Combines both properties that may adjust the metric (aggregation) as well
* as alarm properties.
*/
createAlarm(scope, id, props) {
try {
jsiiDeprecationWarnings._aws_cdk_aws_cloudwatch_CreateAlarmOptions(props);
}
catch (error) {
if (process.env.JSII_DEBUG !== "1" && error.name === "DeprecationError") {
Error.captureStackTrace(error, this.createAlarm);
}
throw error;
}
return new alarm_1.Alarm(scope, id, {
metric: this.with({
period: props.period,
}),
alarmName: props.alarmName,
alarmDescription: props.alarmDescription,
comparisonOperator: props.comparisonOperator,
datapointsToAlarm: props.datapointsToAlarm,
threshold: props.threshold,
evaluationPeriods: props.evaluationPeriods,
evaluateLowSampleCountPercentile: props.evaluateLowSampleCountPercentile,
treatMissingData: props.treatMissingData,
actionsEnabled: props.actionsEnabled,
});
}
toString() {
return this.label || this.expression;
}
validateNoIdConflicts() {
const seen = new Map();
visit(this);
function visit(metric) {
metric_util_1.dispatchMetric(metric, {
withStat() {
// Nothing
},
withExpression(expr) {
for (const [id, subMetric] of Object.entries(expr.usingMetrics)) {
const existing = seen.get(id);
if (existing && metric_util_1.metricKey(existing) !== metric_util_1.metricKey(subMetric)) {
throw new Error(`The ID '${id}' used for two metrics in the expression: '${subMetric}' and '${existing}'. Rename one.`);
}
seen.set(id, subMetric);
visit(subMetric);
}
},
});
}
}
}
exports.MathExpression = MathExpression;
_b = JSII_RTTI_SYMBOL_1;
MathExpression[_b] = { fqn: "@aws-cdk/aws-cloudwatch.MathExpression", version: "1.198.0" };
/**
* Pattern for a variable name. Alphanum starting with lowercase.
*/
const VARIABLE_PAT = '[a-z][a-zA-Z0-9_]*';
const VALID_VARIABLE = new RegExp(`^${VARIABLE_PAT}$`);
const FIND_VARIABLE = new RegExp(VARIABLE_PAT, 'g');
function validVariableName(x) {
return VALID_VARIABLE.test(x);
}
/**
* Return all variable names used in an expression
*/
function allIdentifiersInExpression(x) {
return Array.from(matchAll(x, FIND_VARIABLE)).map(m => m[0]);
}
function ifUndefined(x, def) {
if (x !== undefined) {
return x;
}
return def;
}
/**
* Change periods of all metrics in the map
*/
function changeAllPeriods(metrics, period) {
const ret = {};
for (const [id, metric] of Object.entries(metrics)) {
ret[id] = changePeriod(metric, period);
}
return ret;
}
/**
* Return a new metric object which is the same type as the input object, but with the period changed
*
* Relies on the fact that implementations of `IMetric` are also supposed to have
* an implementation of `with` that accepts an argument called `period`. See `IModifiableMetric`.
*/
function changePeriod(metric, period) {
if (isModifiableMetric(metric)) {
return metric.with({ period });
}
throw new Error(`Metric object should also implement 'with': ${metric}`);
}
function isModifiableMetric(m) {
return typeof m === 'object' && m !== null && !!m.with;
}
// Polyfill for string.matchAll(regexp)
function matchAll(x, re) {
const ret = new Array();
let m;
while (m = re.exec(x)) {
ret.push(m);
}
return ret;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibWV0cmljLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7OztBQUFBLHdDQUF3QztBQUN4QyxxQ0FBcUM7QUFFckMsbUNBQXNFO0FBRXRFLHVEQUFrRTtBQUNsRSxtREFBeUU7QUErTnpFOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFhLE1BQU07SUF5Q2pCLFlBQVksS0FBa0I7Ozs7OzsrQ0F6Q25CLE1BQU07Ozs7UUEwQ2YsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTSxJQUFJLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3RELE1BQU0sU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDMUMsSUFBSSxTQUFTLEtBQUssQ0FBQyxJQUFJLFNBQVMsS0FBSyxDQUFDLElBQUksU0FBUyxLQUFLLEVBQUUsSUFBSSxTQUFTLEtBQUssRUFBRSxJQUFJLFNBQVMsR0FBRyxFQUFFLEtBQUssQ0FBQyxFQUFFO1lBQ3RHLE1BQU0sSUFBSSxLQUFLLENBQUMsd0VBQXdFLFNBQVMsRUFBRSxDQUFDLENBQUM7U0FDdEc7UUFDRCxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsYUFBYSxJQUFJLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUNuRixJQUFJLENBQUMsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUM7UUFDakMsSUFBSSxDQUFDLFVBQVUsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDO1FBQ25DLHdEQUF3RDtRQUN4RCxJQUFJLENBQUMsU0FBUyxHQUFHLDhCQUFrQixDQUFDLEtBQUssQ0FBQyxTQUFTLElBQUksU0FBUyxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUMsS0FBSyxDQUFDO1FBQ3pCLElBQUksQ0FB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QixDQUFDLE9BQWdDLEVBQUUsTUFBb0I7SUFDOUUsTUFBTSxHQUFHLEdBQTRCLEVBQUUsQ0FBQztJQUN4QyxLQUFLLE1BQU0sQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRTtRQUNsRCxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsWUFBWSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztLQUN4QztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsU0FBUyxZQUFZLENBQUMsTUFBZSxFQUFFLE1BQW9CO0lBQ3pELElBQUksa0JBQWtCLENBQUMsTUFBTSxDQUFDLEVBQUU7UUFDOUIsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQztLQUNoQztJQUVELE1BQU0sSUFBSSxLQUFLLENBQUMsK0NBQStDLE1BQU0sRUFBRSxDQUFDLENBQUM7QUFDM0UsQ0FBQztBQXdCRCxTQUFTLGtCQUFrQixDQUFDLENBQU07SUFDaEMsT0FBTyxPQUFPLENBQUMsS0FBSyxRQUFRLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUN6RCxDQUFDO0FBRUQsdUNBQXVDO0FBQ3ZDLFNBQVMsUUFBUSxDQUFDLENBQVMsRUFBRSxFQUFVO0lBQ3JDLE1BQU0sR0FBRyxHQUFHLElBQUksS0FBSyxFQUFvQixDQUFDO0lBQzFDLElBQUksQ0FBeUIsQ0FBQztJQUM5QixPQUFPLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFO1FBQ3JCLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7S0FDYjtJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIGlhbSBmcm9tICdAYXdzLWNkay9hd3MtaWFtJztcbmltcG9ydCAqIGFzIGNkayBmcm9tICdAYXdzLWNkay9jb3JlJztcbmltcG9ydCAqIGFzIGNvbnN0cnVjdHMgZnJvbSAnY29uc3RydWN0cyc7XG5pbXBvcnQgeyBBbGFybSwgQ29tcGFyaXNvbk9wZXJhdG9yLCBUcmVhdE1pc3NpbmdEYXRhIH0gZnJvbSAnLi9hbGFybSc7XG5pbXBvcnQgeyBEaW1lbnNpb24sIElNZXRyaWMsIE1ldHJpY0FsYXJtQ29uZmlnLCBNZXRyaWNDb25maWcsIE1ldHJpY0dyYXBoQ29uZmlnLCBVbml0IH0gZnJvbSAnLi9tZXRyaWMtdHlwZXMnO1xuaW1wb3J0IHsgZGlzcGF0Y2hNZXRyaWMsIG1ldHJpY0tleSB9IGZyb20gJy4vcHJpdmF0ZS9tZXRyaWMtdXRpbCc7XG5pbXBvcnQgeyBub3JtYWxpemVTdGF0aXN0aWMsIHBhcnNlU3RhdGlzdGljIH0gZnJvbSAnLi9wcml2YXRlL3N0YXRpc3RpYyc7XG5cbi8vIGtlZXAgdGhpcyBpbXBvcnQgc2VwYXJhdGUgZnJvbSBvdGhlciBpbXBvcnRzIHRvIHJlZHVjZSBjaGFuY2UgZm9yIG1lcmdlIGNvbmZsaWN0cyB3aXRoIHYyLW1haW5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1kdXBsaWNhdGUtaW1wb3J0cywgaW1wb3J0L29yZGVyXG5pbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdAYXdzLWNkay9jb3JlJztcblxuZXhwb3J0IHR5cGUgRGltZW5zaW9uSGFzaCA9IHtbZGltOiBzdHJpbmddOiBhbnl9O1xuXG5leHBvcnQgdHlwZSBEaW1lbnNpb25zTWFwID0geyBbZGltOiBzdHJpbmddOiBzdHJpbmcgfTtcblxuLyoqXG4gKiBPcHRpb25zIHNoYXJlZCBieSBtb3N0IG1ldGhvZHMgYWNjZXB0aW5nIG1ldHJpYyBvcHRpb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQ29tbW9uTWV0cmljT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgcGVyaW9kIG92ZXIgd2hpY2ggdGhlIHNwZWNpZmllZCBzdGF0aXN0aWMgaXMgYXBwbGllZC5cbiAgICpcbiAgICogQGRlZmF1bHQgRHVyYXRpb24ubWludXRlcyg1KVxuICAgKi9cbiAgcmVhZG9ubHkgcGVyaW9kPzogY2RrLkR1cmF0aW9uO1xuXG4gIC8qKlxuICAgKiBXaGF0IGZ1bmN0aW9uIHRvIHVzZSBmb3IgYWdncmVnYXRpbmcuXG4gICAqXG4gICAqIENhbiBiZSBvbmUgb2YgdGhlIGZvbGxvd2luZzpcbiAgICpcbiAgICogLSBcIk1pbmltdW1cIiB8IFwibWluXCJcbiAgICogLSBcIk1heGltdW1cIiB8IFwibWF4XCJcbiAgICogLSBcIkF2ZXJhZ2VcIiB8IFwiYXZnXCJcbiAgICogLSBcIlN1bVwiIHwgXCJzdW1cIlxuICAgKiAtIFwiU2FtcGxlQ291bnQgfCBcIm5cIlxuICAgKiAtIFwicE5OLk5OXCJcbiAgICpcbiAgICogQGRlZmF1bHQgQXZlcmFnZVxuICAgKi9cbiAgcmVhZG9ubHkgc3RhdGlzdGljPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBEaW1lbnNpb25zIG9mIHRoZSBtZXRyaWNcbiAgICpcbiAgICogQGRlZmF1bHQgLSBObyBkaW1lbnNpb25zLlxuICAgKlxuICAgKiBAZGVwcmVjYXRlZCBVc2UgJ2RpbWVuc2lvbnNNYXAnIGluc3RlYWQuXG4gICAqL1xuICByZWFkb25seSBkaW1lbnNpb25zPzogRGltZW5zaW9uSGFzaDtcblxuICAvKipcbiAgICogRGltZW5zaW9ucyBvZiB0aGUgbWV0cmljXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gTm8gZGltZW5zaW9ucy5cbiAgICovXG4gIHJlYWRvbmx5IGRpbWVuc2lvbnNNYXA/OiBEaW1lbnNpb25zTWFwO1xuXG4gIC8qKlxuICAgKiBVbml0IHVzZWQgdG8gZmlsdGVyIHRoZSBtZXRyaWMgc3RyZWFtXG4gICAqXG4gICAqIE9ubHkgcmVmZXIgdG8gZGF0dW1zIGVtaXR0ZWQgdG8gdGhlIG1ldHJpYyBzdHJlYW0gd2l0aCB0aGUgZ2l2ZW4gdW5pdCBhbmRcbiAgICogaWdub3JlIGFsbCBvdGhlcnMuIE9ubHkgdXNlZnVsIHdoZW4gZGF0dW1zIGFyZSBiZWluZyBlbWl0dGVkIHRvIHRoZSBzYW1lXG4gICAqIG1ldHJpYyBzdHJlYW0gdW5kZXIgZGlmZmVyZW50IHVuaXRzLlxuICAgKlxuICAgKiBUaGUgZGVmYXVsdCBpcyB0byB1c2UgYWxsIG1hdHJpYyBkYXR1bXMgaW4gdGhlIHN0cmVhbSwgcmVnYXJkbGVzcyBvZiB1bml0LFxuICAgKiB3aGljaCBpcyByZWNvbW1lbmRlZCBpbiBuZWFybHkgYWxsIGNhc2VzLlxuICAgKlxuICAgKiBDbG91ZFdhdGNoIGRvZXMgbm90IGhvbm9yIHRoaXMgcHJvcGVydHkgZm9yIGdyYXBocy5cbiAgICpcbiAgICogQGRlZmF1bHQgLSBBbGwgbWV0cmljIGRhdHVtcyBpbiB0aGUgZ2l2ZW4gbWV0cmljIHN0cmVhbVxuICAgKi9cbiAgcmVhZG9ubHkgdW5pdD86IFVuaXQ7XG5cbiAgLyoqXG4gICAqIExhYmVsIGZvciB0aGlzIG1ldHJpYyB3aGVuIGFkZGVkIHRvIGEgR3JhcGggaW4gYSBEYXNoYm9hcmRcbiAgICpcbiAgICogWW91IGNhbiB1c2UgW2R5bmFtaWMgbGFiZWxzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRXYXRjaC9sYXRlc3QvbW9uaXRvcmluZy9ncmFwaC1keW5hbWljLWxhYmVscy5odG1sKVxuICAgKiB0byBzaG93IHN1bW1hcnkgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGVudGlyZSBkaXNwbGF5ZWQgdGltZSBzZXJpZXNcbiAgICogaW4gdGhlIGxlZ2VuZC4gRm9yIGV4YW1wbGUsIGlmIHlvdSB1c2U6XG4gICAqXG4gICAqIGBgYFxuICAgKiBbbWF4OiAke01BWH1dIE15TWV0cmljXG4gICAqIGBgYFxuICAgKlxuICAgKiBBcyB0aGUgbWV0cmljIGxhYmVsLCB0aGUgbWF4aW11bSB2YWx1ZSBpbiB0aGUgdmlzaWJsZSByYW5nZSB3aWxsXG4gICAqIGJlIHNob3duIG5leHQgdG8gdGhlIHRpbWUgc2VyaWVzIG5hbWUgaW4gdGhlIGdyYXBoJ3MgbGVnZW5kLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIE5vIGxhYmVsXG4gICAqL1xuICByZWFkb25seSBsYWJlbD86IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIGhleCBjb2xvciBjb2RlLCBwcmVmaXhlZCB3aXRoICcjJyAoZS5nLiAnIzAwZmYwMCcpLCB0byB1c2Ugd2hlbiB0aGlzIG1ldHJpYyBpcyByZW5kZXJlZCBvbiBhIGdyYXBoLlxuICAgKiBUaGUgYENvbG9yYCBjbGFzcyBoYXMgYSBzZXQgb2Ygc3RhbmRhcmQgY29sb3JzIHRoYXQgY2FuIGJlIHVzZWQgaGVyZS5cbiAgICogQGRlZmF1bHQgLSBBdXRvbWF0aWMgY29sb3JcbiAgICovXG4gIHJlYWRvbmx5IGNvbG9yPzogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBBY2NvdW50IHdoaWNoIHRoaXMgbWV0cmljIGNvbWVzIGZyb20uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVwbG95bWVudCBhY2NvdW50LlxuICAgKi9cbiAgcmVhZG9ubHkgYWNjb3VudD86IHN0cmluZztcblxuICAvKipcbiAgICogUmVnaW9uIHdoaWNoIHRoaXMgbWV0cmljIGNvbWVzIGZyb20uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRGVwbG95bWVudCByZWdpb24uXG4gICAqL1xuICByZWFkb25seSByZWdpb24/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUHJvcGVydGllcyBmb3IgYSBtZXRyaWNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXRyaWNQcm9wcyBleHRlbmRzIENvbW1vbk1ldHJpY09wdGlvbnMge1xuICAvKipcbiAgICogTmFtZXNwYWNlIG9mIHRoZSBtZXRyaWMuXG4gICAqL1xuICByZWFkb25seSBuYW1lc3BhY2U6IHN0cmluZztcblxuICAvKipcbiAgICogTmFtZSBvZiB0aGUgbWV0cmljLlxuICAgKi9cbiAgcmVhZG9ubHkgbWV0cmljTmFtZTogc3RyaW5nO1xufVxuXG4vKipcbiAqIFByb3BlcnRpZXMgb2YgYSBtZXRyaWMgdGhhdCBjYW4gYmUgY2hhbmdlZFxuICovXG5leHBvcnQgaW50ZXJmYWNlIE1ldHJpY09wdGlvbnMgZXh0ZW5kcyBDb21tb25NZXRyaWNPcHRpb25zIHtcbn1cblxuLyoqXG4gKiBDb25maWd1cmFibGUgb3B0aW9ucyBmb3IgTWF0aEV4cHJlc3Npb25zXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWF0aEV4cHJlc3Npb25PcHRpb25zIHtcbiAgLyoqXG4gICAqIExhYmVsIGZvciB0aGlzIGV4cHJlc3Npb24gd2hlbiBhZGRlZCB0byBhIEdyYXBoIGluIGEgRGFzaGJvYXJkXG4gICAqXG4gICAqIElmIHRoaXMgZXhwcmVzc2lvbiBldmFsdWF0ZXMgdG8gbW9yZSB0aGFuIG9uZSB0aW1lIHNlcmllcyAoZm9yXG4gICAqIGV4YW1wbGUsIHRocm91Z2ggdGhlIHVzZSBvZiBgTUVUUklDUygpYCBvciBgU0VBUkNIKClgIGV4cHJlc3Npb25zKSxcbiAgICogZWFjaCB0aW1lIHNlcmllcyB3aWxsIGFwcGVhciBpbiB0aGUgZ3JhcGggdXNpbmcgYSBjb21iaW5hdGlvbiBvZiB0aGVcbiAgICogZXhwcmVzc2lvbiBsYWJlbCBhbmQgdGhlIGluZGl2aWR1YWwgbWV0cmljIGxhYmVsLiBTcGVjaWZ5IHRoZSBlbXB0eVxuICAgKiBzdHJpbmcgKGAnJ2ApIHRvIHN1cHByZXNzIHRoZSBleHByZXNzaW9uIGxhYmVsIGFuZCBvbmx5IGtlZXAgdGhlXG4gICAqIG1ldHJpYyBsYWJlbC5cbiAgICpcbiAgICogWW91IGNhbiB1c2UgW2R5bmFtaWMgbGFiZWxzXShodHRwczovL2RvY3MuYXdzLmFtYXpvbi5jb20vQW1hem9uQ2xvdWRXYXRjaC9sYXRlc3QvbW9uaXRvcmluZy9ncmFwaC1keW5hbWljLWxhYmVscy5odG1sKVxuICAgKiB0byBzaG93IHN1bW1hcnkgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRpc3BsYXllZCB0aW1lIHNlcmllc1xuICAgKiBpbiB0aGUgbGVnZW5kLiBGb3IgZXhhbXBsZSwgaWYgeW91IHVzZTpcbiAgICpcbiAgICogYGBgXG4gICAqIFttYXg6ICR7TUFYfV0gTXlNZXRyaWNcbiAgICogYGBgXG4gICAqXG4gICAqIEFzIHRoZSBtZXRyaWMgbGFiZWwsIHRoZSBtYXhpbXVtIHZhbHVlIGluIHRoZSB2aXNpYmxlIHJhbmdlIHdpbGxcbiAgICogYmUgc2hvd24gbmV4dCB0byB0aGUgdGltZSBzZXJpZXMgbmFtZSBpbiB0aGUgZ3JhcGgncyBsZWdlbmQuIElmIHRoZVxuICAgKiBtYXRoIGV4cHJlc3Npb24gcHJvZHVjZXMgbW9yZSB0aGFuIG9uZSB0aW1lIHNlcmllcywgdGhlIG1heGltdW1cbiAgICogd2lsbCBiZSBzaG93biBmb3IgZWFjaCBpbmRpdmlkdWFsIHRpbWUgc2VyaWVzIHByb2R1Y2UgYnkgdGhpc1xuICAgKiBtYXRoIGV4cHJlc3Npb24uXG4gICAqXG4gICAqIEBkZWZhdWx0IC0gRXhwcmVzc2lvbiB2YWx1ZSBpcyB1c2VkIGFzIGxhYmVsXG4gICAqL1xuICByZWFkb25seSBsYWJlbD86IHN0cmluZztcblxuICAvKipcbiAgICogQ29sb3IgZm9yIHRoaXMgbWV0cmljIHdoZW4gYWRkZWQgdG8gYSBHcmFwaCBpbiBhIERhc2hib2FyZFxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEF1dG9tYXRpYyBjb2xvclxuICAgKi9cbiAgcmVhZG9ubHkgY29sb3I/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoZSBwZXJpb2Qgb3ZlciB3aGljaCB0aGUgZXhwcmVzc2lvbidzIHN0YXRpc3RpY3MgYXJlIGFwcGxpZWQuXG4gICAqXG4gICAqIFRoaXMgcGVyaW9kIG92ZXJyaWRlcyBhbGwgcGVyaW9kcyBpbiB0aGUgbWV0cmljcyB1c2VkIGluIHRoaXNcbiAgICogbWF0aCBleHByZXNzaW9uLlxuICAgKlxuICAgKiBAZGVmYXVsdCBEdXJhdGlvbi5taW51dGVzKDUpXG4gICAqL1xuICByZWFkb25seSBwZXJpb2Q/OiBjZGsuRHVyYXRpb247XG5cbiAgLyoqXG4gICAqIEFjY291bnQgdG8gZXZhbHVhdGUgc2VhcmNoIGV4cHJlc3Npb25zIHdpdGhpbi5cbiAgICpcbiAgICogU3BlY2lmeWluZyBhIHNlYXJjaEFjY291bnQgaGFzIG5vIGVmZmVjdCB0byB0aGUgYWNjb3VudCB1c2VkXG4gICAqIGZvciBtZXRyaWNzIHdpdGhpbiB0aGUgZXhwcmVzc2lvbiAocGFzc2VkIHZpYSB1c2luZ01ldHJpY3MpLlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIERlcGxveW1lbnQgYWNjb3VudC5cbiAgICovXG4gIHJlYWRvbmx5IHNlYXJjaEFjY291bnQ/OiBzdHJpbmc7XG5cbiAgLyoqXG4gICAgKiBSZWdpb24gdG8gZXZhbHVhdGUgc2VhcmNoIGV4cHJlc3Npb25zIHdpdGhpbi5cbiAgICAqXG4gICAgKiBTcGVjaWZ5aW5nIGEgc2VhcmNoUmVnaW9uIGhhcyBubyBlZmZlY3QgdG8gdGhlIHJlZ2lvbiB1c2VkXG4gICAgKiBmb3IgbWV0cmljcyB3aXRoaW4gdGhlIGV4cHJlc3Npb24gKHBhc3NlZCB2aWEgdXNpbmdNZXRyaWNzKS5cbiAgICAqXG4gICAgKiBAZGVmYXVsdCAtIERlcGxveW1lbnQgcmVnaW9uLlxuICAgICovXG4gIHJlYWRvbmx5IHNlYXJjaFJlZ2lvbj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcm9wZXJ0aWVzIGZvciBhIE1hdGhFeHByZXNzaW9uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWF0aEV4cHJlc3Npb25Qcm9wcyBleHRlbmRzIE1hdGhFeHByZXNzaW9uT3B0aW9ucyB7XG4gIC8qKlxuICAgKiBUaGUgZXhwcmVzc2lvbiBkZWZpbmluZyB0aGUgbWV0cmljLlxuICAgKlxuICAgKiBXaGVuIGFuIGV4cHJlc3Npb24gY29udGFpbnMgYSBTRUFSQ0ggZnVuY3Rpb24sIGl0IGNhbm5vdCBiZSB1c2VkXG4gICAqIHdpdGhpbiBhbiBBbGFybS5cbiAgICovXG4gIHJlYWRvbmx5IGV4cHJlc3Npb246IHN0cmluZztcblxuICAvKipcbiAgICogVGhlIG1ldHJpY3MgdXNlZCBpbiB0aGUgZXhwcmVzc2lvbiwgaW4gYSBtYXAuXG4gICAqXG4gICAqIFRoZSBrZXkgaXMgdGhlIGlkZW50aWZpZXIgdGhhdCByZXByZXNlbnRzIHRoZSBnaXZlbiBtZXRyaWMgaW4gdGhlXG4gICAqIGV4cHJlc3Npb24sIGFuZCB0aGUgdmFsdWUgaXMgdGhlIGFjdHVhbCBNZXRyaWMgb2JqZWN0LlxuICAgKlxuICAgKiBAZGVmYXVsdCAtIEVtcHR5IG1hcC5cbiAgICovXG4gIHJlYWRvbmx5IHVzaW5nTWV0cmljcz86IFJlY29yZDxzdHJpbmcsIElNZXRyaWM+O1xufVxuXG4vKipcbiAqIEEgbWV0cmljIGVtaXR0ZWQgYnkgYSBzZXJ2aWNlXG4gKlxuICogVGhlIG1ldHJpYyBpcyBhIGNvbWJpbmF0aW9uIG9mIGEgbWV0cmljIGlkZW50aWZpZXIgKG5hbWVzcGFjZSwgbmFtZSBhbmQgZGltZW5zaW9ucylcbiAqIGFuZCBhbiBhZ2dyZWdhdGlvbiBmdW5jdGlvbiAoc3RhdGlzdGljLCBwZXJpb2QgYW5kIHVuaXQpLlxuICpcbiAqIEl0IGFsc28gY29udGFpbnMgbWV0YWRhdGEgd2hpY2ggaXMgdXNlZCBvbmx5IGluIGdyYXBocywgc3VjaCBhcyBjb2xvciBhbmQgbGFiZWwuXG4gKiBJdCBtYWtlcyBzZW5zZSB0byBlbWJlZCB0aGlzIGluIGhlcmUsIHNvIHRoYXQgY29tcG91bmQgY29uc3RydWN0cyBjYW4gYXR0YWNoXG4gKiB0aGF0IG1ldGFkYXRhIHRvIG1ldHJpY3MgdGhleSBleHBvc2UuXG4gKlxuICogVGhpcyBjbGFzcyBkb2VzIG5vdCByZXByZXNlbnQgYSByZXNvdXJjZSwgc28gaGVuY2UgaXMgbm90IGEgY29uc3RydWN0LiBJbnN0ZWFkLFxuICogTWV0cmljIGlzIGFuIGFic3RyYWN0aW9uIHRoYXQgbWFrZXMgaXQgZWFzeSB0byBzcGVjaWZ5IG1ldHJpY3MgZm9yIHVzZSBpbiBib3RoXG4gKiBhbGFybXMgYW5kIGdyYXBocy5cbiAqL1xuZXhwb3J0IGNsYXNzIE1ldHJpYyBpbXBsZW1lbnRzIElNZXRyaWMge1xuICAvKipcbiAgICogR3JhbnQgcGVybWlzc2lvbnMgdG8gdGhlIGdpdmVuIGlkZW50aXR5IHRvIHdyaXRlIG1ldHJpY3MuXG4gICAqXG4gICAqIEBwYXJhbSBncmFudGVlIFRoZSBJQU0gaWRlbnRpdHkgdG8gZ2l2ZSBwZXJtaXNzaW9ucyB0by5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZ3JhbnRQdXRNZXRyaWNEYXRhKGdyYW50ZWU6IGlhbS5JR3JhbnRhYmxlKTogaWFtLkdyYW50IHtcbiAgICByZXR1cm4gaWFtLkdyYW50LmFkZFRvUHJpbmNpcGFsKHtcbiAgICAgIGdyYW50ZWUsXG4gICAgICBhY3Rpb25zOiBbJ2Nsb3Vkd2F0Y2g6UHV0TWV0cmljRGF0YSddLFxuICAgICAgcmVzb3VyY2VBcm5zOiBbJyonXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKiBEaW1lbnNpb25zIG9mIHRoaXMgbWV0cmljICovXG4gIHB1YmxpYyByZWFkb25seSBkaW1lbnNpb25zPzogRGltZW5zaW9uSGFzaDtcbiAgLyoqIE5hbWVzcGFjZSBvZiB0aGlzIG1ldHJpYyAqL1xuICBwdWJsaWMgcmVhZG9ubHkgbmFtZXNwYWNlOiBzdHJpbmc7XG4gIC8qKiBOYW1lIG9mIHRoaXMgbWV0cmljICovXG4gIHB1YmxpYyByZWFkb25seSBtZXRyaWNOYW1lOiBzdHJpbmc7XG4gIC8qKiBQZXJpb2Qgb2YgdGhpcyBtZXRyaWMgKi9cbiAgcHVibGljIHJlYWRvbmx5IHBlcmlvZDogY2RrLkR1cmF0aW9uO1xuICAvKiogU3RhdGlzdGljIG9mIHRoaXMgbWV0cmljICovXG4gIHB1YmxpYyByZWFkb25seSBzdGF0aXN0aWM6IHN0cmluZztcbiAgLyoqIExhYmVsIGZvciB0aGlzIG1ldHJpYyB3aGVuIGFkZGVkIHRvIGEgR3JhcGggaW4gYSBEYXNoYm9hcmQgKi9cbiAgcHVibGljIHJlYWRvbmx5IGxhYmVsPzogc3RyaW5nO1xuICAvKiogVGhlIGhleCBjb2xvciBjb2RlIHVzZWQgd2hlbiB0aGlzIG1ldHJpYyBpcyByZW5kZXJlZCBvbiBhIGdyYXBoLiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgY29sb3I/OiBzdHJpbmc7XG5cbiAgLyoqIFVuaXQgb2YgdGhlIG1ldHJpYy4gKi9cbiAgcHVibGljIHJlYWRvbmx5IHVuaXQ/OiBVbml0O1xuXG4gIC8qKiBBY2NvdW50IHdoaWNoIHRoaXMgbWV0cmljIGNvbWVzIGZyb20gKi9cbiAgcHVibGljIHJlYWRvbmx5IGFjY291bnQ/OiBzdHJpbmc7XG5cbiAgLyoqIFJlZ2lvbiB3aGljaCB0aGlzIG1ldHJpYyBjb21lcyBmcm9tLiAqL1xuICBwdWJsaWMgcmVhZG9ubHkgcmVnaW9uPzogc3RyaW5nO1xuXG4gIC8qKiBXYXJuaW5ncyBhdHRhY2hlZCB0byB0aGlzIG1ldHJpYy4gKi9cbiAgcHVibGljIHJlYWRvbmx5IHdhcm5pbmdzPzogc3RyaW5nW107XG5cbiAgY29uc3RydWN0b3IocHJvcHM