Instrumentation: Measure app init load times (#67900)

* adding load time metrics for app init.

* chore: add the `metrics.ts` to the CODEOWNERS

* moved file according to PR feedback.

---------

Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
This commit is contained in:
Marcus Andersson
2023-05-10 11:03:15 +02:00
committed by GitHub
parent e1ff434917
commit 047763978d
4 changed files with 49 additions and 1 deletions

1
.github/CODEOWNERS vendored
View File

@ -453,6 +453,7 @@ lerna.json @grafana/frontend-ops
/public/app/angular/ @torkelo
/public/app/app.ts @grafana/frontend-ops
/public/app/dev.ts @grafana/frontend-ops
/public/app/core/utils/metrics.ts @grafana/plugins-platform-frontend
/public/app/index.ts @grafana/frontend-ops
/public/app/AppWrapper.tsx @grafana/frontend-ops
/public/app/partials/ @grafana/grafana-frontend-platform

View File

@ -67,6 +67,7 @@ import { GAEchoBackend } from './core/services/echo/backends/analytics/GABackend
import { RudderstackBackend } from './core/services/echo/backends/analytics/RudderstackBackend';
import { GrafanaJavascriptAgentBackend } from './core/services/echo/backends/grafana-javascript-agent/GrafanaJavascriptAgentBackend';
import { KeybindingSrv } from './core/services/keybindingSrv';
import { startMeasure, stopMeasure } from './core/utils/metrics';
import { initDevFeatures } from './dev';
import { getTimeSrv } from './features/dashboard/services/TimeSrv';
import { initGrafanaLive } from './features/live';
@ -119,6 +120,8 @@ export class GrafanaApp {
setBackendSrv(backendSrv);
initEchoSrv();
// This needs to be done after the `initEchoSrv` since it is being used under the hood.
startMeasure('frontend_app_init');
addClassIfNoOverlayScrollbar();
setLocale(config.bootData.user.locale);
setWeekStart(config.bootData.user.weekStart);
@ -219,6 +222,8 @@ export class GrafanaApp {
} catch (error) {
console.error('Failed to start Grafana', error);
window.__grafana_load_failed();
} finally {
stopMeasure('frontend_app_init');
}
}
}

View File

@ -0,0 +1,35 @@
import { reportPerformance } from '../services/echo/EchoSrv';
export function startMeasure(eventName: string) {
if (!performance) {
return;
}
try {
performance.mark(`${eventName}_started`);
} catch (error) {
console.error(`[Metrics] Failed to startMeasure ${eventName}`, error);
}
}
export function stopMeasure(eventName: string) {
if (!performance) {
return;
}
try {
const started = `${eventName}_started`;
const completed = `${eventName}_completed`;
const measured = `${eventName}_measured`;
performance.mark(completed);
const measure = performance.measure(measured, started, completed);
reportPerformance(`${eventName}_ms`, measure.duration);
performance.clearMarks(started);
performance.clearMarks(completed);
performance.clearMeasures(measured);
} catch (error) {
console.error(`[Metrics] Failed to stopMeasure ${eventName}`, error);
}
}

View File

@ -1,5 +1,6 @@
import type { PluginExtensionLinkConfig } from '@grafana/data';
import type { AppPluginConfig } from '@grafana/runtime';
import { startMeasure, stopMeasure } from 'app/core/utils/metrics';
import * as pluginLoader from './plugin_loader';
@ -10,18 +11,24 @@ export type PluginPreloadResult = {
};
export async function preloadPlugins(apps: Record<string, AppPluginConfig> = {}): Promise<PluginPreloadResult[]> {
startMeasure('frontend_plugins_preload');
const pluginsToPreload = Object.values(apps).filter((app) => app.preload);
return Promise.all(pluginsToPreload.map(preload));
const result = await Promise.all(pluginsToPreload.map(preload));
stopMeasure('frontend_plugins_preload');
return result;
}
async function preload(config: AppPluginConfig): Promise<PluginPreloadResult> {
const { path, version, id: pluginId } = config;
try {
startMeasure(`frontend_plugin_preload_${pluginId}`);
const { plugin } = await pluginLoader.importPluginModule(path, version);
const { extensionConfigs = [] } = plugin;
return { pluginId, extensionConfigs };
} catch (error) {
console.error(`[Plugins] Failed to preload plugin: ${path} (version: ${version})`, error);
return { pluginId, extensionConfigs: [], error };
} finally {
stopMeasure(`frontend_plugin_preload_${pluginId}`);
}
}