mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[EBT] Enrich kibana loaded with timings (#134770)
* Add timings to kibana loaded event * jest * PR failures * code review * docs * add first_app_nav and first_app * tests * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * Update src/core/public/core_system.ts Co-authored-by: Alejandro Fernández Haro <afharo@gmail.com> * Update src/core/public/core_system.ts Co-authored-by: Alejandro Fernández Haro <afharo@gmail.com> * review @afjaro * typo * KBN_LOAD_MARKS Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Alejandro Fernández Haro <afharo@gmail.com>
This commit is contained in:
parent
ca532310f2
commit
8133605b89
10 changed files with 136 additions and 7 deletions
|
@ -70,6 +70,19 @@ const defaultCoreSystemParams = {
|
|||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
MockPluginsService.getOpaqueIds.mockReturnValue(new Map());
|
||||
|
||||
window.performance.mark = jest.fn();
|
||||
window.performance.clearMarks = jest.fn();
|
||||
window.performance.getEntriesByName = jest.fn().mockReturnValue([
|
||||
{
|
||||
detail: 'load_started',
|
||||
startTime: 456,
|
||||
},
|
||||
{
|
||||
detail: 'bootstrap_started',
|
||||
startTime: 123,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
function createCoreSystem(params = {}) {
|
||||
|
@ -221,7 +234,9 @@ describe('#start()', () => {
|
|||
});
|
||||
|
||||
await core.setup();
|
||||
await core.start();
|
||||
|
||||
const services = await core.start();
|
||||
await services?.application.navigateToApp('home');
|
||||
}
|
||||
|
||||
it('clears the children of the rootDomElement and appends container for rendering service with #kibana-body, notifications, overlays', async () => {
|
||||
|
@ -233,16 +248,22 @@ describe('#start()', () => {
|
|||
);
|
||||
});
|
||||
|
||||
it('reports the event Loaded Kibana', async () => {
|
||||
it('reports the event Loaded Kibana and clears marks', async () => {
|
||||
await startCore();
|
||||
expect(analyticsServiceStartMock.reportEvent).toHaveBeenCalledTimes(1);
|
||||
expect(analyticsServiceStartMock.reportEvent).toHaveBeenCalledWith('Loaded Kibana', {
|
||||
kibana_version: '1.2.3',
|
||||
load_started: 456,
|
||||
bootstrap_started: 123,
|
||||
});
|
||||
|
||||
expect(window.performance.clearMarks).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('reports the event Loaded Kibana (with memory)', async () => {
|
||||
fetchOptionalMemoryInfoMock.mockReturnValue({
|
||||
load_started: 456,
|
||||
bootstrap_started: 123,
|
||||
memory_js_heap_size_limit: 3,
|
||||
memory_js_heap_size_total: 2,
|
||||
memory_js_heap_size_used: 1,
|
||||
|
@ -251,6 +272,8 @@ describe('#start()', () => {
|
|||
await startCore();
|
||||
expect(analyticsServiceStartMock.reportEvent).toHaveBeenCalledTimes(1);
|
||||
expect(analyticsServiceStartMock.reportEvent).toHaveBeenCalledWith('Loaded Kibana', {
|
||||
load_started: 456,
|
||||
bootstrap_started: 123,
|
||||
kibana_version: '1.2.3',
|
||||
memory_js_heap_size_limit: 3,
|
||||
memory_js_heap_size_total: 2,
|
||||
|
|
|
@ -15,7 +15,7 @@ import {
|
|||
} from '@kbn/core-injected-metadata-browser-internal';
|
||||
import { DocLinksService } from '@kbn/core-doc-links-browser-internal';
|
||||
import { ThemeService } from '@kbn/core-theme-browser-internal';
|
||||
import type { AnalyticsServiceSetup } from '@kbn/core-analytics-browser';
|
||||
import type { AnalyticsServiceSetup, AnalyticsServiceStart } from '@kbn/core-analytics-browser';
|
||||
import { AnalyticsService } from '@kbn/core-analytics-browser-internal';
|
||||
import { I18nService } from '@kbn/core-i18n-browser-internal';
|
||||
import { CoreSetup, CoreStart } from '.';
|
||||
|
@ -35,6 +35,7 @@ import { CoreApp } from './core_app';
|
|||
import type { InternalApplicationSetup, InternalApplicationStart } from './application/types';
|
||||
import { ExecutionContextService } from './execution_context';
|
||||
import { fetchOptionalMemoryInfo } from './fetch_optional_memory_info';
|
||||
import { KBN_LOAD_MARKS } from './utils';
|
||||
|
||||
interface Params {
|
||||
rootDomElement: HTMLElement;
|
||||
|
@ -124,6 +125,30 @@ export class CoreSystem {
|
|||
|
||||
this.plugins = new PluginsService(this.coreContext, injectedMetadata.uiPlugins);
|
||||
this.coreApp = new CoreApp(this.coreContext);
|
||||
|
||||
performance.mark(KBN_LOAD_MARKS, {
|
||||
detail: 'core_created',
|
||||
});
|
||||
}
|
||||
|
||||
private getLoadMarksInfo() {
|
||||
if (!performance) return [];
|
||||
const reportData: Record<string, number> = {};
|
||||
const marks = performance.getEntriesByName(KBN_LOAD_MARKS);
|
||||
for (const mark of marks) {
|
||||
reportData[(mark as PerformanceMark).detail] = mark.startTime;
|
||||
}
|
||||
|
||||
return reportData;
|
||||
}
|
||||
|
||||
private reportKibanaLoadedEvent(analytics: AnalyticsServiceStart) {
|
||||
analytics.reportEvent('Loaded Kibana', {
|
||||
kibana_version: this.coreContext.env.packageInfo.version,
|
||||
...fetchOptionalMemoryInfo(),
|
||||
...this.getLoadMarksInfo(),
|
||||
});
|
||||
performance.clearMarks(KBN_LOAD_MARKS);
|
||||
}
|
||||
|
||||
public async setup() {
|
||||
|
@ -171,6 +196,10 @@ export class CoreSystem {
|
|||
// Services that do not expose contracts at setup
|
||||
await this.plugins.setup(core);
|
||||
|
||||
performance.mark(KBN_LOAD_MARKS, {
|
||||
detail: 'setup_done',
|
||||
});
|
||||
|
||||
return { fatalErrors: this.fatalErrorsSetup };
|
||||
} catch (error) {
|
||||
if (this.fatalErrorsSetup) {
|
||||
|
@ -267,9 +296,19 @@ export class CoreSystem {
|
|||
targetDomElement: coreUiTargetDomElement,
|
||||
});
|
||||
|
||||
analytics.reportEvent('Loaded Kibana', {
|
||||
kibana_version: this.coreContext.env.packageInfo.version,
|
||||
...fetchOptionalMemoryInfo(),
|
||||
performance.mark(KBN_LOAD_MARKS, {
|
||||
detail: 'start_done',
|
||||
});
|
||||
|
||||
// Wait for the first app navigation to report Kibana Loaded
|
||||
const appSub = application.currentAppId$.subscribe((appId) => {
|
||||
if (appId === undefined) return;
|
||||
|
||||
performance.mark(KBN_LOAD_MARKS, {
|
||||
detail: 'first_app_nav',
|
||||
});
|
||||
this.reportKibanaLoadedEvent(analytics);
|
||||
appSub.unsubscribe();
|
||||
});
|
||||
|
||||
return {
|
||||
|
@ -323,6 +362,33 @@ export class CoreSystem {
|
|||
type: 'long',
|
||||
_meta: { description: 'The used size of the heap', optional: true },
|
||||
},
|
||||
load_started: {
|
||||
type: 'long',
|
||||
_meta: { description: 'When the render template starts loading assets', optional: true },
|
||||
},
|
||||
bootstrap_started: {
|
||||
type: 'long',
|
||||
_meta: { description: 'When kbnBootstrap callback is called', optional: true },
|
||||
},
|
||||
core_created: {
|
||||
type: 'long',
|
||||
_meta: { description: 'When core system is created', optional: true },
|
||||
},
|
||||
setup_done: {
|
||||
type: 'long',
|
||||
_meta: { description: 'When core system setup is complete', optional: true },
|
||||
},
|
||||
start_done: {
|
||||
type: 'long',
|
||||
_meta: { description: 'When core system start is complete', optional: true },
|
||||
},
|
||||
first_app_nav: {
|
||||
type: 'long',
|
||||
_meta: {
|
||||
description: 'When the application emits the first app navigation',
|
||||
optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ describe('kbn_bootstrap', () => {
|
|||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
window.performance.mark = jest.fn();
|
||||
});
|
||||
|
||||
it('does not report a fatal error if apm load fails', async () => {
|
||||
|
|
|
@ -9,9 +9,14 @@
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { CoreSystem } from './core_system';
|
||||
import { ApmSystem } from './apm_system';
|
||||
import { KBN_LOAD_MARKS } from './utils';
|
||||
|
||||
/** @internal */
|
||||
export async function __kbnBootstrap__() {
|
||||
performance.mark(KBN_LOAD_MARKS, {
|
||||
detail: 'bootstrap_started',
|
||||
});
|
||||
|
||||
const injectedMetadata = JSON.parse(
|
||||
document.querySelector('kbn-injected-metadata')!.getAttribute('data')!
|
||||
);
|
||||
|
|
|
@ -1554,6 +1554,6 @@ export interface UserProvidedValues<T = any> {
|
|||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/core/public/core_system.ts:186:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts
|
||||
// src/core/public/core_system.ts:202:21 - (ae-forgotten-export) The symbol "InternalApplicationStart" needs to be exported by the entry point index.d.ts
|
||||
|
||||
```
|
||||
|
|
10
src/core/public/utils/consts.ts
Normal file
10
src/core/public/utils/consts.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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 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 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
/** @internal */
|
||||
export const KBN_LOAD_MARKS = 'kbnLoad';
|
|
@ -9,3 +9,4 @@
|
|||
export { Sha256 } from './crypto';
|
||||
export { MountWrapper, mountReactNode } from './mount';
|
||||
export { CoreContextProvider } from './core_context_provider';
|
||||
export { KBN_LOAD_MARKS } from './consts';
|
||||
|
|
|
@ -104,6 +104,10 @@ if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) {
|
|||
});
|
||||
}
|
||||
|
||||
performance.mark('kbnLoad', {
|
||||
detail: 'load_started',
|
||||
})
|
||||
|
||||
load([
|
||||
'/js-1','/js-2'
|
||||
], function () {
|
||||
|
|
|
@ -120,6 +120,10 @@ if (window.__kbnStrictCsp__ && window.__kbnCspNotEnforced__) {
|
|||
});
|
||||
}
|
||||
|
||||
performance.mark('kbnLoad', {
|
||||
detail: 'load_started',
|
||||
})
|
||||
|
||||
load([
|
||||
${jsDependencyPaths.map((path) => `'${path}'`).join(',')}
|
||||
], function () {
|
||||
|
|
|
@ -25,7 +25,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
expect(event.properties).to.have.property('kibana_version');
|
||||
expect(event.properties.kibana_version).to.be.a('string');
|
||||
|
||||
// Kibana Loaded timings
|
||||
expect(event.properties).to.have.property('load_started');
|
||||
expect(event.properties.load_started).to.be.a('number');
|
||||
expect(event.properties).to.have.property('bootstrap_started');
|
||||
expect(event.properties.bootstrap_started).to.be.a('number');
|
||||
expect(event.properties).to.have.property('core_created');
|
||||
expect(event.properties.core_created).to.be.a('number');
|
||||
expect(event.properties).to.have.property('setup_done');
|
||||
expect(event.properties.setup_done).to.be.a('number');
|
||||
expect(event.properties).to.have.property('start_done');
|
||||
expect(event.properties.start_done).to.be.a('number');
|
||||
expect(event.properties).to.have.property('first_app_nav');
|
||||
expect(event.properties.start_done).to.be.a('number');
|
||||
|
||||
if (browser.isChromium) {
|
||||
// Kibana Loaded memory
|
||||
expect(event.properties).to.have.property('memory_js_heap_size_limit');
|
||||
expect(event.properties.memory_js_heap_size_limit).to.be.a('number');
|
||||
expect(event.properties).to.have.property('memory_js_heap_size_total');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue