UNPKG

23.9 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _autoBind = _interopRequireDefault(require("auto-bind"));
9
10var _System = _interopRequireDefault(require("./System"));
11
12var _errorUtils = require("./errorUtils");
13
14var _stringUtils = require("./stringUtils");
15
16function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
18function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
19
20function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
21
22class Module {
23 // Instance
24 constructor(moduleName, moduleConfig) {
25 _defineProperty(this, "MODULE_NAME", void 0);
26
27 _defineProperty(this, "_moduleConfig", void 0);
28
29 _defineProperty(this, "debug", (message, data, logOnly) => {
30 this._internalLog('debug', this.MODULE_NAME, message, data, logOnly);
31 });
32
33 _defineProperty(this, "log", (message, data, logOnly) => {
34 this._internalLog('info', this.MODULE_NAME, message, data, logOnly);
35 });
36
37 _defineProperty(this, "warn", (message, data, logOnly) => {
38 this._internalLog('warn', this.MODULE_NAME, message, data, logOnly);
39 });
40
41 _defineProperty(this, "error", (message, data, logOnly) => {
42 this._internalLog('error', this.MODULE_NAME, message, data, logOnly);
43 });
44
45 _defineProperty(this, "trackCountsDated", async countMetrics => {
46 try {
47 await _trackMetricsToInfluxDB(countMetrics.map(metric => _objectSpread({}, metric, {
48 metricType: 'counters',
49 module: this.MODULE_NAME
50 })));
51 } catch (err) {
52 this.error('Failed to track dated counts', {
53 err
54 });
55 }
56 });
57
58 _defineProperty(this, "trackCountDated", async (statName, value, timestampMs, dims) => {
59 // $FlowIgnore
60 await this.trackCountsDated([{
61 statName,
62 value,
63 timestampMs,
64 dims
65 }]);
66 });
67
68 _defineProperty(this, "noteGauge", async (statName, value, dims) => {
69 try {
70 // $FlowIgnore
71 await _trackMetricToInfluxDB(statName, value, _objectSpread({}, dims, {
72 metricType: 'gauges',
73 module: this.MODULE_NAME
74 }));
75 } catch (err) {
76 this.error('Failed to track gauge', {
77 err,
78 statName
79 });
80 }
81 });
82
83 _defineProperty(this, "noteCount", async (statName, value = 1, dims) => {
84 try {
85 // $FlowIgnore
86 await _trackMetricToInfluxDB(statName, value, _objectSpread({}, dims, {
87 metricType: 'counters',
88 module: this.MODULE_NAME
89 }));
90 } catch (err) {
91 this.error('Failed to track count', {
92 err,
93 statName
94 }, true); // avoid call loop of error count logs tracking
95 }
96 });
97
98 _defineProperty(this, "noteTimer", async (statName, durationMs, dims) => {
99 if (typeof durationMs !== 'number') throw new Error(`durationMs must be a number (${statName})`); // cant use context here, circular dependency...
100
101 try {
102 // $FlowIgnore
103 await _trackMetricToInfluxDB(statName, durationMs, _objectSpread({}, dims, {
104 metricType: 'timers',
105 module: this.MODULE_NAME
106 }));
107 } catch (err) {
108 this.error('Failed to track timer', {
109 err,
110 statName
111 });
112 }
113 });
114
115 this.MODULE_NAME = (moduleName.split('/').pop() || '').split('.')[0];
116 this._moduleConfig = moduleConfig || {}; // $FlowIgnore
117 // NOTE: the outer timeout is set to avoid calling System from the Moduile ctor, which can access System before it was loaded
118
119 setTimeout(() => {
120 const lifesignIntervalMS = _System.default.getConfig().lifesignIntervalMS;
121
122 if (lifesignIntervalMS && this._moduleConfig.isEntryPoint) {
123 setInterval(() => {
124 this.noteCount('lifesign');
125 }, lifesignIntervalMS);
126 }
127 }, 1000);
128 (0, _autoBind.default)(this);
129 }
130
131 async trackOp(op, name, dims, options) {
132 if (name == null) {
133 return await op();
134 }
135
136 options = options || {};
137 dims = _objectSpread({}, dims, {
138 module: this.MODULE_NAME
139 });
140 const startMS = Date.now();
141 let endMS = startMS;
142
143 try {
144 options.log && this.log(`Operation '${name}' started...`);
145 this.noteCount(`${name}.start`, 1, dims);
146 const ret = await op();
147 this.noteCount(`${name}.success`, 1, dims);
148 endMS = Date.now();
149 options.log && this.log(`Operation '${name}' completed`, {
150 execMS: endMS - startMS
151 });
152 return ret;
153 } catch (err) {
154 endMS = Date.now();
155 options.log && this.log(`Operation '${name}' threw an error`, {
156 execMS: endMS - startMS,
157 err: err
158 });
159 this.noteCount(`${name}.fail`, 1, dims);
160 throw err;
161 } finally {
162 this.noteCount(`${name}.end`, 1, dims);
163 this.noteTimer(name, endMS - startMS, dims);
164 }
165 }
166
167 _internalLog(level, module, message, data, logOnly) {
168 try {
169 // check if level is activated
170 if (_System.default.activeLogLevels && !_System.default.activeLogLevels.includes(level)) return;
171 const logRecord = {
172 level: level,
173 module: module,
174 message: message,
175 data: _correctData(data) // log to other destinations
176
177 };
178
179 _System.default.queueLogRecord(logRecord);
180
181 if (!logOnly) this.noteCount(`logging.${level}`, 1);
182 } catch (err) {
183 console.error(`Error thrown during logging operation: ${err.toString()}`); // eslint-disable-line no-console
184 }
185 }
186
187}
188
189exports.default = Module;
190
191async function _trackMetricsToInfluxDB(metrics) {
192 await Promise.all(_System.default.influxDBClients.map(idbClient => idbClient.trackMetrics(metrics.map(metric => _objectSpread({}, metric, {
193 timestampMs: Date.now()
194 })))));
195}
196
197async function _trackMetricToInfluxDB(statName, value, dims, timestampMs) {
198 await _trackMetricsToInfluxDB([{
199 statName,
200 value,
201 dims,
202 timestampMs
203 }]);
204}
205
206function _correctData(data) {
207 if (data != null) {
208 if ((0, _errorUtils.isError)(data)) {
209 data = {
210 err: data
211 };
212 }
213
214 let iteratingData = data;
215 let maxDepth = 4;
216
217 while (--maxDepth && iteratingData && (0, _errorUtils.isError)(iteratingData.err)) {
218 // $FlowIgnore
219 iteratingData.err = (0, _stringUtils.errorToObj)(iteratingData.err); // $FlowIgnore
220
221 iteratingData = iteratingData.err.data;
222 }
223 }
224
225 return data;
226}
227//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9Nb2R1bGUuanMiXSwibmFtZXMiOlsiTW9kdWxlIiwiY29uc3RydWN0b3IiLCJtb2R1bGVOYW1lIiwibW9kdWxlQ29uZmlnIiwibWVzc2FnZSIsImRhdGEiLCJsb2dPbmx5IiwiX2ludGVybmFsTG9nIiwiTU9EVUxFX05BTUUiLCJjb3VudE1ldHJpY3MiLCJfdHJhY2tNZXRyaWNzVG9JbmZsdXhEQiIsIm1hcCIsIm1ldHJpYyIsIm1ldHJpY1R5cGUiLCJtb2R1bGUiLCJlcnIiLCJlcnJvciIsInN0YXROYW1lIiwidmFsdWUiLCJ0aW1lc3RhbXBNcyIsImRpbXMiLCJ0cmFja0NvdW50c0RhdGVkIiwiX3RyYWNrTWV0cmljVG9JbmZsdXhEQiIsImR1cmF0aW9uTXMiLCJFcnJvciIsInNwbGl0IiwicG9wIiwiX21vZHVsZUNvbmZpZyIsInNldFRpbWVvdXQiLCJsaWZlc2lnbkludGVydmFsTVMiLCJTeXN0ZW0iLCJnZXRDb25maWciLCJpc0VudHJ5UG9pbnQiLCJzZXRJbnRlcnZhbCIsIm5vdGVDb3VudCIsInRyYWNrT3AiLCJvcCIsIm5hbWUiLCJvcHRpb25zIiwic3RhcnRNUyIsIkRhdGUiLCJub3ciLCJlbmRNUyIsImxvZyIsInJldCIsImV4ZWNNUyIsIm5vdGVUaW1lciIsImxldmVsIiwiYWN0aXZlTG9nTGV2ZWxzIiwiaW5jbHVkZXMiLCJsb2dSZWNvcmQiLCJfY29ycmVjdERhdGEiLCJxdWV1ZUxvZ1JlY29yZCIsImNvbnNvbGUiLCJ0b1N0cmluZyIsIm1ldHJpY3MiLCJQcm9taXNlIiwiYWxsIiwiaW5mbHV4REJDbGllbnRzIiwiaWRiQ2xpZW50IiwidHJhY2tNZXRyaWNzIiwiaXRlcmF0aW5nRGF0YSIsIm1heERlcHRoIl0sIm1hcHBpbmdzIjoiOzs7Ozs7O0FBSUE7O0FBRUE7O0FBQ0E7O0FBQ0E7Ozs7Ozs7O0FBU2UsTUFBTUEsTUFBTixDQUFhO0FBRTFCO0FBT0FDLEVBQUFBLFdBQVcsQ0FBQ0MsVUFBRCxFQUFxQkMsWUFBckIsRUFB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QWQsQ0FBa0JWLElBQWxDO0FBQ0Q7QUFDRjs7QUFFRCxTQUFPQSxJQUFQO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBAZmxvd1xuXG4vLyBOT1RFOiBkb250IHVzZSBNb2R1bGUgaGVyZSwgdGhpcyBmaWxlIGlzIHVzZWQgYnkgTW9kdWxlXG5cbmltcG9ydCBhdXRvQmluZCBmcm9tICdhdXRvLWJpbmQnXG5cbmltcG9ydCBTeXN0ZW0gZnJvbSAnLi9TeXN0ZW0nXG5pbXBvcnQgeyBpc0Vycm9yIH0gZnJvbSAnLi9lcnJvclV0aWxzJ1xuaW1wb3J0IHsgZXJyb3JUb09iaiB9IGZyb20gJy4vc3RyaW5nVXRpbHMnXG5cbmltcG9ydCB0eXBlIHsgTWV0cmljRGltZW5zaW9ucywgTWluaW1hbE1ldHJpY0RpbWVuc2lvbnMgfSBmcm9tICcuL3R5cGVzJ1xuaW1wb3J0IHR5cGUgeyBNZXRyaWMgfSBmcm9tICcuL0luZmx1eERCQ2xpZW50J1xuXG50eXBlIE1vZHVsZUNvbmZpZyA9IHtcbiAgaXNFbnRyeVBvaW50PzogP2Jvb2xlYW4sXG59XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE1vZHVsZSB7XG5cbiAgLy8gSW5zdGFuY2VcblxuICBNT0RVTEVfTkFNRTogc3RyaW5nXG5cbiAgX21vZHVsZUNvbmZpZzogTW9kdWxlQ29uZmlnXG5cblxuICBjb25zdHJ1Y3Rvcihtb2R1bGVOYW1lOiBzdHJpbmcsIG1vZHVsZUNvbmZpZzogP01vZHVsZUNvbmZpZykge1xuICAgIHRoaXMuTU9EVUxFX05BTUUgPSAobW9kdWxlTmFtZS5zcGxpdCgnLycpLnBvcCgpIHx8ICcnKS5zcGxpdCgnLicpWzBdXG4gICAgdGhpcy5fbW9kdWxlQ29uZmlnID0gbW9kdWxlQ29uZmlnIHx8IHt9XG4gICAgLy8gJEZsb3dJZ25vcmVcblxuICAgIC8vIE5PVEU6IHRoZSBvdXRlciB0aW1lb3V0IGlzIHNldCB0byBhdm9pZCBjYWxsaW5nIFN5c3RlbSBmcm9tIHRoZSBNb2R1aWxlIGN0b3IsIHdoaWNoIGNhbiBhY2Nlc3MgU3lzdGVtIGJlZm9yZSBpdCB3YXMgbG9hZGVkXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICBjb25zdCBsaWZlc2lnbkludGVydmFsTVMgPSBTeXN0ZW0uZ2V0Q29uZmlnKCkubGlmZXNpZ25JbnRlcnZhbE1TXG4gICAgICBpZiAobGlmZXNpZ25JbnRlcnZhbE1TICYmIHRoaXMuX21vZHVsZUNvbmZpZy5pc0VudHJ5UG9pbnQpIHtcbiAgICAgICAgc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgICAgIHRoaXMubm90ZUNvdW50KCdsaWZlc2lnbicpXG4gICAgICAgIH0sIGxpZmVzaWduSW50ZXJ2YWxNUylcbiAgICAgIH1cbiAgICB9LCAxMDAwKVxuXG4gICAgYXV0b0JpbmQodGhpcylcbiAgfVxuXG5cbiAgZGVidWcgPSAobWVzc2FnZTogc3RyaW5nLCBkYXRhOiA/YW55LCBsb2dPbmx5OiA/Ym9vbGVhbikgPT4ge1xuICAgIHRoaXMuX2ludGVybmFsTG9nKCdkZWJ1ZycsIHRoaXMuTU9EVUxFX05BTUUsIG1lc3NhZ2UsIGRhdGEsIGxvZ09ubHkpXG4gIH1cblxuICBsb2cgPSAobWVzc2FnZTogc3RyaW5nLCBkYXRhOiA/YW55LCBsb2dPbmx5OiA/Ym9vbGVhbikgPT4ge1xuICAgIHRoaXMuX2ludGVybmFsTG9nKCdpbmZvJywgdGhpcy5NT0RVTEVfTkFNRSwgbWVzc2FnZSwgZGF0YSwgbG9nT25seSlcbiAgfVxuXG4gIHdhcm4gPSAobWVzc2FnZTogc3RyaW5nLCBkYXRhOiA/YW55LCBsb2dPbmx5OiA/Ym9vbGVhbikgPT4ge1xuICAgIHRoaXMuX2ludGVybmFsTG9nKCd3YXJuJywgdGhpcy5NT0RVTEVfTkFNRSwgbWVzc2FnZSwgZGF0YSwgbG9nT25seSlcbiAgfVxuXG4gIGVycm9yID0gKG1lc3NhZ2U6IHN0cmluZywgZGF0YTogP2FueSwgbG9nT25seTogP2Jvb2xlYW4pID0+IHtcbiAgICB0aGlzLl9pbnRlcm5hbExvZygnZXJyb3InLCB0aGlzLk1PRFVMRV9OQU1FLCBtZXNzYWdlLCBkYXRhLCBsb2dPbmx5KVxuICB9XG5cbiAgdHJhY2tDb3VudHNEYXRlZCA9IGFzeW5jIChjb3VudE1ldHJpY3M6IEFycmF5PE1ldHJpYz4pID0+IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgX3RyYWNrTWV0cmljc1RvSW5mbHV4REIoY291bnRNZXRyaWNzLm1hcChtZXRyaWMgPT4gKHsgXG4gICAgICAgIC4uLm1ldHJpYywgXG4gICAgICAgIG1ldHJpY1R5cGU6ICdjb3VudGVycycsIFxuICAgICAgICBtb2R1bGU6IHRoaXMuTU9EVUxFX05BTUUsXG4gICAgICB9KSkpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmVycm9yKCdGYWlsZWQgdG8gdHJhY2sgZGF0ZWQgY291bnRzJywgeyBlcnIgfSlcbiAgICB9XG4gIH1cblxuICB0cmFja0NvdW50RGF0ZWQgPSBhc3luYyAoc3RhdE5hbWU6IHN0cmluZywgdmFsdWU6IG51bWJlciwgdGltZXN0YW1wTXM6IG51bWJlciwgZGltczogTWV0cmljRGltZW5zaW9ucykgPT4ge1xuICAgIC8vICRGbG93SWdub3JlXG4gICAgYXdhaXQgdGhpcy50cmFja0NvdW50c0RhdGVkKFsgeyBzdGF0TmFtZSwgdmFsdWUsIHRpbWVzdGFtcE1zLCBkaW1zIH0gXSlcbiAgfVxuICBcbiAgbm90ZUdhdWdlID0gYXN5bmMgKHN0YXROYW1lOiBzdHJpbmcsIHZhbHVlOiBudW1iZXIsIGRpbXM6ID9NZXRyaWNEaW1lbnNpb25zKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIC8vICRGbG93SWdub3JlXG4gICAgICBhd2FpdCBfdHJhY2tNZXRyaWNUb0luZmx1eERCKHN0YXROYW1lLCB2YWx1ZSwgeyBcbiAgICAgICAgLi4uZGltcywgXG4gICAgICAgIG1ldHJpY1R5cGU6ICdnYXVnZXMnLCBcbiAgICAgICAgbW9kdWxlOiB0aGlzLk1PRFVMRV9OQU1FLFxuICAgICAgfSkgXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmVycm9yKCdGYWlsZWQgdG8gdHJhY2sgZ2F1Z2UnLCB7IGVyciwgc3RhdE5hbWUgfSlcbiAgICB9XG4gIH1cbiAgXG4gIG5vdGVDb3VudCA9IGFzeW5jIChzdGF0TmFtZTogc3RyaW5nLCB2YWx1ZTogbnVtYmVyID0gMSwgZGltczogP01ldHJpY0RpbWVuc2lvbnMpID0+IHtcbiAgICB0cnkge1xuICAgICAgLy8gJEZsb3dJZ25vcmVcbiAgICAgIGF3YWl0IF90cmFja01ldHJpY1RvSW5mbHV4REIoc3RhdE5hbWUsIHZhbHVlLCB7IFxuICAgICAgICAuLi5kaW1zLCBcbiAgICAgICAgbWV0cmljVHlwZTogJ2NvdW50ZXJzJywgXG4gICAgICAgIG1vZHVsZTogdGhpcy5NT0RVTEVfTkFNRSxcbiAgICAgIH0pIFxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5lcnJvcignRmFpbGVkIHRvIHRyYWNrIGNvdW50JywgeyBlcnIsIHN0YXROYW1lIH0sIHRydWUpIC8vIGF2b2lkIGNhbGwgbG9vcCBvZiBlcnJvciBjb3VudCBsb2dzIHRyYWNraW5nXG4gICAgfVxuICB9XG4gIFxuICBub3RlVGltZXIgPSBhc3luYyAoc3RhdE5hbWU6IHN0cmluZywgZHVyYXRpb25NczogbnVtYmVyLCBkaW1zOiA/TWV0cmljRGltZW5zaW9ucykgPT4ge1xuICAgIGlmICh0eXBlb2YgZHVyYXRpb25NcyAhPT0gJ251bWJlcicpXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYGR1cmF0aW9uTXMgbXVzdCBiZSBhIG51bWJlciAoJHtzdGF0TmFtZX0pYCkgLy8gY2FudCB1c2UgY29udGV4dCBoZXJlLCBjaXJjdWxhciBkZXBlbmRlbmN5Li4uXG4gICAgdHJ5IHtcbiAgICAgIC8vICRGbG93SWdub3JlXG4gICAgICBhd2FpdCBfdHJhY2tNZXRyaWNUb0luZmx1eERCKHN0YXROYW1lLCBkdXJhdGlvbk1zLCB7IFxuICAgICAgICAuLi5kaW1zLCBcbiAgICAgICAgbWV0cmljVHlwZTogJ3RpbWVycycsIFxuICAgICAgICBtb2R1bGU6IHRoaXMuTU9EVUxFX05BTUUsXG4gICAgICB9KVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5lcnJvcignRmFpbGVkIHRvIHRyYWNrIHRpbWVyJywgeyBlcnIsIHN0YXROYW1lIH0pXG4gICAgfVxuICB9XG4gIFxuXG4gIGFzeW5jIHRyYWNrT3A8VD4ob3A6ICgpID0+IFByb21pc2U8VD4sIG5hbWU6ID9zdHJpbmcsIGRpbXM6ID9NZXRyaWNEaW1lbnNpb25zLCBvcHRpb25zOiA/eyBsb2c/OiA/Ym9vbGVhbiB9KTogUHJvbWlzZTxUPiB7XG4gICAgaWYgKG5hbWUgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIGF3YWl0IG9wKClcbiAgICB9XG4gICAgXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge31cbiAgICBkaW1zID0geyAuLi5kaW1zLCBtb2R1bGU6IHRoaXMuTU9EVUxFX05BTUUgfVxuICAgIGNvbnN0IHN0YXJ0TVMgPSBEYXRlLm5vdygpXG4gICAgbGV0IGVuZE1TID0gc3RhcnRNU1xuICAgIHRyeSB7XG4gICAgICBvcHRpb25zLmxvZyAmJiB0aGlzLmxvZyhgT3BlcmF0aW9uICcke25hbWV9JyBzdGFydGVkLi4uYClcbiAgICAgIHRoaXMubm90ZUNvdW50KGAke25hbWV9LnN0YXJ0YCwgMSwgZGltcylcbiAgICAgIGNvbnN0IHJldCA9IGF3YWl0IG9wKClcbiAgICAgIHRoaXMubm90ZUNvdW50KGAke25hbWV9LnN1Y2Nlc3NgLCAxLCBkaW1zKVxuICAgICAgZW5kTVMgPSBEYXRlLm5vdygpXG4gICAgICBvcHRpb25zLmxvZyAmJiB0aGlzLmxvZyhgT3BlcmF0aW9uICcke25hbWV9JyBjb21wbGV0ZWRgLCB7IGV4ZWNNUzogZW5kTVMgLSBzdGFydE1TIH0pXG4gICAgICByZXR1cm4gcmV0XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBlbmRNUyA9IERhdGUubm93KClcbiAgICAgIG9wdGlvbnMubG9nICYmIHRoaXMubG9nKGBPcGVyYXRpb24gJyR7bmFtZX0nIHRocmV3IGFuIGVycm9yYCwgeyBleGVjTVM6IGVuZE1TIC0gc3RhcnRNUywgZXJyOiBlcnIgfSlcbiAgICAgIHRoaXMubm90ZUNvdW50KGAke25hbWV9LmZhaWxgLCAxLCBkaW1zKVxuICAgICAgdGhyb3cgZXJyXG4gICAgfSBmaW5hbGx5IHtcbiAgICAgIHRoaXMubm90ZUNvdW50KGAke25hbWV9LmVuZGAsIDEsIGRpbXMpXG4gICAgICB0aGlzLm5vdGVUaW1lcihuYW1lLCBlbmRNUyAtIHN0YXJ0TVMsIGRpbXMpXG4gICAgfVxuICB9XG5cblxuICBfaW50ZXJuYWxMb2cobGV2ZWw6IHN0cmluZywgbW9kdWxlOiBzdHJpbmcsIG1lc3NhZ2U6IHN0cmluZywgZGF0YTogP2FueSwgbG9nT25seTogP2Jvb2xlYW4pIHtcbiAgICB0cnkge1xuICAgICAgLy8gY2hlY2sgaWYgbGV2ZWwgaXMgYWN0aXZhdGVkXG4gICAgICBpZiAoU3lzdGVtLmFjdGl2ZUxvZ0xldmVscyAmJiAhU3lzdGVtLmFjdGl2ZUxvZ0xldmVscy5pbmNsdWRlcyhsZXZlbCkpXG4gICAgICAgIHJldHVybiAgICAgIFxuICAgIFxuICAgICAgY29uc3QgbG9nUmVjb3JkID0ge1xuICAgICAgICBsZXZlbDogbGV2ZWwsXG4gICAgICAgIG1vZHVsZTogbW9kdWxlLFxuICAgICAgICBtZXNzYWdlOiBtZXNzYWdlLFxuICAgICAgICBkYXRhOiBfY29ycmVjdERhdGEoZGF0YSksXG4gICAgICB9XG5cbiAgICAgIC8vIGxvZyB0byBvdGhlciBkZXN0aW5hdGlvbnNcbiAgICAgIFN5c3RlbS5xdWV1ZUxvZ1JlY29yZChsb2dSZWNvcmQpXG4gICAgXG4gICAgICBpZiAoIWxvZ09ubHkpXG4gICAgICAgIHRoaXMubm90ZUNvdW50KGBsb2dnaW5nLiR7bGV2ZWx9YCwgMSlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHRocm93biBkdXJpbmcgbG9nZ2luZyBvcGVyYXRpb246ICR7ZXJyLnRvU3RyaW5nKCl9YCkgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG4gICAgfVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIF90cmFja01ldHJpY3NUb0luZmx1eERCKG1ldHJpY3M6IEFycmF5PE1ldHJpYz4pIHtcbiAgYXdhaXQgUHJvbWlzZS5hbGwoU3lzdGVtLmluZmx1eERCQ2xpZW50cy5tYXAoaWRiQ2xpZW50ID0+IGlkYkNsaWVudC50cmFja01ldHJpY3MobWV0cmljcy5tYXAobWV0cmljID0+ICh7XG4gICAgLi4ubWV0cmljLFxuICAgIHRpbWVzdGFtcE1zOiBEYXRlLm5vdygpLFxuICB9KSkpKSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gX3RyYWNrTWV0cmljVG9JbmZsdXhEQihzdGF0TmFtZTogc3RyaW5nLCB2YWx1ZTogbnVtYmVyLCBkaW1zOiBNaW5pbWFsTWV0cmljRGltZW5zaW9ucywgdGltZXN0YW1wTXM/OiA/bnVtYmVyKSB7XG4gIGF3YWl0IF90cmFja01ldHJpY3NUb0luZmx1eERCKFsgeyBzdGF0TmFtZSwgdmFsdWUsIGRpbXMsIHRpbWVzdGFtcE1zIH0gXSkgXG59XG5cbmZ1bmN0aW9uIF9jb3JyZWN0RGF0YShkYXRhOiA/YW55KTogP2FueSB7XG4gIGlmIChkYXRhICE9IG51bGwpIHtcbiAgICBpZiAoaXNFcnJvcihkYXRhKSkge1xuICAgICAgZGF0YSA9IHtcbiAgICAgICAgZXJyOiBkYXRhLFxuICAgICAgfVxuICAgIH0gXG4gICAgXG4gICAgbGV0IGl0ZXJhdGluZ0RhdGEgPSBkYXRhXG4gICAgbGV0IG1heERlcHRoID0gNFxuICAgIHdoaWxlICgtLW1heERlcHRoICYmIGl0ZXJhdGluZ0RhdGEgJiYgaXNFcnJvcihpdGVyYXRpbmdEYXRhLmVycikpIHtcbiAgICAgIC8vICRGbG93SWdub3JlXG4gICAgICBpdGVyYXRpbmdEYXRhLmVyciA9IGVycm9yVG9PYmooaXRlcmF0aW5nRGF0YS5lcnIpXG4gICAgICAvLyAkRmxvd0lnbm9yZVxuICAgICAgaXRlcmF0aW5nRGF0YSA9IGl0ZXJhdGluZ0RhdGEuZXJyLmRhdGFcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZGF0YVxufVxuIl19
\No newline at end of file