This is an automated email from the ASF dual-hosted git repository. wusheng pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/skywalking-client-js.git
commit cd46b4ebf07c712553022aa23fa6eedbd133b98e Author: Qiuxia Fan <[email protected]> AuthorDate: Thu Aug 6 17:03:30 2020 +0800 feat: update perf detail --- src/monitor.ts | 8 +++++++- src/performance/fmp.ts | 47 +++++++++++------------------------------------ src/performance/index.ts | 25 +++++++++++++------------ src/performance/perf.ts | 31 +++++++------------------------ src/performance/type.d.ts | 43 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 73 deletions(-) diff --git a/src/monitor.ts b/src/monitor.ts index 7b903ba..3c405c2 100644 --- a/src/monitor.ts +++ b/src/monitor.ts @@ -65,7 +65,13 @@ const ClientMonitor = { ...this.customPerfOptions, ...options, }; - Performance.recordPerf(customPerfOptions); + if (document.readyState === 'complete') { + Performance.recordPerf(customPerfOptions); + } else { + window.addEventListener('load', () => { + Performance.recordPerf(customPerfOptions); + }, false); + } }, }; diff --git a/src/performance/fmp.ts b/src/performance/fmp.ts index 8f5e8a9..ae5f1ac 100644 --- a/src/performance/fmp.ts +++ b/src/performance/fmp.ts @@ -14,16 +14,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -function getStyle(element: Element | any, attr: any) { +import { ICalScore, Els } from './type'; + +const getStyle = (element: Element | any, attr: any) => { if (window.getComputedStyle) { return window.getComputedStyle(element, null)[attr]; } else { return element.currentStyle[attr]; } -} - -const START_TIME: number = performance.now(); -const IGNORE_TAG_SET: string[] = ['SCRIPT', 'STYLE', 'META', 'HEAD', 'LINK']; +}; enum ELE_WEIGHT { SVG = 2, @@ -34,33 +33,22 @@ enum ELE_WEIGHT { VIDEO = 4, } +const START_TIME: number = performance.now(); +const IGNORE_TAG_SET: string[] = ['SCRIPT', 'STYLE', 'META', 'HEAD', 'LINK']; const LIMIT: number = 3000; const WW: number = window.innerWidth; const WH: number = window.innerHeight; const DELAY: number = 500; -interface ICalScore { - dpss: ICalScore[]; - st: number; - els: Els; - root?: Element; -} -type Els = Array<{ - $node: Element; - st: number; - weight: number; -}>; class FMPTiming { + public fmpTime: number = 0; private statusCollector: Array<{time: number}> = []; private flag: boolean = true; private observer: MutationObserver = null; private callbackCount: number = 0; private entries: any = {}; - private fmpCallback: any = null; - constructor(fmpCallback?: (res: any) => void) { - if (fmpCallback) { - this.fmpCallback = fmpCallback; - } + + constructor() { this.initObserver(); } private getFirstSnapShot(): void { @@ -118,24 +106,11 @@ class FMPTiming { this.entries[item.name] = item.responseEnd; }); if (!tp) { - if (this.fmpCallback) { - this.fmpCallback({ - tp: null, - resultEls: [], - fmpTiming: 0, - }); - } return false; } const resultEls: Els = this.filterResult(tp.els); const fmpTiming: number = this.getFmpTime(resultEls); - if (this.fmpCallback) { - this.fmpCallback({ - tp, - resultEls, - fmpTiming, - }); - } + this.fmpTime = fmpTiming; } else { setTimeout(() => { this.calculateFinalScore(); @@ -162,7 +137,7 @@ class FMPTiming { if (match && match[1]) { url = match[1]; } - if (url.indexOf('http') === -1) { + if (!url.includes('http')) { url = location.protocol + match[1]; } time = this.entries[url]; diff --git a/src/performance/index.ts b/src/performance/index.ts index 65e0bb6..ef32ad8 100644 --- a/src/performance/index.ts +++ b/src/performance/index.ts @@ -19,27 +19,29 @@ import { CustomPerfOptionsType } from '../types'; import Report from '../services/report'; import pagePerf from './perf'; +import FMP from './fmp'; +import { IPerfDetail } from './type'; class TracePerf { private isPerf: boolean = true; private perfConfig = { - // resources: [], perfDetail: {}, - } as any; + } as { perfDetail: IPerfDetail }; - public recordPerf(options: CustomPerfOptionsType) { - setTimeout(async () => { - if (this.isPerf) { - this.perfConfig.perfDetail = await pagePerf.getPerfTiming(); - } + public async recordPerf(options: CustomPerfOptionsType) { + if (this.isPerf) { + this.perfConfig.perfDetail = await new pagePerf().getPerfTiming(); + } + const fmp: {fmpTime: number} = await new FMP(); + + setTimeout(() => { const perfInfo = { - perfDetail: this.perfConfig.perfDetail, - // resources: this.perfConfig.resources, + perfDetail: {...this.perfConfig.perfDetail, fmpTime: fmp.fmpTime}, ...options, }; new Report(options.reportUrl).sendByXhr(perfInfo); this.clearPerf(); - }, 100); + }, 5000); } private clearPerf() { @@ -48,9 +50,8 @@ class TracePerf { } window.performance.clearResourceTimings(); this.perfConfig = { - // resources: [], perfDetail: {}, - }; + } as { perfDetail: IPerfDetail }; } } diff --git a/src/performance/perf.ts b/src/performance/perf.ts index 2280447..4a62ed7 100644 --- a/src/performance/perf.ts +++ b/src/performance/perf.ts @@ -15,32 +15,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -import FMP from './fmp'; +import { IPerfDetail } from './type'; class PagePerf { - private fmpTime: number = 0; - - constructor() { - new FMP(this.getFmpTiming); - } - public getPerfTiming() { + public getPerfTiming(): IPerfDetail { try { if (!window.performance || !window.performance.timing) { console.log('your browser do not support performance'); return; } const { timing } = window.performance; - const loadTime = timing.loadEventEnd - timing.loadEventStart; let redirectTime = 0; - if (loadTime < 0) { - setTimeout(() => { - this.getPerfTiming(); - }, 3000); - return; - } - if (timing.navigationStart !== undefined) { redirectTime = timing.fetchStart - timing.navigationStart; } else if (timing.redirectEnd !== undefined) { @@ -48,6 +34,7 @@ class PagePerf { } else { redirectTime = 0; } + return { redirectTime, dnsTime: timing.domainLookupEnd - timing.domainLookupStart, @@ -59,20 +46,16 @@ class PagePerf { domReadyTime: timing.domContentLoadedEventEnd - timing.fetchStart, loadPage: timing.loadEventStart - timing.fetchStart, // Page full load time resTime: timing.loadEventStart - timing.domContentLoadedEventEnd, // Synchronous load resources in the page - sslTime: timing.connectEnd - timing.secureConnectionStart, // Only valid for HTTPS + // Only valid for HTTPS + sslTime: location.protocol.includes('https') ? timing.connectEnd - timing.secureConnectionStart : null, ttlTime: timing.domInteractive - timing.fetchStart, // time to interact firstPackTime: timing.responseStart - timing.domainLookupStart, // first pack time - fmpTime: this.fmpTime, // First Meaningful Paint + fmpTime: 0, // First Meaningful Paint }; } catch (e) { throw e; } } - - private getFmpTiming(data: any) { - console.log(data); - this.fmpTime = data.fmpTiming; - } } -export default new PagePerf(); +export default PagePerf; diff --git a/src/performance/type.d.ts b/src/performance/type.d.ts new file mode 100644 index 0000000..03435f4 --- /dev/null +++ b/src/performance/type.d.ts @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export interface ICalScore { + dpss: ICalScore[]; + st: number; + els: Els; + root?: Element; +} +export type Els = Array<{ + $node: Element; + st: number; + weight: number; +}>; +export type IPerfDetail = { + redirectTime: number | undefined; + dnsTime: number | undefined; + ttfbTime: number | undefined; // Time to First Byte + tcpTime: number | undefined; + transTime: number | undefined; + domAnalysisTime: number | undefined; + fptTime: number | undefined; // First Paint Time or Blank Screen Time + domReadyTime: number | undefined; + loadPage: number | undefined; // Page full load time + resTime: number | undefined; // Synchronous load resources in the page + sslTime: number | undefined; // Only valid for HTTPS + ttlTime: number | undefined; // time to interact + firstPackTime: number | undefined; // first pack time + fmpTime: number | undefined; // First Meaningful Paint +};
