diff --git a/lib/client/hijack/wrapDynamicImport.js b/lib/client/hijack/wrapDynamicImport.js index a83ab609..9939df4b 100644 --- a/lib/client/hijack/wrapDynamicImport.js +++ b/lib/client/hijack/wrapDynamicImport.js @@ -1,20 +1,20 @@ import { Ntp } from '../../ntp'; const meteorInstall = require('meteor/modules').meteorInstall; -let oldFetch; +let oldMeteorInstallFetch; export function wrapDynamicImport () { - oldFetch = meteorInstall.fetch; + oldMeteorInstallFetch = meteorInstall.fetch; meteorInstall.fetch = function (ids) { const start = Ntp._now(); - const promise = oldFetch(ids); + const promise = oldMeteorInstallFetch(ids); Kadira.webVitals.pendingObjects += 1; return promise.then((...args) => { - Kadira.webVitals.importTime.push({start, end: Ntp._now(), ids}); + Kadira.webVitals.importTime.push({start, end: Ntp._now(), ids: Object.keys(ids)}); Kadira.webVitals.completedObjects += 1; return Promise.resolve(...args); }); }; } export function unwrapDynamicImport () { - meteorInstall.fetch = oldFetch; + meteorInstall.fetch = oldMeteorInstallFetch; } diff --git a/lib/client/models/webVitals.js b/lib/client/models/webVitals.js index 822a2f81..5ac44e4d 100644 --- a/lib/client/models/webVitals.js +++ b/lib/client/models/webVitals.js @@ -13,7 +13,7 @@ function calculateTimeframe (array) { if (current.end > acc.lastEnd) { acc.lastEnd = current.end; } - if (current.start > acc.firstStart) { + if (current.start < acc.firstStart) { acc.firstStart = current.start; } return acc; @@ -32,6 +32,7 @@ export class WebVitalsModel { sent = false; pendingObjects = 0; completedObjects = 0; + dynamicImportTransferedSize = 0; addToQueue (metric) { this.queue.add({ metric: metric.value, metricName: metric.name }); @@ -41,12 +42,19 @@ export class WebVitalsModel { if (this.sent) { return; } - navigator.sendBeacon(`${Kadira.options.endpoint}/client-metrics`, this._buildPayload([...this.queue])); + const payload = this._buildPayload([...this.queue]); + navigator.sendBeacon(`${Kadira.options.endpoint}/client-metrics`, JSON.stringify(payload)); this.sent = true; } stopTracking () { unwrapDynamicImport(); + this.dynamicImportTransferedSize = performance.getEntriesByType('resource') + .filter(b => b.name.includes('/__meteor__/dynamic-import/fetch')) + .reduce((acc, cur) => { + acc += cur.transferSize; + return acc; + }, 0); unwrapSubscription(); unwrapMethodCall(); if (this.pendingObjects > 0 && this.pendingObjects === this.completedObjects) this.flushQueue(); @@ -142,7 +150,7 @@ export class WebVitalsModel { if (current.responseEnd > acc.lastResponseEnd) { acc.lastResponseEnd = current.responseEnd; } - if (current.startTime > acc.firstStartTime) { + if (current.startTime < acc.firstStartTime) { acc.firstStartTime = current.startTime; } return acc; @@ -151,8 +159,8 @@ export class WebVitalsModel { metrics.resourcesTotalSize = totalSize; metrics.cachedResourcesTotalSize = cachedSize; // resources timeline - metrics.resourcesRequestStart = firstStartTime - this.startTime; - metrics.resourcesResponseEnd = lastResponseEnd - this.startTime; + metrics.resourcesRequestStart = firstStartTime; + metrics.resourcesResponseEnd = lastResponseEnd; metricsArray.forEach(m => { @@ -168,26 +176,34 @@ export class WebVitalsModel { // dynamic import time is an array metrics.dynamicImportTime = this.importTime; + metrics.dynamicImportTransferedSize = this.dynamicImportTransferedSize; // aggregate dynamic import metrics - const {lastEnd: importsEnd, firstStart: importsStart} = calculateTimeframe(this.importTime); - metrics.importsStart = importsStart - this.startTime; - metrics.importsEnd = importsEnd - this.startTime; - + if (this.importTime.length) { + const {lastEnd: importsEnd, firstStart: importsStart} = calculateTimeframe(this.importTime); + metrics.importsStart = importsStart - this.startTime; + metrics.importsEnd = importsEnd - this.startTime; + } // aggregate methods metrics - const {lastEnd: methodsEnd, firstStart: methodsStart} = calculateTimeframe(this.methods); - metrics.methodsStart = methodsStart - this.startTime; - metrics.methodsEnd = methodsEnd - this.startTime; + if (this.methods.length) { + const {lastEnd: methodsEnd, firstStart: methodsStart} = calculateTimeframe(this.methods); + metrics.methodsStart = methodsStart - this.startTime; + metrics.methodsEnd = methodsEnd - this.startTime; + } // aggregate subs metrics - const {lastEnd: subsEnd, firstStart: subsStart} = calculateTimeframe(this.subs); - metrics.subsStart = subsStart - this.startTime; - metrics.subsEnd = subsEnd - this.startTime; - - + if (this.subs.length) { + const {lastEnd: subsEnd, firstStart: subsStart} = calculateTimeframe(this.subs); + metrics.subsStart = subsStart - this.startTime; + metrics.subsEnd = subsEnd - this.startTime; + } const payload = { recordIPAddress: Kadira.options.recordIPAddress, - metrics, + // round all metrics to the nearest integer + metrics: Object.entries(metrics).reduce((acc,[key, value]) => { + acc[key] = Math.round(value); + return acc; + },{}), ...browserInfo, commitHash: Meteor.gitCommitHash, cacheCleaned: !localStorage?.length && !sessionStorage?.length,