quodolores
Version:
Monorepo for the Firebase JavaScript SDK
122 lines (114 loc) • 4.04 kB
text/typescript
/**
* @license
* Copyright 2020 Google LLC
*
* Licensed 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.
*/
import { Api } from './api_service';
import { Trace } from '../resources/trace';
import { createNetworkRequestEntry } from '../resources/network_request';
import { TRACE_MEASURE_PREFIX } from '../constants';
import { getIid } from './iid_service';
import { PerformanceController } from '../controllers/perf';
const FID_WAIT_TIME_MS = 5000;
export function setupOobResources(
performanceController: PerformanceController
): void {
// Do not initialize unless iid is available.
if (!getIid()) {
return;
}
// The load event might not have fired yet, and that means performance navigation timing
// object has a duration of 0. The setup should run after all current tasks in js queue.
setTimeout(() => setupOobTraces(performanceController), 0);
setTimeout(() => setupNetworkRequests(performanceController), 0);
setTimeout(() => setupUserTimingTraces(performanceController), 0);
}
function setupNetworkRequests(
performanceController: PerformanceController
): void {
const api = Api.getInstance();
const resources = api.getEntriesByType('resource');
for (const resource of resources) {
createNetworkRequestEntry(performanceController, resource);
}
api.setupObserver('resource', entry =>
createNetworkRequestEntry(performanceController, entry)
);
}
function setupOobTraces(performanceController: PerformanceController): void {
const api = Api.getInstance();
const navigationTimings = api.getEntriesByType(
'navigation'
) as PerformanceNavigationTiming[];
const paintTimings = api.getEntriesByType('paint');
// If First Input Desly polyfill is added to the page, report the fid value.
// https://github.com/GoogleChromeLabs/first-input-delay
if (api.onFirstInputDelay) {
// If the fid call back is not called for certain time, continue without it.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let timeoutId: any = setTimeout(() => {
Trace.createOobTrace(
performanceController,
navigationTimings,
paintTimings
);
timeoutId = undefined;
}, FID_WAIT_TIME_MS);
api.onFirstInputDelay((fid: number) => {
if (timeoutId) {
clearTimeout(timeoutId);
Trace.createOobTrace(
performanceController,
navigationTimings,
paintTimings,
fid
);
}
});
} else {
Trace.createOobTrace(
performanceController,
navigationTimings,
paintTimings
);
}
}
function setupUserTimingTraces(
performanceController: PerformanceController
): void {
const api = Api.getInstance();
// Run through the measure performance entries collected up to this point.
const measures = api.getEntriesByType('measure');
for (const measure of measures) {
createUserTimingTrace(performanceController, measure);
}
// Setup an observer to capture the measures from this point on.
api.setupObserver('measure', entry =>
createUserTimingTrace(performanceController, entry)
);
}
function createUserTimingTrace(
performanceController: PerformanceController,
measure: PerformanceEntry
): void {
const measureName = measure.name;
// Do not create a trace, if the user timing marks and measures are created by the sdk itself.
if (
measureName.substring(0, TRACE_MEASURE_PREFIX.length) ===
TRACE_MEASURE_PREFIX
) {
return;
}
Trace.createUserTimingTrace(performanceController, measureName);
}