transactionAggregator.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. 'use strict';
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. const Debug = require("debug");
  4. const eventemitter2_1 = require("eventemitter2");
  5. const EWMA_1 = require("./EWMA");
  6. const histogram_1 = require("./metrics/histogram");
  7. const fclone = (data) => JSON.parse(JSON.stringify(data));
  8. const log = Debug('axm:features:tracing:aggregator');
  9. class TransactionAggregator extends eventemitter2_1.EventEmitter2 {
  10. constructor() {
  11. super(...arguments);
  12. this.spanTypes = ['redis', 'mysql', 'pg', 'mongo', 'outbound_http'];
  13. this.cache = {
  14. routes: {},
  15. meta: {
  16. trace_count: 0,
  17. http_meter: new EWMA_1.default(),
  18. db_meter: new EWMA_1.default(),
  19. histogram: new histogram_1.default({ measurement: 'median' }),
  20. db_histograms: {}
  21. }
  22. };
  23. this.privacyRegex = /":(?!\[|{)\\"[^"]*\\"|":(["'])(?:(?=(\\?))\2.)*?\1|":(?!\[|{)[^,}\]]*|":\[[^{]*]/g;
  24. }
  25. init(sendInterval = 30000) {
  26. this.worker = setInterval(_ => {
  27. let data = this.prepareAggregationforShipping();
  28. this.emit('packet', { data });
  29. }, sendInterval);
  30. }
  31. destroy() {
  32. if (this.worker !== undefined) {
  33. clearInterval(this.worker);
  34. }
  35. this.cache.routes = {};
  36. }
  37. getAggregation() {
  38. return this.cache;
  39. }
  40. validateData(packet) {
  41. if (!packet) {
  42. log('Packet malformated', packet);
  43. return false;
  44. }
  45. if (!packet.spans || !packet.spans[0]) {
  46. log('Trace without spans: %s', Object.keys(packet.data));
  47. return false;
  48. }
  49. if (!packet.spans[0].labels) {
  50. log('Trace spans without labels: %s', Object.keys(packet.spans));
  51. return false;
  52. }
  53. return true;
  54. }
  55. aggregate(packet) {
  56. if (this.validateData(packet) === false)
  57. return false;
  58. let path = packet.spans[0].labels['http/path'];
  59. if (process.env.PM2_APM_CENSOR_SPAMS !== '0') {
  60. this.censorSpans(packet.spans);
  61. }
  62. packet.spans = packet.spans.filter((span) => {
  63. return span.endTime !== span.startTime;
  64. });
  65. packet.spans.forEach((span) => {
  66. span.mean = Math.round(new Date(span.endTime).getTime() - new Date(span.startTime).getTime());
  67. delete span.endTime;
  68. });
  69. packet.spans.forEach((span) => {
  70. if (!span.name || !span.kind)
  71. return false;
  72. if (span.kind === 'RPC_SERVER') {
  73. this.cache.meta.histogram.update(span.mean);
  74. return this.cache.meta.http_meter.update(1);
  75. }
  76. if (span.labels && span.labels['http/method'] && span.labels['http/status_code']) {
  77. span.labels['service'] = span.name;
  78. span.name = 'outbound_http';
  79. }
  80. for (let i = 0; i < this.spanTypes.length; i++) {
  81. if (span.name.indexOf(this.spanTypes[i]) > -1) {
  82. this.cache.meta.db_meter.update(1);
  83. if (!this.cache.meta.db_histograms[this.spanTypes[i]]) {
  84. this.cache.meta.db_histograms[this.spanTypes[i]] = new histogram_1.default({ measurement: 'mean' });
  85. }
  86. this.cache.meta.db_histograms[this.spanTypes[i]].update(span.mean);
  87. break;
  88. }
  89. }
  90. });
  91. this.cache.meta.trace_count++;
  92. if (path[0] === '/' && path !== '/') {
  93. path = path.substr(1, path.length - 1);
  94. }
  95. let matched = this.matchPath(path, this.cache.routes);
  96. if (!matched) {
  97. this.cache.routes[path] = [];
  98. this.mergeTrace(this.cache.routes[path], packet);
  99. }
  100. else {
  101. this.mergeTrace(this.cache.routes[matched], packet);
  102. }
  103. return this.cache;
  104. }
  105. mergeTrace(aggregated, trace) {
  106. if (!aggregated || !trace)
  107. return;
  108. if (trace.spans.length === 0)
  109. return;
  110. if (!aggregated.variances)
  111. aggregated.variances = [];
  112. if (!aggregated.meta) {
  113. aggregated.meta = {
  114. histogram: new histogram_1.default({ measurement: 'median' }),
  115. meter: new EWMA_1.default()
  116. };
  117. }
  118. aggregated.meta.histogram.update(trace.spans[0].mean);
  119. aggregated.meta.meter.update();
  120. const merge = (variance) => {
  121. if (variance == null) {
  122. delete trace.projectId;
  123. delete trace.traceId;
  124. trace.histogram = new histogram_1.default({ measurement: 'median' });
  125. trace.histogram.update(trace.spans[0].mean);
  126. trace.spans.forEach((span) => {
  127. span.histogram = new histogram_1.default({ measurement: 'median' });
  128. span.histogram.update(span.mean);
  129. delete span.mean;
  130. });
  131. aggregated.variances.push(trace);
  132. }
  133. else {
  134. variance.histogram.update(trace.spans[0].mean);
  135. this.updateSpanDuration(variance.spans, trace.spans);
  136. trace.spans.forEach((span) => {
  137. delete span.labels.stacktrace;
  138. });
  139. }
  140. };
  141. for (let i = 0; i < aggregated.variances.length; i++) {
  142. if (this.compareList(aggregated.variances[i].spans, trace.spans)) {
  143. return merge(aggregated.variances[i]);
  144. }
  145. }
  146. return merge(null);
  147. }
  148. updateSpanDuration(spans, newSpans) {
  149. for (let i = 0; i < spans.length; i++) {
  150. if (!newSpans[i])
  151. continue;
  152. spans[i].histogram.update(newSpans[i].mean);
  153. }
  154. }
  155. compareList(one, two) {
  156. if (one.length !== two.length)
  157. return false;
  158. for (let i = 0; i < one.length; i++) {
  159. if (one[i].name !== two[i].name)
  160. return false;
  161. if (one[i].kind !== two[i].kind)
  162. return false;
  163. if (!one[i].labels && two[i].labels)
  164. return false;
  165. if (one[i].labels && !two[i].labels)
  166. return false;
  167. if (one[i].labels.length !== two[i].labels.length)
  168. return false;
  169. }
  170. return true;
  171. }
  172. matchPath(path, routes) {
  173. if (!path || !routes)
  174. return false;
  175. if (path === '/')
  176. return routes[path] ? path : null;
  177. if (path[path.length - 1] === '/') {
  178. path = path.substr(0, path.length - 1);
  179. }
  180. path = path.split('/');
  181. if (path.length === 1)
  182. return routes[path[0]] ? routes[path[0]] : null;
  183. let keys = Object.keys(routes);
  184. for (let i = 0; i < keys.length; i++) {
  185. let route = keys[i];
  186. let segments = route.split('/');
  187. if (segments.length !== path.length)
  188. continue;
  189. for (let j = path.length - 1; j >= 0; j--) {
  190. if (path[j] !== segments[j]) {
  191. if (this.isIdentifier(path[j]) && segments[j] === '*' && path[j - 1] === segments[j - 1]) {
  192. return segments.join('/');
  193. }
  194. else if (path[j - 1] !== undefined && path[j - 1] === segments[j - 1] && this.isIdentifier(path[j]) && this.isIdentifier(segments[j])) {
  195. segments[j] = '*';
  196. routes[segments.join('/')] = routes[route];
  197. delete routes[keys[i]];
  198. return segments.join('/');
  199. }
  200. else {
  201. break;
  202. }
  203. }
  204. if (j === 0)
  205. return segments.join('/');
  206. }
  207. }
  208. }
  209. prepareAggregationforShipping() {
  210. let routes = this.cache.routes;
  211. const normalized = {
  212. routes: [],
  213. meta: {
  214. trace_count: this.cache.meta.trace_count,
  215. http_meter: Math.round(this.cache.meta.http_meter.rate(1000) * 100) / 100,
  216. db_meter: Math.round(this.cache.meta.db_meter.rate(1000) * 100) / 100,
  217. http_percentiles: {
  218. median: this.cache.meta.histogram.percentiles([0.5])[0.5],
  219. p95: this.cache.meta.histogram.percentiles([0.95])[0.95],
  220. p99: this.cache.meta.histogram.percentiles([0.99])[0.99]
  221. },
  222. db_percentiles: {}
  223. }
  224. };
  225. this.spanTypes.forEach((name) => {
  226. let histogram = this.cache.meta.db_histograms[name];
  227. if (!histogram)
  228. return;
  229. normalized.meta.db_percentiles[name] = histogram.percentiles([0.5])[0.5];
  230. });
  231. Object.keys(routes).forEach((path) => {
  232. let data = routes[path];
  233. if (!data.variances || data.variances.length === 0)
  234. return;
  235. const variances = data.variances.sort((a, b) => {
  236. return b.count - a.count;
  237. }).slice(0, 5);
  238. let routeCopy = {
  239. path: path === '/' ? '/' : '/' + path,
  240. meta: {
  241. min: data.meta.histogram.getMin(),
  242. max: data.meta.histogram.getMax(),
  243. count: data.meta.histogram.getCount(),
  244. meter: Math.round(data.meta.meter.rate(1000) * 100) / 100,
  245. median: data.meta.histogram.percentiles([0.5])[0.5],
  246. p95: data.meta.histogram.percentiles([0.95])[0.95]
  247. },
  248. variances: []
  249. };
  250. variances.forEach((variance) => {
  251. if (!variance.spans || variance.spans.length === 0)
  252. return;
  253. let tmp = {
  254. spans: [],
  255. count: variance.histogram.getCount(),
  256. min: variance.histogram.getMin(),
  257. max: variance.histogram.getMax(),
  258. median: variance.histogram.percentiles([0.5])[0.5],
  259. p95: variance.histogram.percentiles([0.95])[0.95]
  260. };
  261. variance.spans.forEach((oldSpan) => {
  262. const span = fclone({
  263. name: oldSpan.name,
  264. labels: oldSpan.labels,
  265. kind: oldSpan.kind,
  266. startTime: oldSpan.startTime,
  267. min: oldSpan.histogram ? oldSpan.histogram.getMin() : undefined,
  268. max: oldSpan.histogram ? oldSpan.histogram.getMax() : undefined,
  269. median: oldSpan.histogram ? oldSpan.histogram.percentiles([0.5])[0.5] : undefined
  270. });
  271. tmp.spans.push(span);
  272. });
  273. routeCopy.variances.push(tmp);
  274. });
  275. normalized.routes.push(routeCopy);
  276. });
  277. log(`sending formatted trace to remote endpoint`);
  278. return normalized;
  279. }
  280. isIdentifier(id) {
  281. id = typeof (id) !== 'string' ? id + '' : id;
  282. if (id.match(/[0-9a-f]{8}-[0-9a-f]{4}-[14][0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}|[0-9a-f]{12}[14][0-9a-f]{19}/i)) {
  283. return true;
  284. }
  285. else if (id.match(/\d+/)) {
  286. return true;
  287. }
  288. else if (id.match(/[0-9]+[a-z]+|[a-z]+[0-9]+/)) {
  289. return true;
  290. }
  291. else if (id.match(/((?:[0-9a-zA-Z]+[@\-_.][0-9a-zA-Z]+|[0-9a-zA-Z]+[@\-_.]|[@\-_.][0-9a-zA-Z]+)+)/)) {
  292. return true;
  293. }
  294. return false;
  295. }
  296. censorSpans(spans) {
  297. if (!spans)
  298. return log('spans is null');
  299. spans.forEach((span) => {
  300. if (!span.labels)
  301. return;
  302. delete span.labels.results;
  303. delete span.labels.result;
  304. delete span.spanId;
  305. delete span.parentSpanId;
  306. delete span.labels.values;
  307. delete span.labels.stacktrace;
  308. Object.keys(span.labels).forEach((key) => {
  309. if (typeof (span.labels[key]) === 'string' && key !== 'stacktrace') {
  310. span.labels[key] = span.labels[key].replace(this.privacyRegex, '\": \"?\"');
  311. }
  312. });
  313. });
  314. }
  315. }
  316. exports.TransactionAggregator = TransactionAggregator;
  317. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb25BZ2dyZWdhdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3V0aWxzL3RyYW5zYWN0aW9uQWdncmVnYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxZQUFZLENBQUE7O0FBRVosK0JBQThCO0FBQzlCLGlEQUE2QztBQUM3QyxpQ0FBeUI7QUFDekIsbURBQTJDO0FBRTNDLE1BQU0sTUFBTSxHQUFHLENBQUMsSUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtBQUNqRSxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsaUNBQWlDLENBQUMsQ0FBQTtBQTREcEQsTUFBYSxxQkFBc0IsU0FBUSw2QkFBYTtJQUF4RDs7UUFFVSxjQUFTLEdBQWEsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsZUFBZSxDQUFDLENBQUE7UUFDeEUsVUFBSyxHQUFlO1lBQzFCLE1BQU0sRUFBRSxFQUFFO1lBQ1YsSUFBSSxFQUFFO2dCQUNKLFdBQVcsRUFBRSxDQUFDO2dCQUNkLFVBQVUsRUFBRSxJQUFJLGNBQUksRUFBRTtnQkFDdEIsUUFBUSxFQUFFLElBQUksY0FBSSxFQUFFO2dCQUNwQixTQUFTLEVBQUUsSUFBSSxtQkFBUyxDQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxDQUFDO2dCQUNuRCxhQUFhLEVBQUUsRUFBRTthQUNsQjtTQUNGLENBQUE7UUFDTyxpQkFBWSxHQUFXLG1GQUFtRixDQUFBO0lBK1lwSCxDQUFDO0lBNVlDLElBQUksQ0FBRSxlQUF1QixLQUFLO1FBQ2hDLElBQUksQ0FBQyxNQUFNLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxFQUFFO1lBQzVCLElBQUksSUFBSSxHQUFHLElBQUksQ0FBQyw2QkFBNkIsRUFBRSxDQUFBO1lBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtRQUMvQixDQUFDLEVBQUUsWUFBWSxDQUFDLENBQUE7SUFDbEIsQ0FBQztJQUVELE9BQU87UUFDTCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFO1lBQzdCLGFBQWEsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7U0FDM0I7UUFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxFQUFFLENBQUE7SUFDeEIsQ0FBQztJQUVELGNBQWM7UUFDWixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUE7SUFDbkIsQ0FBQztJQUVELFlBQVksQ0FBRSxNQUFNO1FBQ2xCLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDWCxHQUFHLENBQUMsb0JBQW9CLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDakMsT0FBTyxLQUFLLENBQUE7U0FDYjtRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtZQUNyQyxHQUFHLENBQUMseUJBQXlCLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtZQUN4RCxPQUFPLEtBQUssQ0FBQTtTQUNiO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFO1lBQzNCLEdBQUcsQ0FBQyxnQ0FBZ0MsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFBO1lBQ2hFLE9BQU8sS0FBSyxDQUFBO1NBQ2I7UUFFRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7SUFPRCxTQUFTLENBQUUsTUFBTTtRQUNmLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsS0FBSyxLQUFLO1lBQUUsT0FBTyxLQUFLLENBQUE7UUFHckQsSUFBSSxJQUFJLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLENBQUE7UUFFOUMsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLG9CQUFvQixLQUFLLEdBQUcsRUFBRTtZQUM1QyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQTtTQUMvQjtRQUdELE1BQU0sQ0FBQyxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUMxQyxPQUFPLElBQUksQ0FBQyxPQUFPLEtBQUssSUFBSSxDQUFDLFNBQVMsQ0FBQTtRQUN4QyxDQUFDLENBQUMsQ0FBQTtRQUdGLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7WUFDNUIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQTtZQUM3RixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUE7UUFDckIsQ0FBQyxDQUFDLENBQUE7UUFHRixNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUk7Z0JBQUUsT0FBTyxLQUFLLENBQUE7WUFFMUMsSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFlBQVksRUFBRTtnQkFDOUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7Z0JBQzNDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQTthQUM1QztZQUdELElBQUksSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsRUFBRTtnQkFDaEYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFBO2dCQUNsQyxJQUFJLENBQUMsSUFBSSxHQUFHLGVBQWUsQ0FBQTthQUM1QjtZQUVELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDOUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUU7b0JBQzdDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUE7b0JBQ2xDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFO3dCQUNyRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksbUJBQVMsQ0FBQyxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO3FCQUMxRjtvQkFDRCxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7b0JBQ2xFLE1BQUs7aUJBQ047YUFDRjtRQUNILENBQUMsQ0FBQyxDQUFBO1FBRUYsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7UUFLN0IsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxHQUFHLEVBQUU7WUFDbkMsSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUE7U0FDdkM7UUFFRCxJQUFJLE9BQU8sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBRXJELElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDWixJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUE7WUFDNUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQTtTQUNqRDthQUFNO1lBQ0wsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQTtTQUNwRDtRQUVELE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQTtJQUNuQixDQUFDO0lBUUQsVUFBVSxDQUFFLFVBQVUsRUFBRSxLQUFLO1FBQzNCLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxLQUFLO1lBQUUsT0FBTTtRQUdqQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUM7WUFBRSxPQUFNO1FBR3BDLElBQUksQ0FBQyxVQUFVLENBQUMsU0FBUztZQUFFLFVBQVUsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFBO1FBQ3BELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFO1lBQ3BCLFVBQVUsQ0FBQyxJQUFJLEdBQUc7Z0JBQ2hCLFNBQVMsRUFBRSxJQUFJLG1CQUFTLENBQUMsRUFBRSxXQUFXLEVBQUUsUUFBUSxFQUFFLENBQUM7Z0JBQ25ELEtBQUssRUFBRSxJQUFJLGNBQUksRUFBRTthQUNsQixDQUFBO1NBQ0Y7UUFFRCxVQUFVLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNyRCxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQTtRQUU5QixNQUFNLEtBQUssR0FBRyxDQUFDLFFBQVEsRUFBRSxFQUFFO1lBRXpCLElBQUksUUFBUSxJQUFJLElBQUksRUFBRTtnQkFDcEIsT0FBTyxLQUFLLENBQUMsU0FBUyxDQUFBO2dCQUN0QixPQUFPLEtBQUssQ0FBQyxPQUFPLENBQUE7Z0JBQ3BCLEtBQUssQ0FBQyxTQUFTLEdBQUcsSUFBSSxtQkFBUyxDQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUE7Z0JBQzFELEtBQUssQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7Z0JBRTNDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7b0JBQzNCLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxtQkFBUyxDQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUE7b0JBQ3pELElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtvQkFDaEMsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFBO2dCQUNsQixDQUFDLENBQUMsQ0FBQTtnQkFJRixVQUFVLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTthQUNqQztpQkFBTTtnQkFFTCxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO2dCQUc5QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsS0FBSyxDQUFDLENBQUE7Z0JBR3BELEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUU7b0JBQzNCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUE7Z0JBQy9CLENBQUMsQ0FBQyxDQUFBO2FBQ0g7UUFDSCxDQUFDLENBQUE7UUFHRCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDcEQsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRTtnQkFDaEUsT0FBTyxLQUFLLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO2FBQ3RDO1NBQ0Y7UUFFRCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQTtJQUNwQixDQUFDO0lBT0Qsa0JBQWtCLENBQUUsS0FBSyxFQUFFLFFBQVE7UUFDakMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDckMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7Z0JBQUUsU0FBUTtZQUMxQixLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7U0FDNUM7SUFDSCxDQUFDO0lBS0QsV0FBVyxDQUFFLEdBQVUsRUFBRSxHQUFVO1FBQ2pDLElBQUksR0FBRyxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUMsTUFBTTtZQUFFLE9BQU8sS0FBSyxDQUFBO1FBRTNDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ25DLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQkFBRSxPQUFPLEtBQUssQ0FBQTtZQUM3QyxJQUFJLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0JBQUUsT0FBTyxLQUFLLENBQUE7WUFDN0MsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07Z0JBQUUsT0FBTyxLQUFLLENBQUE7WUFDakQsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07Z0JBQUUsT0FBTyxLQUFLLENBQUE7WUFDakQsSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU07Z0JBQUUsT0FBTyxLQUFLLENBQUE7U0FDaEU7UUFDRCxPQUFPLElBQUksQ0FBQTtJQUNiLENBQUM7SUFLRCxTQUFTLENBQUUsSUFBSSxFQUFFLE1BQU07UUFFckIsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPLEtBQUssQ0FBQTtRQUNsQyxJQUFJLElBQUksS0FBSyxHQUFHO1lBQUUsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO1FBR25ELElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFO1lBQ2pDLElBQUksR0FBRyxJQUFJLENBQUMs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