Skip to content

Commit c60a946

Browse files
authored
feat: detect supported browser APIs for core web vitals (#157)
1 parent dce0d5b commit c60a946

File tree

3 files changed

+51
-12
lines changed

3 files changed

+51
-12
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ The register method supports the following parameters.
5252
|jsErrors|Boolean|Support js errors monitoring|false|true|
5353
|apiErrors|Boolean|Support API errors monitoring|false|true|
5454
|resourceErrors|Boolean|Support resource errors monitoring|false|true|
55-
|useFmp|Boolean|Collect FMP (first meaningful paint) data of the first screen. Deprecated: This is no longer recommended. Please use the useWebVitals instead. |false|false|
55+
|useFmp|Boolean|Collect FMP (first meaningful paint) data of the first screen. Deprecated: This is no longer recommended. Please use the `useWebVitals` instead. |false|false|
5656
|enableSPA|Boolean|Monitor the page hashchange event and report PV, which is suitable for [single page application scenarios](https://github.com/apache/skywalking-client-js#spa-page). |false|false|
5757
|autoTracePerf|Boolean|Support sending of performance data automatically.|false|true|
5858
|vue|Vue|Support vue2 errors monitoring. Deprecated: This is no longer recommended. Please use the [Catching errors in frames](https://github.com/apache/skywalking-client-js#catching-errors-in-frames-including-react-angular-vue) scenario instead. |false|undefined|
@@ -61,7 +61,7 @@ The register method supports the following parameters.
6161
|noTraceOrigins|(string \| RegExp)[]|Origin in the `noTraceOrigins` list will not be traced.|false|[]|
6262
|traceTimeInterval|Number|Support setting time interval to report segments.|false|60000|
6363
|customTags|Array|Custom Tags|false|-|
64-
|useWebVitals|Boolean|Collect three core web vitals|false|false|
64+
|useWebVitals|Boolean|Collect three core web vitals. NOTE, Safari does not support all core web vitals, and Firefox does not support `CLS`.|false|false|
6565

6666
## Collect Metrics Manually
6767
Use the `setPerformance` method to report metrics at the moment of page loaded or any other moment meaningful.

src/performance/index.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,17 @@
1717

1818
import {CustomOptionsType} from '../types';
1919
import Report from '../services/report';
20-
import {prerenderChangeListener, onHidden, runOnce, idlePeriod} from "../services/eventsListener";
20+
import {prerenderChangeListener, onHidden, runOnce, idlePeriod} from '../services/eventsListener';
2121
import pagePerf from './perf';
2222
import FMP from './fmp';
23-
import {observe} from "../services/observe";
24-
import {LCPMetric, INPMetric, CLSMetric} from "./type";
25-
import {LayoutShift} from "../services/types";
26-
import {getVisibilityObserver} from "../services/getVisibilityObserver";
27-
import {getActivationStart, getResourceEntry} from "../services/getEntries";
28-
import {onBFCacheRestore} from "../services/bfcache";
29-
import {handleInteractionEntry, clearInteractions, getLongestInteraction, DEFAULT_DURATION_THRESHOLD} from "../services/interactions";
23+
import {observe} from '../services/observe';
24+
import {LCPMetric, INPMetric, CLSMetric} from './type';
25+
import {LayoutShift} from '../services/types';
26+
import {getVisibilityObserver} from '../services/getVisibilityObserver';
27+
import {getActivationStart, getResourceEntry} from '../services/getEntries';
28+
import {onBFCacheRestore} from '../services/bfcache';
29+
import {handleInteractionEntry, clearInteractions, getLongestInteraction, DEFAULT_DURATION_THRESHOLD} from '../services/interactions';
30+
import {isLayoutShiftSupported, isEventSupported, isLargestContentfulPaintSupported} from '../services/apiDetectSupported';
3031

3132
const handler = {
3233
set(target: {[key: string]: unknown}, prop: string, value: unknown) {
@@ -121,10 +122,13 @@ class TracePerf {
121122
this.INP();
122123
this.CLS();
123124
setTimeout(() => {
124-
this.coreWebMetrics.fmpTime = Math.floor(FMP.fmpTime);
125+
this.coreWebMetrics.fmpTime = Math.floor(FMP.fmpTime) || 0;
125126
}, 5000);
126127
}
127128
private CLS() {
129+
if (!isLayoutShiftSupported()) {
130+
return this.coreWebMetrics.clsTime = 0;
131+
}
128132
let partValue = 0;
129133
let entryList: LayoutShift[] = [];
130134

@@ -147,7 +151,9 @@ class TracePerf {
147151
}
148152
});
149153
if (partValue > 0) {
150-
this.coreWebMetrics.clsTime = Math.floor(partValue);
154+
setTimeout(() => {
155+
this.coreWebMetrics.clsTime = partValue;
156+
}, 3000);
151157
}
152158
};
153159

@@ -162,6 +168,9 @@ class TracePerf {
162168
});
163169
}
164170
private LCP() {
171+
if (!isLargestContentfulPaintSupported()) {
172+
return this.coreWebMetrics.lcpTime = 0;
173+
}
165174
prerenderChangeListener(() => {
166175
const visibilityObserver = getVisibilityObserver();
167176
const processEntries = (entries: LCPMetric['entries']) => {
@@ -191,6 +200,9 @@ class TracePerf {
191200
})
192201
}
193202
private INP() {
203+
if (!isEventSupported()) {
204+
return;
205+
}
194206
prerenderChangeListener(() => {
195207
const processEntries = (entries: INPMetric['entries']) => {
196208
idlePeriod(() => {

src/services/apiDetectSupported.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
export function isLayoutShiftSupported() {
18+
return PerformanceObserver.supportedEntryTypes.includes('layout-shift');
19+
}
20+
21+
export function isLargestContentfulPaintSupported() {
22+
return PerformanceObserver.supportedEntryTypes.includes('largest-contentful-paint');
23+
}
24+
25+
export function isEventSupported() {
26+
return PerformanceObserver.supportedEntryTypes.includes('event');
27+
}

0 commit comments

Comments
 (0)