New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@firebase/performance

Package Overview
Dependencies
Maintainers
4
Versions
2798
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@firebase/performance - npm Package Compare versions

Comparing version 0.6.12-canary.3c1559b7e to 0.6.12-canary.59ae45e48

dist/esm/src/resources/web_vitals.d.ts

276

dist/esm/index.esm2017.js
import { ErrorFactory, areCookiesEnabled, isIndexedDBAvailable, validateIndexedDBOpenable, getModularInstance, deepEqual } from '@firebase/util';
import { Logger, LogLevel } from '@firebase/logger';
import { onLCP, onINP, onCLS } from 'web-vitals/attribution';
import { _getProvider, getApp, _registerComponent, registerVersion } from '@firebase/app';

@@ -8,3 +9,3 @@ import { Component } from '@firebase/component';

const name = "@firebase/performance";
const version = "0.6.12-canary.3c1559b7e";
const version = "0.6.12-canary.59ae45e48";

@@ -39,2 +40,8 @@ /**

const FIRST_INPUT_DELAY_COUNTER_NAME = '_fid';
const LARGEST_CONTENTFUL_PAINT_METRIC_NAME = '_lcp';
const LARGEST_CONTENTFUL_PAINT_ATTRIBUTE_NAME = 'lcp_element';
const INTERACTION_TO_NEXT_PAINT_METRIC_NAME = '_inp';
const INTERACTION_TO_NEXT_PAINT_ATTRIBUTE_NAME = 'inp_interactionTarget';
const CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME = '_cls';
const CUMULATIVE_LAYOUT_SHIFT_ATTRIBUTE_NAME = 'cls_largestShiftTarget';
const CONFIG_LOCAL_STORAGE_KEY = '@firebase/performance/config';

@@ -144,2 +151,5 @@ const CONFIG_EXPIRY_LOCAL_STORAGE_KEY = '@firebase/performance/configexpire';

}
this.onLCP = onLCP;
this.onINP = onINP;
this.onCLS = onCLS;
}

@@ -698,5 +708,4 @@ getUrl() {

const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;
// If end point does not work, the call will be tried for these many times.
const MAX_EVENT_COUNT_PER_REQUEST = 1000;
const DEFAULT_REMAINING_TRIES = 3;
const MAX_EVENT_COUNT_PER_REQUEST = 1000;
let remainingTries = DEFAULT_REMAINING_TRIES;

@@ -718,7 +727,6 @@ /* eslint-enable camelcase */

}
// If there are no events to process, wait for DEFAULT_SEND_INTERVAL_MS and try again.
if (!queue.length) {
return processQueue(DEFAULT_SEND_INTERVAL_MS);
if (queue.length > 0) {
dispatchQueueEvents();
}
dispatchQueueEvents();
processQueue(DEFAULT_SEND_INTERVAL_MS);
}, timeOffset);

@@ -747,3 +755,7 @@ }

/* eslint-enable camelcase */
sendEventsToFl(data, staged).catch(() => {
postToFlEndpoint(data)
.then(() => {
remainingTries = DEFAULT_REMAINING_TRIES;
})
.catch(() => {
// If the request fails for some reason, add the events that were attempted

@@ -757,37 +769,12 @@ // back to the primary queue to retry later.

}
function sendEventsToFl(data, staged) {
return postToFlEndpoint(data)
.then(res => {
if (!res.ok) {
consoleLogger.info('Call to Firebase backend failed.');
}
return res.json();
})
.then(res => {
// Find the next call wait time from the response.
const transportWait = Number(res.nextRequestWaitMillis);
let requestOffset = DEFAULT_SEND_INTERVAL_MS;
if (!isNaN(transportWait)) {
requestOffset = Math.max(transportWait, requestOffset);
}
// Delete request if response include RESPONSE_ACTION_UNKNOWN or DELETE_REQUEST action.
// Otherwise, retry request using normal scheduling if response include RETRY_REQUEST_LATER.
const logResponseDetails = res.logResponseDetails;
if (Array.isArray(logResponseDetails) &&
logResponseDetails.length > 0 &&
logResponseDetails[0].responseAction === 'RETRY_REQUEST_LATER') {
queue = [...staged, ...queue];
consoleLogger.info(`Retry transport request later.`);
}
remainingTries = DEFAULT_REMAINING_TRIES;
// Schedule the next process.
processQueue(requestOffset);
});
}
function postToFlEndpoint(data) {
const flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
return fetch(flTransportFullUrl, {
method: 'POST',
body: JSON.stringify(data)
});
const body = JSON.stringify(data);
return navigator.sendBeacon && navigator.sendBeacon(flTransportFullUrl, body)
? Promise.resolve()
: fetch(flTransportFullUrl, {
method: 'POST',
body,
keepalive: true
}).then();
}

@@ -813,2 +800,11 @@ function addToQueue(evt) {

}
/**
* Force flush the queued events. Useful at page unload time to ensure all
* events are uploaded.
*/
function flushQueuedEvents() {
while (queue.length > 0) {
dispatchQueueEvents();
}
}

@@ -832,8 +828,12 @@ /**

let logger;
//
// This method is not called before initialization.
function sendLog(resource, resourceType) {
if (!logger) {
logger = transportHandler(serializer);
logger = {
send: transportHandler(serializer),
flush: flushQueuedEvents
};
}
logger(resource, resourceType);
logger.send(resource, resourceType);
}

@@ -854,6 +854,2 @@ function logTrace(trace) {

}
// Only log the page load auto traces if page is visible.
if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) {
return;
}
if (isPerfInitialized()) {

@@ -868,2 +864,7 @@ sendTraceLog(trace);

}
function flushLogs() {
if (logger) {
logger.flush();
}
}
function sendTraceLog(trace) {

@@ -878,3 +879,3 @@ if (!getIid()) {

}
setTimeout(() => sendLog(trace, 1 /* ResourceType.Trace */), 0);
sendLog(trace, 1 /* ResourceType.Trace */);
}

@@ -902,3 +903,3 @@ function logNetworkRequest(networkRequest) {

}
setTimeout(() => sendLog(networkRequest, 0 /* ResourceType.NetworkRequest */), 0);
sendLog(networkRequest, 0 /* ResourceType.NetworkRequest */);
}

@@ -979,2 +980,42 @@ function serializer(resource, resourceType) {

*/
function createNetworkRequestEntry(performanceController, entry) {
const performanceEntry = entry;
if (!performanceEntry || performanceEntry.responseStart === undefined) {
return;
}
const timeOrigin = Api.getInstance().getTimeOrigin();
const startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
const timeToResponseInitiatedUs = performanceEntry.responseStart
? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
: undefined;
const timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
// Remove the query params from logged network request url.
const url = performanceEntry.name && performanceEntry.name.split('?')[0];
const networkRequest = {
performanceController,
url,
responsePayloadBytes: performanceEntry.transferSize,
startTimeUs,
timeToResponseInitiatedUs,
timeToResponseCompletedUs
};
logNetworkRequest(networkRequest);
}
/**
* @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.
*/
const MAX_METRIC_NAME_LENGTH = 100;

@@ -985,3 +1026,6 @@ const RESERVED_AUTO_PREFIX = '_';

FIRST_CONTENTFUL_PAINT_COUNTER_NAME,
FIRST_INPUT_DELAY_COUNTER_NAME
FIRST_INPUT_DELAY_COUNTER_NAME,
LARGEST_CONTENTFUL_PAINT_METRIC_NAME,
CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME,
INTERACTION_TO_NEXT_PAINT_METRIC_NAME
];

@@ -1225,3 +1269,3 @@ /**

*/
static createOobTrace(performanceController, navigationTimings, paintTimings, firstInputDelay) {
static createOobTrace(performanceController, navigationTimings, paintTimings, webVitalMetrics, firstInputDelay) {
const route = Api.getInstance().getUrl();

@@ -1256,4 +1300,18 @@ if (!route) {

}
this.addWebVitalMetric(trace, LARGEST_CONTENTFUL_PAINT_METRIC_NAME, LARGEST_CONTENTFUL_PAINT_ATTRIBUTE_NAME, webVitalMetrics.lcp);
this.addWebVitalMetric(trace, CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME, CUMULATIVE_LAYOUT_SHIFT_ATTRIBUTE_NAME, webVitalMetrics.cls);
this.addWebVitalMetric(trace, INTERACTION_TO_NEXT_PAINT_METRIC_NAME, INTERACTION_TO_NEXT_PAINT_ATTRIBUTE_NAME, webVitalMetrics.inp);
// Page load logs are sent at unload time and so should be logged and
// flushed immediately.
logTrace(trace);
flushLogs();
}
static addWebVitalMetric(trace, metricKey, attributeKey, metric) {
if (metric) {
trace.putMetric(metricKey, Math.floor(metric.value * 1000));
if (metric.elementAttribution) {
trace.putAttribute(attributeKey, metric.elementAttribution);
}
}
}
static createUserTimingTrace(performanceController, measureName) {

@@ -1281,43 +1339,5 @@ const trace = new Trace(performanceController, measureName, false, measureName);

*/
function createNetworkRequestEntry(performanceController, entry) {
const performanceEntry = entry;
if (!performanceEntry || performanceEntry.responseStart === undefined) {
return;
}
const timeOrigin = Api.getInstance().getTimeOrigin();
const startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
const timeToResponseInitiatedUs = performanceEntry.responseStart
? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
: undefined;
const timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
// Remove the query params from logged network request url.
const url = performanceEntry.name && performanceEntry.name.split('?')[0];
const networkRequest = {
performanceController,
url,
responsePayloadBytes: performanceEntry.transferSize,
startTimeUs,
timeToResponseInitiatedUs,
timeToResponseCompletedUs
};
logNetworkRequest(networkRequest);
}
/**
* @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.
*/
const FID_WAIT_TIME_MS = 5000;
let webVitalMetrics = {};
let sentPageLoadTrace = false;
let firstInputDelay;
function setupOobResources(performanceController) {

@@ -1328,4 +1348,5 @@ // Do not initialize unless iid is available.

}
// 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.
// 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);

@@ -1345,23 +1366,40 @@ setTimeout(() => setupNetworkRequests(performanceController), 0);

const api = Api.getInstance();
const navigationTimings = api.getEntriesByType('navigation');
const paintTimings = api.getEntriesByType('paint');
// If First Input Delay polyfill is added to the page, report the fid value.
// https://github.com/GoogleChromeLabs/first-input-delay
// Better support for Safari
if ('onpagehide' in window) {
api.document.addEventListener('pagehide', () => sendOobTrace(performanceController));
}
else {
api.document.addEventListener('unload', () => sendOobTrace(performanceController));
}
api.document.addEventListener('visibilitychange', () => {
if (api.document.visibilityState === 'hidden') {
sendOobTrace(performanceController);
}
});
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 = setTimeout(() => {
Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
timeoutId = undefined;
}, FID_WAIT_TIME_MS);
api.onFirstInputDelay((fid) => {
if (timeoutId) {
clearTimeout(timeoutId);
Trace.createOobTrace(performanceController, navigationTimings, paintTimings, fid);
}
firstInputDelay = fid;
});
}
else {
Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
}
api.onLCP((metric) => {
var _a;
webVitalMetrics.lcp = {
value: metric.value,
elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.element
};
});
api.onCLS((metric) => {
var _a;
webVitalMetrics.cls = {
value: metric.value,
elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.largestShiftTarget
};
});
api.onINP((metric) => {
var _a;
webVitalMetrics.inp = {
value: metric.value,
elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.interactionTarget
};
});
}

@@ -1380,3 +1418,4 @@ function setupUserTimingTraces(performanceController) {

const measureName = measure.name;
// Do not create a trace, if the user timing marks and measures are created by the sdk itself.
// 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) ===

@@ -1388,2 +1427,15 @@ TRACE_MEASURE_PREFIX) {

}
function sendOobTrace(performanceController) {
if (!sentPageLoadTrace) {
sentPageLoadTrace = true;
const api = Api.getInstance();
const navigationTimings = api.getEntriesByType('navigation');
const paintTimings = api.getEntriesByType('paint');
// On page unload web vitals may be updated so queue the oob trace creation
// so that these updates have time to be included.
setTimeout(() => {
Trace.createOobTrace(performanceController, navigationTimings, paintTimings, webVitalMetrics, firstInputDelay);
}, 0);
}
}

@@ -1390,0 +1442,0 @@ /**

@@ -29,2 +29,8 @@ /**

export declare const FIRST_INPUT_DELAY_COUNTER_NAME = "_fid";
export declare const LARGEST_CONTENTFUL_PAINT_METRIC_NAME = "_lcp";
export declare const LARGEST_CONTENTFUL_PAINT_ATTRIBUTE_NAME = "lcp_element";
export declare const INTERACTION_TO_NEXT_PAINT_METRIC_NAME = "_inp";
export declare const INTERACTION_TO_NEXT_PAINT_ATTRIBUTE_NAME = "inp_interactionTarget";
export declare const CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME = "_cls";
export declare const CUMULATIVE_LAYOUT_SHIFT_ATTRIBUTE_NAME = "cls_largestShiftTarget";
export declare const CONFIG_LOCAL_STORAGE_KEY = "@firebase/performance/config";

@@ -31,0 +37,0 @@ export declare const CONFIG_EXPIRY_LOCAL_STORAGE_KEY = "@firebase/performance/configexpire";

@@ -19,2 +19,3 @@ /**

import { PerformanceController } from '../controllers/perf';
import { CoreVitalMetric, WebVitalMetrics } from './web_vitals';
export declare class Trace implements PerformanceTrace {

@@ -118,4 +119,5 @@ readonly performanceController: PerformanceController;

*/
static createOobTrace(performanceController: PerformanceController, navigationTimings: PerformanceNavigationTiming[], paintTimings: PerformanceEntry[], firstInputDelay?: number): void;
static createOobTrace(performanceController: PerformanceController, navigationTimings: PerformanceNavigationTiming[], paintTimings: PerformanceEntry[], webVitalMetrics: WebVitalMetrics, firstInputDelay?: number): void;
static addWebVitalMetric(trace: Trace, metricKey: string, attributeKey: string, metric?: CoreVitalMetric): void;
static createUserTimingTrace(performanceController: PerformanceController, measureName: string): void;
}

@@ -17,2 +17,3 @@ /**

*/
import { CLSMetricWithAttribution, INPMetricWithAttribution, LCPMetricWithAttribution } from 'web-vitals/attribution';
declare global {

@@ -38,2 +39,5 @@ interface Window {

readonly onFirstInputDelay?: (fn: (fid: number) => void) => void;
readonly onLCP: (fn: (metric: LCPMetricWithAttribution) => void) => void;
readonly onINP: (fn: (metric: INPMetricWithAttribution) => void) => void;
readonly onCLS: (fn: (metric: CLSMetricWithAttribution) => void) => void;
readonly localStorage?: Storage;

@@ -40,0 +44,0 @@ readonly document: Document;

@@ -19,1 +19,6 @@ /**

export declare function setupOobResources(performanceController: PerformanceController): void;
/**
* This service will only export the page load trace once. This function allows
* resetting it for unit tests
*/
export declare function resetForUnitTests(): void;

@@ -20,2 +20,3 @@ /**

export declare function logTrace(trace: Trace): void;
export declare function flushLogs(): void;
export declare function logNetworkRequest(networkRequest: NetworkRequest): void;

@@ -24,1 +24,6 @@ /**

export declare function transportHandler(serializer: (...args: any[]) => string): (...args: unknown[]) => void;
/**
* Force flush the queued events. Useful at page unload time to ensure all
* events are uploaded.
*/
export declare function flushQueuedEvents(): void;

@@ -7,2 +7,3 @@ 'use strict';

var logger$1 = require('@firebase/logger');
var attribution = require('web-vitals/attribution');
var app = require('@firebase/app');

@@ -13,3 +14,3 @@ var component = require('@firebase/component');

const name = "@firebase/performance";
const version = "0.6.12-canary.3c1559b7e";
const version = "0.6.12-canary.59ae45e48";

@@ -44,2 +45,8 @@ /**

const FIRST_INPUT_DELAY_COUNTER_NAME = '_fid';
const LARGEST_CONTENTFUL_PAINT_METRIC_NAME = '_lcp';
const LARGEST_CONTENTFUL_PAINT_ATTRIBUTE_NAME = 'lcp_element';
const INTERACTION_TO_NEXT_PAINT_METRIC_NAME = '_inp';
const INTERACTION_TO_NEXT_PAINT_ATTRIBUTE_NAME = 'inp_interactionTarget';
const CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME = '_cls';
const CUMULATIVE_LAYOUT_SHIFT_ATTRIBUTE_NAME = 'cls_largestShiftTarget';
const CONFIG_LOCAL_STORAGE_KEY = '@firebase/performance/config';

@@ -149,2 +156,5 @@ const CONFIG_EXPIRY_LOCAL_STORAGE_KEY = '@firebase/performance/configexpire';

}
this.onLCP = attribution.onLCP;
this.onINP = attribution.onINP;
this.onCLS = attribution.onCLS;
}

@@ -703,5 +713,4 @@ getUrl() {

const INITIAL_SEND_TIME_DELAY_MS = 5.5 * 1000;
// If end point does not work, the call will be tried for these many times.
const MAX_EVENT_COUNT_PER_REQUEST = 1000;
const DEFAULT_REMAINING_TRIES = 3;
const MAX_EVENT_COUNT_PER_REQUEST = 1000;
let remainingTries = DEFAULT_REMAINING_TRIES;

@@ -723,7 +732,6 @@ /* eslint-enable camelcase */

}
// If there are no events to process, wait for DEFAULT_SEND_INTERVAL_MS and try again.
if (!queue.length) {
return processQueue(DEFAULT_SEND_INTERVAL_MS);
if (queue.length > 0) {
dispatchQueueEvents();
}
dispatchQueueEvents();
processQueue(DEFAULT_SEND_INTERVAL_MS);
}, timeOffset);

@@ -752,3 +760,7 @@ }

/* eslint-enable camelcase */
sendEventsToFl(data, staged).catch(() => {
postToFlEndpoint(data)
.then(() => {
remainingTries = DEFAULT_REMAINING_TRIES;
})
.catch(() => {
// If the request fails for some reason, add the events that were attempted

@@ -762,37 +774,12 @@ // back to the primary queue to retry later.

}
function sendEventsToFl(data, staged) {
return postToFlEndpoint(data)
.then(res => {
if (!res.ok) {
consoleLogger.info('Call to Firebase backend failed.');
}
return res.json();
})
.then(res => {
// Find the next call wait time from the response.
const transportWait = Number(res.nextRequestWaitMillis);
let requestOffset = DEFAULT_SEND_INTERVAL_MS;
if (!isNaN(transportWait)) {
requestOffset = Math.max(transportWait, requestOffset);
}
// Delete request if response include RESPONSE_ACTION_UNKNOWN or DELETE_REQUEST action.
// Otherwise, retry request using normal scheduling if response include RETRY_REQUEST_LATER.
const logResponseDetails = res.logResponseDetails;
if (Array.isArray(logResponseDetails) &&
logResponseDetails.length > 0 &&
logResponseDetails[0].responseAction === 'RETRY_REQUEST_LATER') {
queue = [...staged, ...queue];
consoleLogger.info(`Retry transport request later.`);
}
remainingTries = DEFAULT_REMAINING_TRIES;
// Schedule the next process.
processQueue(requestOffset);
});
}
function postToFlEndpoint(data) {
const flTransportFullUrl = SettingsService.getInstance().getFlTransportFullUrl();
return fetch(flTransportFullUrl, {
method: 'POST',
body: JSON.stringify(data)
});
const body = JSON.stringify(data);
return navigator.sendBeacon && navigator.sendBeacon(flTransportFullUrl, body)
? Promise.resolve()
: fetch(flTransportFullUrl, {
method: 'POST',
body,
keepalive: true
}).then();
}

@@ -818,2 +805,11 @@ function addToQueue(evt) {

}
/**
* Force flush the queued events. Useful at page unload time to ensure all
* events are uploaded.
*/
function flushQueuedEvents() {
while (queue.length > 0) {
dispatchQueueEvents();
}
}

@@ -837,8 +833,12 @@ /**

let logger;
//
// This method is not called before initialization.
function sendLog(resource, resourceType) {
if (!logger) {
logger = transportHandler(serializer);
logger = {
send: transportHandler(serializer),
flush: flushQueuedEvents
};
}
logger(resource, resourceType);
logger.send(resource, resourceType);
}

@@ -859,6 +859,2 @@ function logTrace(trace) {

}
// Only log the page load auto traces if page is visible.
if (trace.isAuto && getVisibilityState() !== VisibilityState.VISIBLE) {
return;
}
if (isPerfInitialized()) {

@@ -873,2 +869,7 @@ sendTraceLog(trace);

}
function flushLogs() {
if (logger) {
logger.flush();
}
}
function sendTraceLog(trace) {

@@ -883,3 +884,3 @@ if (!getIid()) {

}
setTimeout(() => sendLog(trace, 1 /* ResourceType.Trace */), 0);
sendLog(trace, 1 /* ResourceType.Trace */);
}

@@ -907,3 +908,3 @@ function logNetworkRequest(networkRequest) {

}
setTimeout(() => sendLog(networkRequest, 0 /* ResourceType.NetworkRequest */), 0);
sendLog(networkRequest, 0 /* ResourceType.NetworkRequest */);
}

@@ -984,2 +985,42 @@ function serializer(resource, resourceType) {

*/
function createNetworkRequestEntry(performanceController, entry) {
const performanceEntry = entry;
if (!performanceEntry || performanceEntry.responseStart === undefined) {
return;
}
const timeOrigin = Api.getInstance().getTimeOrigin();
const startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
const timeToResponseInitiatedUs = performanceEntry.responseStart
? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
: undefined;
const timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
// Remove the query params from logged network request url.
const url = performanceEntry.name && performanceEntry.name.split('?')[0];
const networkRequest = {
performanceController,
url,
responsePayloadBytes: performanceEntry.transferSize,
startTimeUs,
timeToResponseInitiatedUs,
timeToResponseCompletedUs
};
logNetworkRequest(networkRequest);
}
/**
* @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.
*/
const MAX_METRIC_NAME_LENGTH = 100;

@@ -990,3 +1031,6 @@ const RESERVED_AUTO_PREFIX = '_';

FIRST_CONTENTFUL_PAINT_COUNTER_NAME,
FIRST_INPUT_DELAY_COUNTER_NAME
FIRST_INPUT_DELAY_COUNTER_NAME,
LARGEST_CONTENTFUL_PAINT_METRIC_NAME,
CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME,
INTERACTION_TO_NEXT_PAINT_METRIC_NAME
];

@@ -1230,3 +1274,3 @@ /**

*/
static createOobTrace(performanceController, navigationTimings, paintTimings, firstInputDelay) {
static createOobTrace(performanceController, navigationTimings, paintTimings, webVitalMetrics, firstInputDelay) {
const route = Api.getInstance().getUrl();

@@ -1261,4 +1305,18 @@ if (!route) {

}
this.addWebVitalMetric(trace, LARGEST_CONTENTFUL_PAINT_METRIC_NAME, LARGEST_CONTENTFUL_PAINT_ATTRIBUTE_NAME, webVitalMetrics.lcp);
this.addWebVitalMetric(trace, CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME, CUMULATIVE_LAYOUT_SHIFT_ATTRIBUTE_NAME, webVitalMetrics.cls);
this.addWebVitalMetric(trace, INTERACTION_TO_NEXT_PAINT_METRIC_NAME, INTERACTION_TO_NEXT_PAINT_ATTRIBUTE_NAME, webVitalMetrics.inp);
// Page load logs are sent at unload time and so should be logged and
// flushed immediately.
logTrace(trace);
flushLogs();
}
static addWebVitalMetric(trace, metricKey, attributeKey, metric) {
if (metric) {
trace.putMetric(metricKey, Math.floor(metric.value * 1000));
if (metric.elementAttribution) {
trace.putAttribute(attributeKey, metric.elementAttribution);
}
}
}
static createUserTimingTrace(performanceController, measureName) {

@@ -1286,43 +1344,5 @@ const trace = new Trace(performanceController, measureName, false, measureName);

*/
function createNetworkRequestEntry(performanceController, entry) {
const performanceEntry = entry;
if (!performanceEntry || performanceEntry.responseStart === undefined) {
return;
}
const timeOrigin = Api.getInstance().getTimeOrigin();
const startTimeUs = Math.floor((performanceEntry.startTime + timeOrigin) * 1000);
const timeToResponseInitiatedUs = performanceEntry.responseStart
? Math.floor((performanceEntry.responseStart - performanceEntry.startTime) * 1000)
: undefined;
const timeToResponseCompletedUs = Math.floor((performanceEntry.responseEnd - performanceEntry.startTime) * 1000);
// Remove the query params from logged network request url.
const url = performanceEntry.name && performanceEntry.name.split('?')[0];
const networkRequest = {
performanceController,
url,
responsePayloadBytes: performanceEntry.transferSize,
startTimeUs,
timeToResponseInitiatedUs,
timeToResponseCompletedUs
};
logNetworkRequest(networkRequest);
}
/**
* @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.
*/
const FID_WAIT_TIME_MS = 5000;
let webVitalMetrics = {};
let sentPageLoadTrace = false;
let firstInputDelay;
function setupOobResources(performanceController) {

@@ -1333,4 +1353,5 @@ // Do not initialize unless iid is available.

}
// 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.
// 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);

@@ -1350,23 +1371,40 @@ setTimeout(() => setupNetworkRequests(performanceController), 0);

const api = Api.getInstance();
const navigationTimings = api.getEntriesByType('navigation');
const paintTimings = api.getEntriesByType('paint');
// If First Input Delay polyfill is added to the page, report the fid value.
// https://github.com/GoogleChromeLabs/first-input-delay
// Better support for Safari
if ('onpagehide' in window) {
api.document.addEventListener('pagehide', () => sendOobTrace(performanceController));
}
else {
api.document.addEventListener('unload', () => sendOobTrace(performanceController));
}
api.document.addEventListener('visibilitychange', () => {
if (api.document.visibilityState === 'hidden') {
sendOobTrace(performanceController);
}
});
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 = setTimeout(() => {
Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
timeoutId = undefined;
}, FID_WAIT_TIME_MS);
api.onFirstInputDelay((fid) => {
if (timeoutId) {
clearTimeout(timeoutId);
Trace.createOobTrace(performanceController, navigationTimings, paintTimings, fid);
}
firstInputDelay = fid;
});
}
else {
Trace.createOobTrace(performanceController, navigationTimings, paintTimings);
}
api.onLCP((metric) => {
var _a;
webVitalMetrics.lcp = {
value: metric.value,
elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.element
};
});
api.onCLS((metric) => {
var _a;
webVitalMetrics.cls = {
value: metric.value,
elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.largestShiftTarget
};
});
api.onINP((metric) => {
var _a;
webVitalMetrics.inp = {
value: metric.value,
elementAttribution: (_a = metric.attribution) === null || _a === void 0 ? void 0 : _a.interactionTarget
};
});
}

@@ -1385,3 +1423,4 @@ function setupUserTimingTraces(performanceController) {

const measureName = measure.name;
// Do not create a trace, if the user timing marks and measures are created by the sdk itself.
// 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) ===

@@ -1393,2 +1432,15 @@ TRACE_MEASURE_PREFIX) {

}
function sendOobTrace(performanceController) {
if (!sentPageLoadTrace) {
sentPageLoadTrace = true;
const api = Api.getInstance();
const navigationTimings = api.getEntriesByType('navigation');
const paintTimings = api.getEntriesByType('paint');
// On page unload web vitals may be updated so queue the oob trace creation
// so that these updates have time to be included.
setTimeout(() => {
Trace.createOobTrace(performanceController, navigationTimings, paintTimings, webVitalMetrics, firstInputDelay);
}, 0);
}
}

@@ -1395,0 +1447,0 @@ /**

@@ -29,2 +29,8 @@ /**

export declare const FIRST_INPUT_DELAY_COUNTER_NAME = "_fid";
export declare const LARGEST_CONTENTFUL_PAINT_METRIC_NAME = "_lcp";
export declare const LARGEST_CONTENTFUL_PAINT_ATTRIBUTE_NAME = "lcp_element";
export declare const INTERACTION_TO_NEXT_PAINT_METRIC_NAME = "_inp";
export declare const INTERACTION_TO_NEXT_PAINT_ATTRIBUTE_NAME = "inp_interactionTarget";
export declare const CUMULATIVE_LAYOUT_SHIFT_METRIC_NAME = "_cls";
export declare const CUMULATIVE_LAYOUT_SHIFT_ATTRIBUTE_NAME = "cls_largestShiftTarget";
export declare const CONFIG_LOCAL_STORAGE_KEY = "@firebase/performance/config";

@@ -31,0 +37,0 @@ export declare const CONFIG_EXPIRY_LOCAL_STORAGE_KEY = "@firebase/performance/configexpire";

@@ -19,2 +19,3 @@ /**

import { PerformanceController } from '../controllers/perf';
import { CoreVitalMetric, WebVitalMetrics } from './web_vitals';
export declare class Trace implements PerformanceTrace {

@@ -118,4 +119,5 @@ readonly performanceController: PerformanceController;

*/
static createOobTrace(performanceController: PerformanceController, navigationTimings: PerformanceNavigationTiming[], paintTimings: PerformanceEntry[], firstInputDelay?: number): void;
static createOobTrace(performanceController: PerformanceController, navigationTimings: PerformanceNavigationTiming[], paintTimings: PerformanceEntry[], webVitalMetrics: WebVitalMetrics, firstInputDelay?: number): void;
static addWebVitalMetric(trace: Trace, metricKey: string, attributeKey: string, metric?: CoreVitalMetric): void;
static createUserTimingTrace(performanceController: PerformanceController, measureName: string): void;
}

@@ -17,2 +17,3 @@ /**

*/
import { CLSMetricWithAttribution, INPMetricWithAttribution, LCPMetricWithAttribution } from 'web-vitals/attribution';
declare global {

@@ -38,2 +39,5 @@ interface Window {

readonly onFirstInputDelay?: (fn: (fid: number) => void) => void;
readonly onLCP: (fn: (metric: LCPMetricWithAttribution) => void) => void;
readonly onINP: (fn: (metric: INPMetricWithAttribution) => void) => void;
readonly onCLS: (fn: (metric: CLSMetricWithAttribution) => void) => void;
readonly localStorage?: Storage;

@@ -40,0 +44,0 @@ readonly document: Document;

@@ -19,1 +19,6 @@ /**

export declare function setupOobResources(performanceController: PerformanceController): void;
/**
* This service will only export the page load trace once. This function allows
* resetting it for unit tests
*/
export declare function resetForUnitTests(): void;

@@ -20,2 +20,3 @@ /**

export declare function logTrace(trace: Trace): void;
export declare function flushLogs(): void;
export declare function logNetworkRequest(networkRequest: NetworkRequest): void;

@@ -24,1 +24,6 @@ /**

export declare function transportHandler(serializer: (...args: any[]) => string): (...args: unknown[]) => void;
/**
* Force flush the queued events. Useful at page unload time to ensure all
* events are uploaded.
*/
export declare function flushQueuedEvents(): void;
{
"name": "@firebase/performance",
"version": "0.6.12-canary.3c1559b7e",
"version": "0.6.12-canary.59ae45e48",
"description": "Firebase performance for web",

@@ -38,16 +38,17 @@ "author": "Firebase <firebase-support@google.com> (https://firebase.google.com/)",

"peerDependencies": {
"@firebase/app": "0.10.18-canary.3c1559b7e"
"@firebase/app": "0.10.18-canary.59ae45e48"
},
"dependencies": {
"@firebase/logger": "0.4.4-canary.3c1559b7e",
"@firebase/installations": "0.6.12-canary.3c1559b7e",
"@firebase/util": "1.10.3-canary.3c1559b7e",
"@firebase/component": "0.6.12-canary.3c1559b7e",
"tslib": "^2.1.0"
"@firebase/logger": "0.4.4-canary.59ae45e48",
"@firebase/installations": "0.6.12-canary.59ae45e48",
"@firebase/util": "1.10.3-canary.59ae45e48",
"@firebase/component": "0.6.12-canary.59ae45e48",
"tslib": "^2.1.0",
"web-vitals": "^4.2.4"
},
"license": "Apache-2.0",
"devDependencies": {
"@firebase/app": "0.10.18-canary.3c1559b7e",
"@firebase/app": "0.10.18-canary.59ae45e48",
"rollup": "2.79.1",
"@rollup/plugin-json": "4.1.0",
"@rollup/plugin-json": "6.1.0",
"rollup-plugin-typescript2": "0.31.2",

@@ -54,0 +55,0 @@ "typescript": "5.5.4"

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc