blob: 4f25ba3a33281c6a505e315035aee311ae0f94c9 [file]
/**
* 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.
*/
import { Interaction, EntryPreProcessingHook, PerformanceEventTiming } from "./types";
export const DEFAULT_DURATION_THRESHOLD = 40;
// Longest interactions list
export const interactionList: Interaction[] = [];
export const interactionsMap: Map<number, Interaction> = new Map();
export const entryPreProcessingCallbacks: EntryPreProcessingHook[] = [];
const MAX_INTERACTIONS_TO_CONSIDER = 10;
let prevInteractionCount = 0;
export function handleInteractionEntry (entry: PerformanceEventTiming) {
entryPreProcessingCallbacks.forEach((cb) => cb(entry));
if (!(entry.interactionId || entry.entryType === 'first-input')) return;
const minLongestInteraction = interactionList[interactionList.length - 1];
const existingInteraction = interactionsMap.get(entry.interactionId!);
if (
existingInteraction || interactionList.length < MAX_INTERACTIONS_TO_CONSIDER ||
entry.duration > minLongestInteraction.latency
) {
if (existingInteraction) {
if (entry.duration > existingInteraction.latency) {
existingInteraction.entries = [entry];
existingInteraction.latency = entry.duration;
} else if (
entry.duration === existingInteraction.latency &&
entry.startTime === existingInteraction.entries[0].startTime
) {
existingInteraction.entries.push(entry);
}
} else {
const interaction = {
id: entry.interactionId!,
latency: entry.duration,
entries: [entry],
};
interactionsMap.set(interaction.id, interaction);
interactionList.push(interaction);
}
// Sort the entries by latency
interactionList.sort((a, b) => b.latency - a.latency);
if (interactionList.length > MAX_INTERACTIONS_TO_CONSIDER) {
interactionList
.splice(MAX_INTERACTIONS_TO_CONSIDER)
.forEach((i) => interactionsMap.delete(i.id));
}
}
};
function getInteractionCountForNavigation() {
return getInteractionCount() - prevInteractionCount;
};
export function getLongestInteraction() {
const index = Math.min(interactionList.length - 1, Math.floor(getInteractionCountForNavigation() / 50));
return interactionList[index];
};
export function clearInteractions() {
prevInteractionCount = getInteractionCount();
interactionList.length = 0;
interactionsMap.clear();
};
export function getInteractionCount() {
return (performance.eventCounts as any).size || 0;
};