Skip to content

Commit

Permalink
[8.x] [Perfomance] Track time range picker with onPageReady function (
Browse files Browse the repository at this point in the history
#202889) (#204564)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Perfomance] Track time range picker with `onPageReady` function
(#202889)](#202889)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT
[{"author":{"name":"Katerina","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-12-13T13:11:44Z","message":"[Perfomance]
Track time range picker with `onPageReady` function (#202889)\n\n##
Summary\r\n\r\ncloses
https://github.com/elastic/observability-dev/issues/3377\r\n## Metrics
\r\n#### `meta.query_range_secs` - The duration of the selected time
range\r\nin seconds.\r\n#### `meta.query_offset_secs` - The offset from
\"now\" to the\r\n'rangeTo'/end' time picker value in
seconds.\r\n\r\n____\r\n\r\nExtend the `onPageReady` function to support
date ranges in the meta\r\nfield. The function should compute the query
range in seconds based on\r\nthe provided time range and report it to
telemetry as\r\nmeta.query_range_secs.\r\n\r\n\r\n\r\n\r\nIf the
`rangeTo` is different from 'now', calculate the offset. \r\n- A
negative offset indicates that the rangeTo is in the past, \r\n- a
positive offset means it is in the future, \r\n- and zero indicates that
the rangeTo is exactly 'now'.\" \r\n\r\n\r\n\r\n### How to
instrument\r\nTo report the selected time range, pass the `rangeFrom`
and `rangeTo` . \r\n> Failing to pass the correct type will result in TS
error.\r\n\r\n\r\nThen, use this data when invoking
onPageReady:\r\n```\r\n onPageReady({\r\n meta: { rangeFrom, rangeTo
},\r\n });\r\n```\r\n\r\n### Analysis \r\n\r\nMeta is flatten field. In
order to aggregate the data it's necessary to\r\ncreate a run time
field. You can add a field in the\r\n\r\n1. select data view
(`ebt-kibana-*-performance-metrics`) \r\n2. Add a new field\r\n3. Type
double\r\n4. Set value \r\n\r\n`query_range_secs`\r\n```\r\ndef meta =
doc[“meta”].size();\r\nif (meta > 0) {\r\n def range =
doc[“meta.query_range_secs”].size();\r\n if (range > 0) {\r\n // Emit
the value of ‘meta.target’\r\n
emit(Double.parseDouble(doc[“meta.query_range_secs”].value));\r\n
}\r\n}\r\n\r\n```\r\n\r\n`query_offset_secs` \r\n```\r\n\r\ndef meta =
doc[“meta”].size();\r\nif (meta > 0) {\r\n def offset =
doc[“meta.query_offset_secs”].size();\r\n if (offset > 0) {\r\n \r\n
emit(Double.parseDouble(doc[“meta.query_offset_secs”].value));\r\n
}\r\n}\r\n\r\n```\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n###
Examples\r\n\r\n\r\n<img width=\"1478\" alt=\"Screenshot 2024-12-09 at
19 51
32\"\r\nsrc=\"https://github.com/user-attachments/assets/72f796e1-4f20-487f-b62a-b6a4aead9a4a\">\r\n\r\n<img
width=\"1478\" alt=\"Screenshot 2024-12-09 at 19 56
08\"\r\nsrc=\"https://github.com/user-attachments/assets/c278dc3b-e6f3-47ed-9c90-954d71b59161\">\r\n\r\n<img
width=\"1478\" alt=\"Screenshot 2024-12-09 at 19 53 45
1\"\r\nsrc=\"https://github.com/user-attachments/assets/ef42ecef-48cd-4396-9f5d-c971098d5219\">\r\n\r\n\r\n\r\n\r\n\r\n###
Notes\r\n- Instrumented only 2 solutions as an example (dataset and apm
services)\r\n\r\n### TODO\r\n- [x] Update documentation
-\r\nhttps://github.com//pull/204179\r\n- [ ] Update
dashboards (create a runtime field) \r\n- [x] Track offset ( we need to
know if the user selected now or
now)\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>","sha":"bd1c00fd65848ff27a1bace14363c5ab326c491d","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport
missing","v9.0.0","backport:prev-minor","ci:project-deploy-observability","Team:obs-ux-infra_services"],"number":202889,"url":"https://github.com/elastic/kibana/pull/202889","mergeCommit":{"message":"[Perfomance]
Track time range picker with `onPageReady` function (#202889)\n\n##
Summary\r\n\r\ncloses
https://github.com/elastic/observability-dev/issues/3377\r\n## Metrics
\r\n#### `meta.query_range_secs` - The duration of the selected time
range\r\nin seconds.\r\n#### `meta.query_offset_secs` - The offset from
\"now\" to the\r\n'rangeTo'/end' time picker value in
seconds.\r\n\r\n____\r\n\r\nExtend the `onPageReady` function to support
date ranges in the meta\r\nfield. The function should compute the query
range in seconds based on\r\nthe provided time range and report it to
telemetry as\r\nmeta.query_range_secs.\r\n\r\n\r\n\r\n\r\nIf the
`rangeTo` is different from 'now', calculate the offset. \r\n- A
negative offset indicates that the rangeTo is in the past, \r\n- a
positive offset means it is in the future, \r\n- and zero indicates that
the rangeTo is exactly 'now'.\" \r\n\r\n\r\n\r\n### How to
instrument\r\nTo report the selected time range, pass the `rangeFrom`
and `rangeTo` . \r\n> Failing to pass the correct type will result in TS
error.\r\n\r\n\r\nThen, use this data when invoking
onPageReady:\r\n```\r\n onPageReady({\r\n meta: { rangeFrom, rangeTo
},\r\n });\r\n```\r\n\r\n### Analysis \r\n\r\nMeta is flatten field. In
order to aggregate the data it's necessary to\r\ncreate a run time
field. You can add a field in the\r\n\r\n1. select data view
(`ebt-kibana-*-performance-metrics`) \r\n2. Add a new field\r\n3. Type
double\r\n4. Set value \r\n\r\n`query_range_secs`\r\n```\r\ndef meta =
doc[“meta”].size();\r\nif (meta > 0) {\r\n def range =
doc[“meta.query_range_secs”].size();\r\n if (range > 0) {\r\n // Emit
the value of ‘meta.target’\r\n
emit(Double.parseDouble(doc[“meta.query_range_secs”].value));\r\n
}\r\n}\r\n\r\n```\r\n\r\n`query_offset_secs` \r\n```\r\n\r\ndef meta =
doc[“meta”].size();\r\nif (meta > 0) {\r\n def offset =
doc[“meta.query_offset_secs”].size();\r\n if (offset > 0) {\r\n \r\n
emit(Double.parseDouble(doc[“meta.query_offset_secs”].value));\r\n
}\r\n}\r\n\r\n```\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n###
Examples\r\n\r\n\r\n<img width=\"1478\" alt=\"Screenshot 2024-12-09 at
19 51
32\"\r\nsrc=\"https://github.com/user-attachments/assets/72f796e1-4f20-487f-b62a-b6a4aead9a4a\">\r\n\r\n<img
width=\"1478\" alt=\"Screenshot 2024-12-09 at 19 56
08\"\r\nsrc=\"https://github.com/user-attachments/assets/c278dc3b-e6f3-47ed-9c90-954d71b59161\">\r\n\r\n<img
width=\"1478\" alt=\"Screenshot 2024-12-09 at 19 53 45
1\"\r\nsrc=\"https://github.com/user-attachments/assets/ef42ecef-48cd-4396-9f5d-c971098d5219\">\r\n\r\n\r\n\r\n\r\n\r\n###
Notes\r\n- Instrumented only 2 solutions as an example (dataset and apm
services)\r\n\r\n### TODO\r\n- [x] Update documentation
-\r\nhttps://github.com//pull/204179\r\n- [ ] Update
dashboards (create a runtime field) \r\n- [x] Track offset ( we need to
know if the user selected now or
now)\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>","sha":"bd1c00fd65848ff27a1bace14363c5ab326c491d"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/202889","number":202889,"mergeCommit":{"message":"[Perfomance]
Track time range picker with `onPageReady` function (#202889)\n\n##
Summary\r\n\r\ncloses
https://github.com/elastic/observability-dev/issues/3377\r\n## Metrics
\r\n#### `meta.query_range_secs` - The duration of the selected time
range\r\nin seconds.\r\n#### `meta.query_offset_secs` - The offset from
\"now\" to the\r\n'rangeTo'/end' time picker value in
seconds.\r\n\r\n____\r\n\r\nExtend the `onPageReady` function to support
date ranges in the meta\r\nfield. The function should compute the query
range in seconds based on\r\nthe provided time range and report it to
telemetry as\r\nmeta.query_range_secs.\r\n\r\n\r\n\r\n\r\nIf the
`rangeTo` is different from 'now', calculate the offset. \r\n- A
negative offset indicates that the rangeTo is in the past, \r\n- a
positive offset means it is in the future, \r\n- and zero indicates that
the rangeTo is exactly 'now'.\" \r\n\r\n\r\n\r\n### How to
instrument\r\nTo report the selected time range, pass the `rangeFrom`
and `rangeTo` . \r\n> Failing to pass the correct type will result in TS
error.\r\n\r\n\r\nThen, use this data when invoking
onPageReady:\r\n```\r\n onPageReady({\r\n meta: { rangeFrom, rangeTo
},\r\n });\r\n```\r\n\r\n### Analysis \r\n\r\nMeta is flatten field. In
order to aggregate the data it's necessary to\r\ncreate a run time
field. You can add a field in the\r\n\r\n1. select data view
(`ebt-kibana-*-performance-metrics`) \r\n2. Add a new field\r\n3. Type
double\r\n4. Set value \r\n\r\n`query_range_secs`\r\n```\r\ndef meta =
doc[“meta”].size();\r\nif (meta > 0) {\r\n def range =
doc[“meta.query_range_secs”].size();\r\n if (range > 0) {\r\n // Emit
the value of ‘meta.target’\r\n
emit(Double.parseDouble(doc[“meta.query_range_secs”].value));\r\n
}\r\n}\r\n\r\n```\r\n\r\n`query_offset_secs` \r\n```\r\n\r\ndef meta =
doc[“meta”].size();\r\nif (meta > 0) {\r\n def offset =
doc[“meta.query_offset_secs”].size();\r\n if (offset > 0) {\r\n \r\n
emit(Double.parseDouble(doc[“meta.query_offset_secs”].value));\r\n
}\r\n}\r\n\r\n```\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n###
Examples\r\n\r\n\r\n<img width=\"1478\" alt=\"Screenshot 2024-12-09 at
19 51
32\"\r\nsrc=\"https://github.com/user-attachments/assets/72f796e1-4f20-487f-b62a-b6a4aead9a4a\">\r\n\r\n<img
width=\"1478\" alt=\"Screenshot 2024-12-09 at 19 56
08\"\r\nsrc=\"https://github.com/user-attachments/assets/c278dc3b-e6f3-47ed-9c90-954d71b59161\">\r\n\r\n<img
width=\"1478\" alt=\"Screenshot 2024-12-09 at 19 53 45
1\"\r\nsrc=\"https://github.com/user-attachments/assets/ef42ecef-48cd-4396-9f5d-c971098d5219\">\r\n\r\n\r\n\r\n\r\n\r\n###
Notes\r\n- Instrumented only 2 solutions as an example (dataset and apm
services)\r\n\r\n### TODO\r\n- [x] Update documentation
-\r\nhttps://github.com//pull/204179\r\n- [ ] Update
dashboards (create a runtime field) \r\n- [x] Track offset ( we need to
know if the user selected now or
now)\r\n\r\n---------\r\n\r\nCo-authored-by: kibanamachine
<[email protected]>","sha":"bd1c00fd65848ff27a1bace14363c5ab326c491d"}}]}]
BACKPORT-->
  • Loading branch information
kpatticha authored Dec 17, 2024
1 parent 16f4187 commit 64de070
Show file tree
Hide file tree
Showing 18 changed files with 398 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,31 @@ describe('trackPerformanceMeasureEntries', () => {
value1: 'value1',
});
});

test('reports an analytics event with query metadata', () => {
setupMockPerformanceObserver([
{
name: '/',
entryType: 'measure',
startTime: 100,
duration: 1000,
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
meta: {
queryRangeSecs: 86400,
queryOffsetSecs: 0,
},
},
},
]);
trackPerformanceMeasureEntries(analyticsClientMock, true);

expect(analyticsClientMock.reportEvent).toHaveBeenCalledTimes(1);
expect(analyticsClientMock.reportEvent).toHaveBeenCalledWith('performance_metric', {
duration: 1000,
eventName: 'kibana:plugin_render_time',
meta: { target: '/', query_range_secs: 86400, query_offset_secs: 0 },
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export function trackPerformanceMeasureEntries(analytics: AnalyticsClient, isDev
if (entry.entryType === 'measure' && entry.detail?.type === 'kibana:performance') {
const target = entry?.name;
const duration = entry.duration;
const meta = entry.detail?.meta;
const customMetrics = Object.keys(entry.detail?.customMetrics ?? {}).reduce(
(acc, metric) => {
if (ALLOWED_CUSTOM_METRICS_KEYS_VALUES.includes(metric)) {
Expand Down Expand Up @@ -72,6 +73,8 @@ export function trackPerformanceMeasureEntries(analytics: AnalyticsClient, isDev
...customMetrics,
meta: {
target,
query_range_secs: meta?.queryRangeSecs,
query_offset_secs: meta?.queryOffsetSecs,
},
});
} catch (error) {
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-ebt-tools/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ SHARED_DEPS = [
"@npm//@elastic/apm-rum-core",
"@npm//react",
"@npm//react-router-dom",
"//packages/kbn-timerange"
]

js_library(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import {
getDateRange,
getOffsetFromNowInSeconds,
getTimeDifferenceInSeconds,
} from '@kbn/timerange';
import { perfomanceMarkers } from '../../performance_markers';
import { EventData } from '../performance_context';

interface PerformanceMeta {
queryRangeSecs: number;
queryOffsetSecs: number;
}

export function measureInteraction() {
performance.mark(perfomanceMarkers.startPageChange);
const trackedRoutes: string[] = [];
return {
/**
* Marks the end of the page ready state and measures the performance between the start of the page change and the end of the page ready state.
* @param pathname - The pathname of the page.
* @param customMetrics - Custom metrics to be included in the performance measure.
*/
pageReady(pathname: string, eventData?: EventData) {
let performanceMeta: PerformanceMeta | undefined;
performance.mark(perfomanceMarkers.endPageReady);

if (eventData?.meta) {
const { rangeFrom, rangeTo } = eventData.meta;

// Convert the date range to epoch timestamps (in milliseconds)
const dateRangesInEpoch = getDateRange({
from: rangeFrom,
to: rangeTo,
});

performanceMeta = {
queryRangeSecs: getTimeDifferenceInSeconds(dateRangesInEpoch),
queryOffsetSecs:
rangeTo === 'now' ? 0 : getOffsetFromNowInSeconds(dateRangesInEpoch.endDate),
};
}

if (!trackedRoutes.includes(pathname)) {
performance.measure(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
customMetrics: eventData?.customMetrics,
meta: performanceMeta,
},
start: perfomanceMarkers.startPageChange,
end: perfomanceMarkers.endPageReady,
});
trackedRoutes.push(pathname);
}
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { measureInteraction } from '.';
import { perfomanceMarkers } from '../../performance_markers';

describe('measureInteraction', () => {
afterAll(() => {
jest.restoreAllMocks();
});

beforeEach(() => {
jest.clearAllMocks();
performance.mark = jest.fn();
performance.measure = jest.fn();
});

it('should mark the start of the page change', () => {
measureInteraction();
expect(performance.mark).toHaveBeenCalledWith(perfomanceMarkers.startPageChange);
});

it('should mark the end of the page ready state and measure performance', () => {
const interaction = measureInteraction();
const pathname = '/test-path';
interaction.pageReady(pathname);

expect(performance.mark).toHaveBeenCalledWith(perfomanceMarkers.endPageReady);
expect(performance.measure).toHaveBeenCalledWith(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
},
start: perfomanceMarkers.startPageChange,
end: perfomanceMarkers.endPageReady,
});
});

it('should include custom metrics and meta in the performance measure', () => {
const interaction = measureInteraction();
const pathname = '/test-path';
const eventData = {
customMetrics: { key1: 'foo-metric', value1: 100 },
meta: { rangeFrom: 'now-15m', rangeTo: 'now' },
};

interaction.pageReady(pathname, eventData);

expect(performance.mark).toHaveBeenCalledWith(perfomanceMarkers.endPageReady);
expect(performance.measure).toHaveBeenCalledWith(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
customMetrics: eventData.customMetrics,
meta: {
queryRangeSecs: 900,
queryOffsetSecs: 0,
},
},
end: 'end::pageReady',
start: 'start::pageChange',
});
});

it('should handle absolute date format correctly', () => {
const interaction = measureInteraction();
const pathname = '/test-path';
jest.spyOn(global.Date, 'now').mockReturnValue(1733704200000); // 2024-12-09T00:30:00Z

const eventData = {
meta: { rangeFrom: '2024-12-09T00:00:00Z', rangeTo: '2024-12-09T00:30:00Z' },
};

interaction.pageReady(pathname, eventData);

expect(performance.mark).toHaveBeenCalledWith(perfomanceMarkers.endPageReady);
expect(performance.measure).toHaveBeenCalledWith(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
customMetrics: undefined,
meta: {
queryRangeSecs: 1800,
queryOffsetSecs: 0,
},
},
end: 'end::pageReady',
start: 'start::pageChange',
});
});

it('should handle negative offset when rangeTo is in the past', () => {
const interaction = measureInteraction();
const pathname = '/test-path';
jest.spyOn(global.Date, 'now').mockReturnValue(1733704200000); // 2024-12-09T00:30:00Z

const eventData = {
meta: { rangeFrom: '2024-12-08T00:00:00Z', rangeTo: '2024-12-09T00:00:00Z' },
};

interaction.pageReady(pathname, eventData);

expect(performance.mark).toHaveBeenCalledWith(perfomanceMarkers.endPageReady);
expect(performance.measure).toHaveBeenCalledWith(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
customMetrics: undefined,
meta: {
queryRangeSecs: 86400,
queryOffsetSecs: -1800,
},
},
end: 'end::pageReady',
start: 'start::pageChange',
});
});

it('should handle positive offset when rangeTo is in the future', () => {
const interaction = measureInteraction();
const pathname = '/test-path';
jest.spyOn(global.Date, 'now').mockReturnValue(1733704200000); // 2024-12-09T00:30:00Z

const eventData = {
meta: { rangeFrom: '2024-12-08T01:00:00Z', rangeTo: '2024-12-09T01:00:00Z' },
};

interaction.pageReady(pathname, eventData);

expect(performance.mark).toHaveBeenCalledWith(perfomanceMarkers.endPageReady);
expect(performance.measure).toHaveBeenCalledWith(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
customMetrics: undefined,
meta: {
queryRangeSecs: 86400,
queryOffsetSecs: 1800,
},
},
end: 'end::pageReady',
start: 'start::pageChange',
});
});

it('should not measure the same route twice', () => {
const interaction = measureInteraction();
const pathname = '/test-path';

interaction.pageReady(pathname);
interaction.pageReady(pathname);

expect(performance.measure).toHaveBeenCalledTimes(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,38 +10,19 @@
import React, { useMemo, useState } from 'react';
import { afterFrame } from '@elastic/apm-rum-core';
import { useLocation } from 'react-router-dom';
import { perfomanceMarkers } from '../performance_markers';
import { PerformanceApi, PerformanceContext } from './use_performance_context';
import { PerformanceMetricEvent } from '../../performance_metric_events';
import { measureInteraction } from './measure_interaction';

export type CustomMetrics = Omit<PerformanceMetricEvent, 'eventName' | 'meta' | 'duration'>;

function measureInteraction() {
performance.mark(perfomanceMarkers.startPageChange);
const trackedRoutes: string[] = [];
return {
/**
* Marks the end of the page ready state and measures the performance between the start of the page change and the end of the page ready state.
* @param pathname - The pathname of the page.
* @param customMetrics - Custom metrics to be included in the performance measure.
*/
pageReady(pathname: string, customMetrics?: CustomMetrics) {
performance.mark(perfomanceMarkers.endPageReady);

if (!trackedRoutes.includes(pathname)) {
performance.measure(pathname, {
detail: {
eventName: 'kibana:plugin_render_time',
type: 'kibana:performance',
customMetrics,
},
start: perfomanceMarkers.startPageChange,
end: perfomanceMarkers.endPageReady,
});
trackedRoutes.push(pathname);
}
},
};
export interface Meta {
rangeFrom: string;
rangeTo: string;
}
export interface EventData {
customMetrics?: CustomMetrics;
meta?: Meta;
}

export function PerformanceContextProvider({ children }: { children: React.ReactElement }) {
Expand All @@ -61,9 +42,9 @@ export function PerformanceContextProvider({ children }: { children: React.React

const api = useMemo<PerformanceApi>(
() => ({
onPageReady(customMetrics) {
onPageReady(eventData) {
if (isRendered) {
interaction.pageReady(location.pathname, customMetrics);
interaction.pageReady(location.pathname, eventData);
}
},
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,22 @@
*/

import { useEffect, useState } from 'react';
import { CustomMetrics } from './performance_context';
import type { CustomMetrics, Meta } from './performance_context';
import { usePerformanceContext } from '../../..';

export const usePageReady = (state: { customMetrics?: CustomMetrics; isReady: boolean }) => {
export const usePageReady = (state: {
customMetrics?: CustomMetrics;
isReady: boolean;
meta?: Meta;
}) => {
const { onPageReady } = usePerformanceContext();

const [isReported, setIsReported] = useState(false);

useEffect(() => {
if (state.isReady && !isReported) {
onPageReady(state.customMetrics);
onPageReady({ customMetrics: state.customMetrics, meta: state.meta });
setIsReported(true);
}
}, [isReported, onPageReady, state.customMetrics, state.isReady]);
}, [isReported, onPageReady, state.customMetrics, state.isReady, state.meta]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,13 @@
*/

import { createContext, useContext } from 'react';
import { CustomMetrics } from './performance_context';

import type { EventData } from './performance_context';
export interface PerformanceApi {
/**
* Marks the end of the page ready state and measures the performance between the start of the page change and the end of the page ready state.
* @param customMetrics - Custom metrics to be included in the performance measure.
* @param eventData - Data to send with the performance measure, conforming the structure of a {@link EventData}.
*/
onPageReady(customMetrics?: CustomMetrics): void;
onPageReady(eventData?: EventData): void;
}

export const PerformanceContext = createContext<PerformanceApi | undefined>(undefined);
Expand Down
Loading

0 comments on commit 64de070

Please sign in to comment.