mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Dashboards: Monitor dashboard loading performance (#99629)
* WIP benchmark dashboard rendering * Script * Benchmark with variable and a panel * Add one more benchmark * Explicitely enable profiling * Playwright tests * update scenes * Report measurement to faro when config set * Let user enable metrics reporting in UI * Fix logging * Change how performance metrics is enabled per dashboard, now in config file only * add benchmark run option * Fix benchmark runs * fix description for performance config * remove console.log * update codeowners * add back crashDetection init that was lost in merge * fix yarn.lock * restore custom.ini * fix import * Make sure we have the echoSrv * fix config type * Try to limit changes to e2e runs * remove benchmark * Fix lint issue * fix codeowners --------- Co-authored-by: Dominik Prokop <dominik.prokop@grafana.com> Co-authored-by: Sergej-Vlasov <sergej.s.vlasov@gmail.com>
This commit is contained in:
@@ -2,6 +2,7 @@ import { isEqual } from 'lodash';
|
||||
|
||||
import { locationUtil, UrlQueryMap } from '@grafana/data';
|
||||
import { config, getBackendSrv, isFetchError, locationService } from '@grafana/runtime';
|
||||
import { sceneGraph } from '@grafana/scenes';
|
||||
import { DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
import { StateManagerBase } from 'app/core/services/StateManagerBase';
|
||||
import { getMessageFromError, getMessageIdFromError, getStatusFromError } from 'app/core/utils/errors';
|
||||
@@ -135,7 +136,10 @@ abstract class DashboardScenePageStateManagerBase<T>
|
||||
|
||||
this.setState({ dashboard: dashboard, isLoading: false, options });
|
||||
const measure = stopMeasure(LOAD_SCENE_MEASUREMENT);
|
||||
const queryController = sceneGraph.getQueryController(dashboard);
|
||||
|
||||
trackDashboardSceneLoaded(dashboard, measure?.duration);
|
||||
queryController?.startProfile(dashboard);
|
||||
|
||||
if (options.route !== DashboardRoutes.New) {
|
||||
emitDashboardViewEvent({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { uniqueId } from 'lodash';
|
||||
|
||||
import { DataFrameDTO, DataFrameJSON } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { config, logMeasurement, reportInteraction } from '@grafana/runtime';
|
||||
import {
|
||||
VizPanel,
|
||||
SceneTimePicker,
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
SceneDataLayerProvider,
|
||||
SceneDataLayerControls,
|
||||
UserActionEvent,
|
||||
SceneInteractionProfileEvent,
|
||||
SceneObjectState,
|
||||
} from '@grafana/scenes';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
@@ -229,7 +230,11 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel,
|
||||
new behaviors.CursorSync({
|
||||
sync: oldModel.graphTooltip,
|
||||
}),
|
||||
new behaviors.SceneQueryController(),
|
||||
new behaviors.SceneQueryController({
|
||||
enableProfiling:
|
||||
config.dashboardPerformanceMetrics.findIndex((uid) => uid === '*' || uid === oldModel.uid) !== -1,
|
||||
onProfileComplete: getDashboardInteractionCallback(oldModel.uid, oldModel.title),
|
||||
}),
|
||||
registerDashboardMacro,
|
||||
registerPanelInteractionsReporter,
|
||||
new behaviors.LiveNowTimer({ enabled: oldModel.liveNow }),
|
||||
@@ -434,3 +439,40 @@ function trackIfEmpty(grid: SceneGridLayout) {
|
||||
sub.unsubscribe();
|
||||
};
|
||||
}
|
||||
|
||||
function getDashboardInteractionCallback(uid: string, title: string) {
|
||||
return (e: SceneInteractionProfileEvent) => {
|
||||
let interactionType = '';
|
||||
|
||||
if (e.origin === 'SceneTimeRange') {
|
||||
interactionType = 'time-range-change';
|
||||
} else if (e.origin === 'SceneRefreshPicker') {
|
||||
interactionType = 'refresh';
|
||||
} else if (e.origin === 'DashboardScene') {
|
||||
interactionType = 'view';
|
||||
} else if (e.origin.indexOf('Variable') > -1) {
|
||||
interactionType = 'variable-change';
|
||||
}
|
||||
reportInteraction('dashboard-render', {
|
||||
interactionType,
|
||||
duration: e.duration,
|
||||
networkDuration: e.networkDuration,
|
||||
totalJSHeapSize: e.totalJSHeapSize,
|
||||
usedJSHeapSize: e.usedJSHeapSize,
|
||||
jsHeapSizeLimit: e.jsHeapSizeLimit,
|
||||
});
|
||||
|
||||
logMeasurement(
|
||||
`dashboard.${interactionType}`,
|
||||
{
|
||||
duration: e.duration,
|
||||
networkDuration: e.networkDuration,
|
||||
totalJSHeapSize: e.totalJSHeapSize,
|
||||
usedJSHeapSize: e.usedJSHeapSize,
|
||||
jsHeapSizeLimit: e.jsHeapSizeLimit,
|
||||
timeSinceBoot: performance.measure('time_since_boot', 'frontend_boot_js_done_time_seconds').duration,
|
||||
},
|
||||
{ dashboard: uid, title: title }
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user