Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Synthetucs] Added perf metrics for es queries #186313

Merged
merged 9 commits into from
Jun 21, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
import { ViewMode } from '@kbn/embeddable-plugin/common';
import { observabilityFeatureId } from '@kbn/observability-shared-plugin/public';
import styled from 'styled-components';
import { AnalyticsServiceSetup } from '@kbn/core-analytics-browser';
import { useEBTTelemetry } from '../hooks/use_ebt_telemetry';
import { AllSeries } from '../../../..';
import { AppDataType, ReportViewType } from '../types';
import { OperationTypeComponent } from '../series_editor/columns/operation_type_select';
Expand Down Expand Up @@ -61,6 +63,7 @@ export interface ExploratoryEmbeddableComponentProps extends ExploratoryEmbeddab
lens: LensPublicStart;
dataViewState: DataViewState;
lensFormulaHelper?: FormulaPublicApi;
analytics?: AnalyticsServiceSetup;
}

// eslint-disable-next-line import/no-default-export
Expand Down Expand Up @@ -88,6 +91,7 @@ export default function Embeddable(props: ExploratoryEmbeddableComponentProps) {
lineHeight = 32,
searchSessionId,
onLoad,
analytics,
} = props;
const LensComponent = lens?.EmbeddableComponent;
const LensSaveModalComponent = lens?.SaveModalComponent;
Expand All @@ -103,6 +107,11 @@ export default function Embeddable(props: ExploratoryEmbeddableComponentProps) {

const timeRange = customTimeRange ?? series?.time;

const { reportEvent } = useEBTTelemetry({
analytics,
queryName: series ? `${series.dataType}_${series.name}` : title,
});

const actions = useActions({
withActions,
attributes,
Expand Down Expand Up @@ -198,7 +207,10 @@ export default function Embeddable(props: ExploratoryEmbeddableComponentProps) {
extraActions={actions}
viewMode={ViewMode.VIEW}
searchSessionId={searchSessionId}
onLoad={onLoad}
onLoad={(loading, inspectorAdapters) => {
reportEvent(inspectorAdapters);
onLoad?.(loading);
}}
/>
{isSaveOpen && attributesJSON && (
<LensSaveModalComponent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import React, { useCallback, useMemo, useState, useEffect } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
import type { CoreStart } from '@kbn/core/public';
import type { AnalyticsServiceSetup, CoreStart } from '@kbn/core/public';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { EuiErrorBoundary } from '@elastic/eui';
import styled from 'styled-components';
Expand All @@ -31,7 +31,8 @@ function ExploratoryViewEmbeddable(props: ExploratoryEmbeddableComponentProps) {
}

export function getExploratoryViewEmbeddable(
services: CoreStart & ExploratoryViewPublicPluginsStart
services: CoreStart & ExploratoryViewPublicPluginsStart,
analytics?: AnalyticsServiceSetup
) {
const { lens, dataViews: dataViewsService, theme } = services;

Expand Down Expand Up @@ -141,6 +142,7 @@ export function getExploratoryViewEmbeddable(
lensFormulaHelper={lensHelper?.formula}
searchSessionId={services.data.search.session.getSessionId()}
onLoad={onLensLoaded}
analytics={analytics}
/>
</Wrapper>
</KibanaContextProvider>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { DefaultInspectorAdapters } from '@kbn/expressions-plugin/common';
import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
import { AnalyticsServiceSetup } from '@kbn/core-analytics-browser';

export const useEBTTelemetry = ({
analytics,
queryName,
}: {
analytics?: AnalyticsServiceSetup;
queryName?: string;
}) => {
const reportEvent = (inspectorAdapters?: Partial<DefaultInspectorAdapters>) => {
if (inspectorAdapters) {
const { requests } = inspectorAdapters;
if (requests && analytics) {
const listReq = requests.getRequests();
if (listReq.length > 0) {
// find the highest query time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please elaborate why you need to find the highest query time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's because a chart may have many other queries , so we only care about slowest query.

shahzad31 marked this conversation as resolved.
Show resolved Hide resolved
const duration = listReq.reduce((acc, req) => {
const queryTime = Number(req.stats?.queryTime.value.split('ms')?.[0]);
return queryTime > acc ? queryTime : acc;
}, 0);

if (duration) {
reportPerformanceMetricEvent(analytics, {
eventName: 'exploratory_view_query_time',
duration,
meta:
(queryName && {
queryName,
}) ||
undefined,
});
}
}
}
}
};

return {
reportEvent,
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n';
import { BehaviorSubject } from 'rxjs';
import { SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
import {
AnalyticsServiceSetup,
AppMountParameters,
AppUpdater,
CoreSetup,
Expand Down Expand Up @@ -85,6 +86,8 @@ export class Plugin
{
private readonly appUpdater$ = new BehaviorSubject<AppUpdater>(() => ({}));

private analyticsService?: AnalyticsServiceSetup;

constructor(private readonly initContext: PluginInitializerContext) {}

public setup(
Expand Down Expand Up @@ -129,6 +132,8 @@ export class Plugin
],
});

this.analyticsService = core.analytics;

return {
register: registerDataHandler,
};
Expand All @@ -138,7 +143,10 @@ export class Plugin
return {
createExploratoryViewUrl,
getAppDataView: getAppDataView(pluginsStart.dataViews),
ExploratoryViewEmbeddable: getExploratoryViewEmbeddable({ ...coreStart, ...pluginsStart }),
ExploratoryViewEmbeddable: getExploratoryViewEmbeddable(
{ ...coreStart, ...pluginsStart },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The this.analyticsService should be part of coreStart?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well it's coming from coreSetup, not coreStart.

this.analyticsService
),
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@
"@kbn/observability-ai-assistant-plugin",
"@kbn/shared-ux-link-redirect-app",
"@kbn/react-kibana-context-render",
"@kbn/react-kibana-mount"
"@kbn/react-kibana-mount",
"@kbn/core-analytics-browser",
"@kbn/expressions-plugin",
"@kbn/ebt-tools"
],
"exclude": ["target/**/*"]
}