[Uptime] Added uptime query inspector panel (#115170)

This commit is contained in:
Shahzad 2021-10-18 10:35:02 +02:00 committed by GitHub
parent 411816c1c7
commit d08f091d4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 266 additions and 91 deletions

View file

@ -17,8 +17,7 @@ import { argv } from 'yargs';
import { Logger } from 'kibana/server';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { CollectTelemetryParams } from '../../server/lib/apm_telemetry/collect_data_telemetry';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { unwrapEsResponse } from '../../../observability/server/utils/unwrap_es_response';
import { unwrapEsResponse } from '../../../observability/common/utils/unwrap_es_response';
import { downloadTelemetryTemplate } from '../shared/download-telemetry-template';
import { mergeApmTelemetryMapping } from '../../common/apm_telemetry';
import { generateSampleDocuments } from './generate-sample-documents';

View file

@ -8,8 +8,8 @@
import { i18n } from '@kbn/i18n';
import type { KibanaRequest } from 'kibana/server';
import type { RequestStatistics, RequestStatus } from '../../../../../src/plugins/inspector';
import { WrappedElasticsearchClientError } from '../index';
import { InspectResponse } from '../../typings/common';
import { WrappedElasticsearchClientError } from './unwrap_es_response';
/**
* Get statistics to show on inspector tab.
@ -29,19 +29,26 @@ function getStats({
kibanaRequest: KibanaRequest;
}) {
const stats: RequestStatistics = {
kibanaApiQueryParameters: {
label: i18n.translate('xpack.observability.inspector.stats.kibanaApiQueryParametersLabel', {
defaultMessage: 'Kibana API query parameters',
}),
description: i18n.translate(
'xpack.observability.inspector.stats.kibanaApiQueryParametersDescription',
{
defaultMessage:
'The query parameters used in the Kibana API request that initiated the Elasticsearch request.',
...(kibanaRequest.query
? {
kibanaApiQueryParameters: {
label: i18n.translate(
'xpack.observability.inspector.stats.kibanaApiQueryParametersLabel',
{
defaultMessage: 'Kibana API query parameters',
}
),
description: i18n.translate(
'xpack.observability.inspector.stats.kibanaApiQueryParametersDescription',
{
defaultMessage:
'The query parameters used in the Kibana API request that initiated the Elasticsearch request.',
}
),
value: JSON.stringify(kibanaRequest.query, null, 2),
},
}
),
value: JSON.stringify(kibanaRequest.query, null, 2),
},
: {}),
kibanaApiRoute: {
label: i18n.translate('xpack.observability.inspector.stats.kibanaApiRouteLabel', {
defaultMessage: 'Kibana API route',
@ -93,11 +100,17 @@ function getStats({
}
if (esResponse?.hits?.total !== undefined) {
const total = esResponse.hits.total as {
relation: string;
value: number;
};
const hitsTotalValue = total.relation === 'eq' ? `${total.value}` : `> ${total.value}`;
let hitsTotalValue;
if (typeof esResponse.hits.total === 'number') {
hitsTotalValue = esResponse.hits.total;
} else {
const total = esResponse.hits.total as {
relation: string;
value: number;
};
hitsTotalValue = total.relation === 'eq' ? `${total.value}` : `> ${total.value}`;
}
stats.hitsTotal = {
label: i18n.translate('xpack.observability.inspector.stats.hitsTotalLabel', {

View file

@ -12,7 +12,10 @@ import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern';
import { ESFilter } from '../../../../../../../../src/core/types/elasticsearch';
import { PersistableFilter } from '../../../../../../lens/common';
export function useFilterValues({ field, series, baseFilters }: FilterProps, query?: string) {
export function useFilterValues(
{ field, series, baseFilters, label }: FilterProps,
query?: string
) {
const { indexPatterns } = useAppIndexPatternContext(series.dataType);
const queryFilters: ESFilter[] = [];
@ -28,6 +31,7 @@ export function useFilterValues({ field, series, baseFilters }: FilterProps, que
return useValuesList({
query,
label,
sourceField: field,
time: series.time,
keepHistory: true,

View file

@ -33,6 +33,7 @@ export function FieldValueSuggestions({
required,
allowExclusions = true,
cardinalityField,
inspector,
asCombobox = true,
onChange: onSelectionChange,
}: FieldValueSuggestionsProps) {
@ -44,7 +45,9 @@ export function FieldValueSuggestions({
sourceField,
filters,
time,
inspector,
cardinalityField,
label,
keepHistory: true,
});

View file

@ -8,6 +8,7 @@
import { PopoverAnchorPosition } from '@elastic/eui';
import { Dispatch, SetStateAction } from 'react';
import { ESFilter } from 'src/core/types/elasticsearch';
import { IInspectorInfo } from '../../../../../../../src/plugins/data/common';
interface CommonProps {
selectedValue?: string[];
@ -37,6 +38,7 @@ export type FieldValueSuggestionsProps = CommonProps & {
onChange: (val?: string[], excludedValue?: string[]) => void;
filters: ESFilter[];
time?: { from: string; to: string };
inspector?: IInspectorInfo;
};
export type FieldValueSelectionProps = CommonProps & {

View file

@ -23,6 +23,13 @@ const value: InspectorContextValue = {
export const InspectorContext = createContext<InspectorContextValue>(value);
export type AddInspectorRequest = (
result: FetcherResult<{
mainStatisticsData?: { _inspect?: InspectResponse };
_inspect?: InspectResponse;
}>
) => void;
export function InspectorContextProvider({ children }: { children: ReactNode }) {
const history = useHistory();
const { inspectorAdapters } = value;

View file

@ -9,27 +9,61 @@ import { estypes } from '@elastic/elasticsearch';
import { DataPublicPluginStart } from '../../../../../src/plugins/data/public';
import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch';
import { useKibana } from '../../../../../src/plugins/kibana_react/public';
import { isCompleteResponse } from '../../../../../src/plugins/data/common';
import { useFetcher } from './use_fetcher';
import { IInspectorInfo, isCompleteResponse } from '../../../../../src/plugins/data/common';
import { FETCH_STATUS, useFetcher } from './use_fetcher';
import { useInspectorContext } from '../context/inspector/use_inspector_context';
import { getInspectResponse } from '../../common/utils/get_inspect_response';
export const useEsSearch = <DocumentSource extends unknown, TParams extends estypes.SearchRequest>(
params: TParams,
fnDeps: any[]
fnDeps: any[],
options: { inspector?: IInspectorInfo; name: string }
) => {
const {
services: { data },
} = useKibana<{ data: DataPublicPluginStart }>();
const { name } = options ?? {};
const { addInspectorRequest } = useInspectorContext();
const { data: response = {}, loading } = useFetcher(() => {
if (params.index) {
const startTime = Date.now();
return new Promise((resolve) => {
const search$ = data.search
.search({
params,
})
.search(
{
params,
},
{}
)
.subscribe({
next: (result) => {
if (isCompleteResponse(result)) {
if (addInspectorRequest) {
addInspectorRequest({
data: {
_inspect: [
getInspectResponse({
startTime,
esRequestParams: params,
esResponse: result.rawResponse,
esError: null,
esRequestStatus: 1,
operationName: name,
kibanaRequest: {
route: {
path: '/internal/bsearch',
method: 'POST',
},
} as any,
}),
],
},
status: FETCH_STATUS.SUCCESS,
});
}
// Final result
resolve(result);
search$.unsubscribe();

View file

@ -10,16 +10,19 @@ import { useEffect, useState } from 'react';
import useDebounce from 'react-use/lib/useDebounce';
import { ESFilter } from '../../../../../src/core/types/elasticsearch';
import { createEsParams, useEsSearch } from './use_es_search';
import { IInspectorInfo } from '../../../../../src/plugins/data/common';
import { TRANSACTION_URL } from '../components/shared/exploratory_view/configurations/constants/elasticsearch_fieldnames';
export interface Props {
sourceField: string;
label: string;
query?: string;
indexPatternTitle?: string;
filters?: ESFilter[];
time?: { from: string; to: string };
keepHistory?: boolean;
cardinalityField?: string;
inspector?: IInspectorInfo;
}
export interface ListItem {
@ -60,6 +63,7 @@ export const useValuesList = ({
query = '',
filters,
time,
label,
keepHistory,
cardinalityField,
}: Props): { values: ListItem[]; loading?: boolean } => {
@ -131,7 +135,8 @@ export const useValuesList = ({
},
},
}),
[debouncedQuery, from, to, JSON.stringify(filters), indexPatternTitle, sourceField]
[debouncedQuery, from, to, JSON.stringify(filters), indexPatternTitle, sourceField],
{ name: `get${label.replace(/\s/g, '')}ValuesList` }
);
useEffect(() => {

View file

@ -83,5 +83,8 @@ export type {
export { createObservabilityRuleTypeRegistryMock } from './rules/observability_rule_type_registry_mock';
export type { ExploratoryEmbeddableProps } from './components/shared/exploratory_view/embeddable/embeddable';
export { InspectorContextProvider } from './context/inspector/inspector_context';
export {
InspectorContextProvider,
AddInspectorRequest,
} from './context/inspector/inspector_context';
export { useInspectorContext } from './context/inspector/use_inspector_context';

View file

@ -13,9 +13,12 @@ import { PluginConfigDescriptor, PluginInitializerContext } from 'src/core/serve
import { ObservabilityPlugin, ObservabilityPluginSetup } from './plugin';
import { createOrUpdateIndex, Mappings } from './utils/create_or_update_index';
import { ScopedAnnotationsClient } from './lib/annotations/bootstrap_annotations';
import { unwrapEsResponse, WrappedElasticsearchClientError } from './utils/unwrap_es_response';
import {
unwrapEsResponse,
WrappedElasticsearchClientError,
} from '../common/utils/unwrap_es_response';
export { rangeQuery, kqlQuery } from './utils/queries';
export { getInspectResponse } from './utils/get_inspect_response';
export { getInspectResponse } from '../common/utils/get_inspect_response';
export * from './types';

View file

@ -17,7 +17,7 @@ import {
} from '../../../common/annotations';
import { createOrUpdateIndex } from '../../utils/create_or_update_index';
import { mappings } from './mappings';
import { unwrapEsResponse } from '../../utils/unwrap_es_response';
import { unwrapEsResponse } from '../../../common/utils/unwrap_es_response';
type CreateParams = t.TypeOf<typeof createAnnotationRt>;
type DeleteParams = t.TypeOf<typeof deleteAnnotationRt>;

View file

@ -14,6 +14,7 @@
"requiredPlugins": [
"alerting",
"embeddable",
"inspector",
"features",
"licensing",
"triggersActionsUi",

View file

@ -42,6 +42,7 @@ import {
LazySyntheticsPolicyEditExtension,
} from '../components/fleet_package';
import { LazySyntheticsCustomAssetsExtension } from '../components/fleet_package/lazy_synthetics_custom_assets_extension';
import { Start as InspectorPluginStart } from '../../../../../src/plugins/inspector/public';
export interface ClientPluginsSetup {
data: DataPublicPluginSetup;
@ -56,6 +57,7 @@ export interface ClientPluginsStart {
triggersActionsUi: TriggersAndActionsUIPublicPluginStart;
fleet?: FleetStart;
observability: ObservabilityPublicStart;
inspector: InspectorPluginStart;
}
export interface UptimePluginServices extends Partial<CoreStart> {

View file

@ -33,6 +33,7 @@ import { ActionMenu } from '../components/common/header/action_menu';
import { EuiThemeProvider } from '../../../../../src/plugins/kibana_react/common';
import { Storage } from '../../../../../src/plugins/kibana_utils/public';
import { UptimeIndexPatternContextProvider } from '../contexts/uptime_index_pattern_context';
import { InspectorContextProvider } from '../../../observability/public';
export interface UptimeAppColors {
danger: string;
@ -110,6 +111,7 @@ const Application = (props: UptimeAppProps) => {
...plugins,
storage,
data: startPlugins.data,
inspector: startPlugins.inspector,
triggersActionsUi: startPlugins.triggersActionsUi,
observability: startPlugins.observability,
}}
@ -126,9 +128,11 @@ const Application = (props: UptimeAppProps) => {
className={APP_WRAPPER_CLASS}
application={core.application}
>
<UptimeAlertsFlyoutWrapper />
<PageRouter />
<ActionMenu appMountParameters={appMountParameters} />
<InspectorContextProvider>
<UptimeAlertsFlyoutWrapper />
<PageRouter />
<ActionMenu appMountParameters={appMountParameters} />
</InspectorContextProvider>
</RedirectAppLinks>
</div>
</UptimeIndexPatternContextProvider>

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import React, { useMemo } from 'react';
import React, { useEffect, useMemo } from 'react';
import styled from 'styled-components';
import { EuiPageHeaderProps } from '@elastic/eui';
import { CERTIFICATES_ROUTE, OVERVIEW_ROUTE } from '../../common/constants';
@ -15,6 +15,7 @@ import { useNoDataConfig } from './use_no_data_config';
import { EmptyStateLoading } from '../components/overview/empty_state/empty_state_loading';
import { EmptyStateError } from '../components/overview/empty_state/empty_state_error';
import { useHasData } from '../components/overview/empty_state/use_has_data';
import { useInspectorContext } from '../../../observability/public';
interface Props {
path: string;
@ -39,6 +40,11 @@ export const UptimePageTemplateComponent: React.FC<Props> = ({ path, pageHeader,
const noDataConfig = useNoDataConfig();
const { loading, error, data } = useHasData();
const { inspectorAdapters } = useInspectorContext();
useEffect(() => {
inspectorAdapters.requests.reset();
}, [inspectorAdapters.requests]);
if (error) {
return <EmptyStateError errors={[error]} />;

View file

@ -7,7 +7,7 @@
import { useSelector } from 'react-redux';
import { useContext } from 'react';
import { useEsSearch, createEsParams } from '../../../../observability/public';
import { createEsParams, useEsSearch } from '../../../../observability/public';
import { CertResult, GetCertsParams, Ping } from '../../../common/runtime_types';
@ -48,13 +48,13 @@ export const useCertSearch = ({
body: searchBody,
});
const { data: result, loading } = useEsSearch<Ping, typeof esParams>(esParams, [
settings.settings?.heartbeatIndices,
size,
pageIndex,
lastRefresh,
search,
]);
const { data: result, loading } = useEsSearch<Ping, typeof esParams>(
esParams,
[settings.settings?.heartbeatIndices, size, pageIndex, lastRefresh, search],
{
name: 'getTLSCertificates',
}
);
return result ? { ...processCertsResult(result), loading } : { certs: [], total: 0, loading };
};

View file

@ -18,6 +18,7 @@ import { useGetUrlParams } from '../../../hooks';
import { ToggleAlertFlyoutButton } from '../../overview/alerts/alerts_containers';
import { SETTINGS_ROUTE } from '../../../../common/constants';
import { stringifyUrlParams } from '../../../lib/helper/stringify_url_params';
import { InspectorHeaderLink } from './inspector_header_link';
import { monitorStatusSelector } from '../../../state/selectors';
const ADD_DATA_LABEL = i18n.translate('xpack.uptime.addDataButtonLabel', {
@ -107,6 +108,7 @@ export function ActionMenuContent(): React.ReactElement {
>
{ADD_DATA_LABEL}
</EuiHeaderLink>
<InspectorHeaderLink />
</EuiHeaderLinks>
);
}

View file

@ -0,0 +1,39 @@
/*
* 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 { EuiHeaderLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React from 'react';
import { useKibana } from '../../../../../../../src/plugins/kibana_react/public';
import { enableInspectEsQueries, useInspectorContext } from '../../../../../observability/public';
import { ClientPluginsStart } from '../../../apps/plugin';
export function InspectorHeaderLink() {
const {
services: { inspector, uiSettings },
} = useKibana<ClientPluginsStart>();
const { inspectorAdapters } = useInspectorContext();
const isInspectorEnabled = uiSettings?.get<boolean>(enableInspectEsQueries);
const inspect = () => {
inspector.open(inspectorAdapters);
};
if (!isInspectorEnabled) {
return null;
}
return (
<EuiHeaderLink color="primary" onClick={inspect}>
{i18n.translate('xpack.uptime.inspectButtonText', {
defaultMessage: 'Inspect',
})}
</EuiHeaderLink>
);
}

View file

@ -33,6 +33,7 @@ describe('ML Flyout component', () => {
spy1.mockReturnValue(false);
const value = {
isDevMode: true,
basePath: '',
dateRangeStart: DATE_RANGE_START,
dateRangeEnd: DATE_RANGE_END,
@ -48,6 +49,7 @@ describe('ML Flyout component', () => {
onClose={onClose}
canCreateMLJob={true}
/>
uptime/public/state/api/utils.ts
</UptimeSettingsContext.Provider>
);
@ -57,6 +59,7 @@ describe('ML Flyout component', () => {
it('able to create job if valid license is available', async () => {
const value = {
isDevMode: true,
basePath: '',
dateRangeStart: DATE_RANGE_START,
dateRangeEnd: DATE_RANGE_END,

View file

@ -87,7 +87,8 @@ describe('useStepWaterfallMetrics', () => {
},
index: 'heartbeat-*',
},
['heartbeat-*', '44D-444FFF-444-FFF-3333', true]
['heartbeat-*', '44D-444FFF-444-FFF-3333', true],
{ name: 'getWaterfallStepMetrics' }
);
expect(result.current).toEqual({
loading: false,

View file

@ -57,7 +57,10 @@ export const useStepWaterfallMetrics = ({ checkGroup, hasNavigationRequest, step
},
})
: {},
[heartbeatIndices, checkGroup, hasNavigationRequest]
[heartbeatIndices, checkGroup, hasNavigationRequest],
{
name: 'getWaterfallStepMetrics',
}
);
if (!hasNavigationRequest) {

View file

@ -8,9 +8,10 @@
import React, { useCallback, useState } from 'react';
import { EuiFilterGroup } from '@elastic/eui';
import styled from 'styled-components';
import { capitalize } from 'lodash';
import { useFilterUpdate } from '../../../hooks/use_filter_update';
import { useSelectedFilters } from '../../../hooks/use_selected_filters';
import { FieldValueSuggestions } from '../../../../../observability/public';
import { FieldValueSuggestions, useInspectorContext } from '../../../../../observability/public';
import { SelectedFilters } from './selected_filters';
import { useIndexPattern } from '../../../contexts/uptime_index_pattern_context';
import { useGetUrlParams } from '../../../hooks';
@ -34,6 +35,8 @@ export const FilterGroup = () => {
const { dateRangeStart, dateRangeEnd } = useGetUrlParams();
const { inspectorAdapters } = useInspectorContext();
const { filtersList } = useSelectedFilters();
const indexPattern = useIndexPattern();
@ -67,6 +70,10 @@ export const FilterGroup = () => {
filters={[]}
cardinalityField="monitor.id"
time={{ from: dateRangeStart, to: dateRangeEnd }}
inspector={{
adapter: inspectorAdapters.requests,
title: 'get' + capitalize(label) + 'FilterValues',
}}
/>
))}
</Container>

View file

@ -37,10 +37,13 @@ export const useMonitorHistogram = ({ items }: { items: MonitorSummary[] }) => {
monitorIds
);
const { data, loading } = useEsSearch<Ping, typeof queryParams>(queryParams, [
JSON.stringify(monitorIds),
lastRefresh,
]);
const { data, loading } = useEsSearch<Ping, typeof queryParams>(
queryParams,
[JSON.stringify(monitorIds), lastRefresh],
{
name: 'getMonitorDownHistory',
}
);
const histogramBuckets = data?.aggregations?.histogram.buckets ?? [];
const simplified = histogramBuckets.map((histogramBucket) => {

View file

@ -39,6 +39,8 @@ import {
StepDetailPageRightSideItem,
} from './pages/synthetics/step_detail_page';
import { UptimePageTemplateComponent } from './apps/uptime_page_template';
import { apiService } from './state/api/utils';
import { useInspectorContext } from '../../observability/public';
interface RouteProps {
path: string;
@ -178,6 +180,10 @@ const RouteInit: React.FC<Pick<RouteProps, 'path' | 'title' | 'telemetryId'>> =
};
export const PageRouter: FC = () => {
const { addInspectorRequest } = useInspectorContext();
apiService.addInspectorRequest = addInspectorRequest;
return (
<Switch>
{Routes.map(

View file

@ -18,6 +18,7 @@ describe('snapshot API', () => {
get: jest.fn(),
fetch: jest.fn(),
} as any;
apiService.addInspectorRequest = jest.fn();
fetchMock = jest.spyOn(apiService.http, 'fetch');
mockResponse = { up: 3, down: 12, total: 15 };
});

View file

@ -9,7 +9,7 @@ import { PathReporter } from 'io-ts/lib/PathReporter';
import { isRight } from 'fp-ts/lib/Either';
import { HttpFetchQuery, HttpSetup } from 'src/core/public';
import * as t from 'io-ts';
import { startsWith } from 'lodash';
import { FETCH_STATUS, AddInspectorRequest } from '../../../../observability/public';
function isObject(value: unknown) {
const type = typeof value;
@ -43,6 +43,7 @@ export const formatErrors = (errors: t.Errors): string[] => {
class ApiService {
private static instance: ApiService;
private _http!: HttpSetup;
private _addInspectorRequest!: AddInspectorRequest;
public get http() {
return this._http;
@ -52,6 +53,14 @@ class ApiService {
this._http = httpSetup;
}
public get addInspectorRequest() {
return this._addInspectorRequest;
}
public set addInspectorRequest(addInspectorRequest: AddInspectorRequest) {
this._addInspectorRequest = addInspectorRequest;
}
private constructor() {}
static getInstance(): ApiService {
@ -63,15 +72,14 @@ class ApiService {
}
public async get(apiUrl: string, params?: HttpFetchQuery, decodeType?: any, asResponse = false) {
const debugEnabled =
sessionStorage.getItem('uptime_debug') === 'true' && startsWith(apiUrl, '/api/uptime');
const response = await this._http!.fetch({
path: apiUrl,
query: { ...params, ...(debugEnabled ? { _inspect: true } : {}) },
query: params,
asResponse,
});
this.addInspectorRequest?.({ data: response, status: FETCH_STATUS.SUCCESS, loading: false });
if (decodeType) {
const decoded = decodeType.decode(response);
if (isRight(decoded)) {

View file

@ -18,6 +18,9 @@ import { UMLicenseCheck } from './domains';
import { UptimeRequests } from './requests';
import { savedObjectsAdapter } from './saved_objects';
import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch';
import { RequestStatus } from '../../../../../src/plugins/inspector';
import { getInspectResponse } from '../../../observability/server';
import { InspectResponse } from '../../../observability/typings/common';
export interface UMDomainLibs {
requests: UptimeRequests;
@ -45,6 +48,8 @@ export interface CountResponse {
export type UptimeESClient = ReturnType<typeof createUptimeESClient>;
export const inspectableEsQueriesMap = new WeakMap<KibanaRequest, InspectResponse>();
export function createUptimeESClient({
esClient,
request,
@ -59,7 +64,8 @@ export function createUptimeESClient({
return {
baseESClient: esClient,
async search<DocumentSource extends unknown, TParams extends estypes.SearchRequest>(
params: TParams
params: TParams,
operationName?: string
): Promise<{ body: ESSearchResponse<DocumentSource, TParams> }> {
let res: any;
let esError: any;
@ -70,11 +76,33 @@ export function createUptimeESClient({
const esParams = { index: dynamicSettings!.heartbeatIndices, ...params };
const startTime = process.hrtime();
const startTimeNow = Date.now();
let esRequestStatus: RequestStatus = RequestStatus.PENDING;
try {
res = await esClient.search(esParams);
esRequestStatus = RequestStatus.OK;
} catch (e) {
esError = e;
esRequestStatus = RequestStatus.ERROR;
}
const inspectableEsQueries = inspectableEsQueriesMap.get(request!);
if (inspectableEsQueries) {
inspectableEsQueries.push(
getInspectResponse({
esError,
esRequestParams: esParams,
esRequestStatus,
esResponse: res.body,
kibanaRequest: request!,
operationName: operationName ?? '',
startTime: startTimeNow,
})
);
}
if (_inspect && request) {
debugESCall({ startTime, request, esError, operationName: 'search', params: esParams });
}

View file

@ -87,7 +87,7 @@ export const getPingHistogram: UMElasticsearchQueryFn<GetPingHistogramParams, Hi
},
});
const { body: result } = await uptimeEsClient.search(params);
const { body: result } = await uptimeEsClient.search(params, 'getPingsOverTime');
const buckets = result?.aggregations?.timeseries?.buckets ?? [];
const histogram = buckets.map((bucket) => {

View file

@ -43,9 +43,12 @@ export const getSnapshotCount: UMElasticsearchQueryFn<GetSnapshotCountParams, Sn
};
const statusCount = async (context: QueryContext): Promise<Snapshot> => {
const { body: res } = await context.search({
body: statusCountBody(await context.dateAndCustomFilters(), context),
});
const { body: res } = await context.search(
{
body: statusCountBody(await context.dateAndCustomFilters(), context),
},
'geSnapshotCount'
);
return (
(res.aggregations?.counts?.value as Snapshot) ?? {

View file

@ -40,7 +40,7 @@ const query = async (queryContext: QueryContext, searchAfter: any, size: number)
body,
};
const response = await queryContext.search(params);
const response = await queryContext.search(params, 'getMonitorList-potentialMatches');
return response;
};

View file

@ -43,8 +43,8 @@ export class QueryContext {
this.query = query;
}
async search<TParams>(params: TParams) {
return this.callES.search(params);
async search<TParams>(params: TParams, operationName?: string) {
return this.callES.search(params, operationName);
}
async count(params: any): Promise<any> {

View file

@ -165,5 +165,5 @@ export const query = async (
},
};
return await queryContext.search(params);
return await queryContext.search(params, 'getMonitorList-refinePotentialMatches');
};

View file

@ -5,7 +5,6 @@
* 2.0.
*/
import { schema } from '@kbn/config-schema';
import { UMServerLibs } from '../../lib/lib';
import { UMRestApiRouteFactory } from '../types';
import { API_URLS } from '../../../common/constants';
@ -13,11 +12,7 @@ import { API_URLS } from '../../../common/constants';
export const createGetIndexStatusRoute: UMRestApiRouteFactory = (libs: UMServerLibs) => ({
method: 'GET',
path: API_URLS.INDEX_STATUS,
validate: {
query: schema.object({
_inspect: schema.maybe(schema.boolean()),
}),
},
validate: {},
handler: async ({ uptimeEsClient }): Promise<any> => {
return await libs.requests.getIndexStatus({ uptimeEsClient });
},

View file

@ -21,7 +21,6 @@ export const createMonitorListRoute: UMRestApiRouteFactory = (libs) => ({
statusFilter: schema.maybe(schema.string()),
query: schema.maybe(schema.string()),
pageSize: schema.number(),
_inspect: schema.maybe(schema.boolean()),
}),
},
options: {

View file

@ -18,7 +18,6 @@ export const createGetMonitorLocationsRoute: UMRestApiRouteFactory = (libs: UMSe
monitorId: schema.string(),
dateStart: schema.string(),
dateEnd: schema.string(),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request }): Promise<any> => {

View file

@ -18,7 +18,6 @@ export const createGetStatusBarRoute: UMRestApiRouteFactory = (libs: UMServerLib
monitorId: schema.string(),
dateStart: schema.string(),
dateEnd: schema.string(),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request }): Promise<any> => {

View file

@ -18,7 +18,6 @@ export const createGetMonitorDetailsRoute: UMRestApiRouteFactory = (libs: UMServ
monitorId: schema.string(),
dateStart: schema.maybe(schema.string()),
dateEnd: schema.maybe(schema.string()),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, context, request }): Promise<any> => {

View file

@ -19,7 +19,6 @@ export const createGetMonitorDurationRoute: UMRestApiRouteFactory = (libs: UMSer
monitorId: schema.string(),
dateStart: schema.string(),
dateEnd: schema.string(),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request }): Promise<any> => {

View file

@ -21,7 +21,6 @@ export const createGetPingHistogramRoute: UMRestApiRouteFactory = (libs: UMServe
filters: schema.maybe(schema.string()),
bucketSize: schema.maybe(schema.string()),
query: schema.maybe(schema.string()),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request }): Promise<any> => {

View file

@ -24,7 +24,6 @@ export const createGetPingsRoute: UMRestApiRouteFactory = (libs: UMServerLibs) =
size: schema.maybe(schema.number()),
sort: schema.maybe(schema.string()),
status: schema.maybe(schema.string()),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request, response }): Promise<any> => {

View file

@ -22,9 +22,6 @@ export const createJourneyScreenshotBlocksRoute: UMRestApiRouteFactory = (libs:
body: schema.object({
hashes: schema.arrayOf(schema.string()),
}),
query: schema.object({
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ request, response, uptimeEsClient }) => {
const { hashes: blockIds } = request.body;

View file

@ -26,10 +26,6 @@ export const createJourneyScreenshotRoute: UMRestApiRouteFactory = (libs: UMServ
params: schema.object({
checkGroup: schema.string(),
stepIndex: schema.number(),
_inspect: schema.maybe(schema.boolean()),
}),
query: schema.object({
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request, response }) => {

View file

@ -22,7 +22,6 @@ export const createJourneyRoute: UMRestApiRouteFactory = (libs: UMServerLibs) =>
syntheticEventTypes: schema.maybe(
schema.oneOf([schema.arrayOf(schema.string()), schema.string()])
),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request, response }): Promise<any> => {
@ -59,7 +58,6 @@ export const createJourneyFailedStepsRoute: UMRestApiRouteFactory = (libs: UMSer
validate: {
query: schema.object({
checkGroups: schema.arrayOf(schema.string()),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request, response }): Promise<any> => {

View file

@ -19,7 +19,6 @@ export const createGetSnapshotCount: UMRestApiRouteFactory = (libs: UMServerLibs
dateRangeEnd: schema.string(),
filters: schema.maybe(schema.string()),
query: schema.maybe(schema.string()),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request }): Promise<any> => {

View file

@ -22,7 +22,6 @@ export const createLastSuccessfulStepRoute: UMRestApiRouteFactory = (libs: UMSer
monitorId: schema.string(),
stepIndex: schema.number(),
timestamp: schema.string(),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ uptimeEsClient, request, response }) => {

View file

@ -22,7 +22,6 @@ export const createLogPageViewRoute: UMRestApiRouteFactory = () => ({
autoRefreshEnabled: schema.boolean(),
autorefreshInterval: schema.number(),
refreshTelemetryHistory: schema.maybe(schema.boolean()),
_inspect: schema.maybe(schema.boolean()),
}),
},
handler: async ({ savedObjectsClient, uptimeEsClient, request }): Promise<any> => {

View file

@ -6,10 +6,11 @@
*/
import { UMKibanaRouteWrapper } from './types';
import { createUptimeESClient } from '../lib/lib';
import { createUptimeESClient, inspectableEsQueriesMap } from '../lib/lib';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { KibanaResponse } from '../../../../../src/core/server/http/router';
import { enableInspectEsQueries } from '../../../observability/common';
export const uptimeRouteWrapper: UMKibanaRouteWrapper = (uptimeRoute) => ({
...uptimeRoute,
@ -20,11 +21,18 @@ export const uptimeRouteWrapper: UMKibanaRouteWrapper = (uptimeRoute) => ({
const { client: esClient } = context.core.elasticsearch;
const { client: savedObjectsClient } = context.core.savedObjects;
const isInspectorEnabled = await context.core.uiSettings.client.get<boolean>(
enableInspectEsQueries
);
const uptimeEsClient = createUptimeESClient({
request,
savedObjectsClient,
esClient: esClient.asCurrentUser,
});
if (isInspectorEnabled) {
inspectableEsQueriesMap.set(request, []);
}
const res = await uptimeRoute.handler({
uptimeEsClient,
@ -41,6 +49,7 @@ export const uptimeRouteWrapper: UMKibanaRouteWrapper = (uptimeRoute) => ({
return response.ok({
body: {
...res,
...(isInspectorEnabled ? { _inspect: inspectableEsQueriesMap.get(request) } : {}),
},
});
},