Skip to content

Commit

Permalink
[APM] Fix search bar suggestions (#141101)
Browse files Browse the repository at this point in the history
  • Loading branch information
sorenlouv authored Sep 22, 2022
1 parent fcbb4e4 commit 52e01a3
Show file tree
Hide file tree
Showing 15 changed files with 414 additions and 181 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
* 2.0.
*/

import { synthtrace } from '../../../../synthtrace';
import { generateData } from './generate_data';

function deleteAllRules() {
cy.log('Delete all rules');
cy.request({
Expand Down Expand Up @@ -38,6 +41,21 @@ describe('Rules', () => {
deleteAllRules();
});

before(() => {
const start = '2021-10-10T00:00:00.000Z';
const end = '2021-10-10T00:01:00.000Z';
synthtrace.index(
generateData({
from: new Date(start).getTime(),
to: new Date(end).getTime(),
})
);
});

after(() => {
synthtrace.clean();
});

describe('Error count', () => {
const ruleName = 'Error count threshold';
const comboBoxInputSelector =
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 { apm, timerange } from '@kbn/apm-synthtrace';

export function generateData({ from, to }: { from: number; to: number }) {
const range = timerange(from, to);

const opbeansJava = apm
.service({
name: 'opbeans-java',
environment: 'production',
agentName: 'java',
})
.instance('opbeans-java-prod-1')
.podId('opbeans-java-prod-1-pod');

const opbeansNode = apm
.service({
name: 'opbeans-node',
environment: 'production',
agentName: 'nodejs',
})
.instance('opbeans-node-prod-1');

return range
.interval('2m')
.rate(1)
.generator((timestamp, index) => [
opbeansJava
.transaction({ transactionName: 'GET /apple 🍎 ' })
.timestamp(timestamp)
.duration(1000)
.success()
.errors(
opbeansJava
.error({ message: `Error ${index}`, type: `exception ${index}` })
.timestamp(timestamp)
),
opbeansNode
.transaction({ transactionName: 'GET /banana 🍌' })
.timestamp(timestamp)
.duration(500)
.success(),
]);
}
10 changes: 8 additions & 2 deletions x-pack/plugins/apm/ftr_e2e/cypress_test_runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export async function cypressTestRunner({ getService }: FtrProviderContext) {
return res;
}

function getCypressCliArgs() {
function getCypressCliArgs(): Record<string, unknown> {
if (!process.env.CYPRESS_CLI_ARGS) {
return {};
}
Expand All @@ -82,5 +82,11 @@ function getCypressCliArgs() {
process.env.CYPRESS_CLI_ARGS
) as Record<string, unknown>;

return cypressCliArgs;
const spec =
typeof cypressCliArgs.spec === 'string' &&
!cypressCliArgs.spec.includes('**')
? `**/${cypressCliArgs.spec}*`
: cypressCliArgs.spec;

return { ...cypressCliArgs, spec };
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const stories: Meta<{}> = {
},
notifications: { toasts: { add: () => {}, addWarning: () => {} } },
uiSettings: { get: () => [] },
dataViews: { get: async () => {} },
dataViews: { create: async () => {} },
} as unknown as CoreStart;

const KibanaReactContext = createKibanaReactContext(coreMock);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function ApmMainTemplate({
const location = useLocation();

const { services } = useKibana<ApmPluginStartDeps>();
const { http, docLinks, observability } = services;
const { http, docLinks, observability, application } = services;
const basePath = http?.basePath.get();

const ObservabilityPageTemplate = observability.navigation.PageTemplate;
Expand All @@ -57,6 +57,19 @@ export function ApmMainTemplate({
return callApmApi('GET /internal/apm/has_data');
}, []);

// create static data view on inital load
useFetcher(
(callApmApi) => {
const canCreateDataView =
application?.capabilities.savedObjectsManagement.edit;

if (canCreateDataView) {
return callApmApi('POST /internal/apm/data_view/static');
}
},
[application?.capabilities.savedObjectsManagement.edit]
);

const shouldBypassNoDataScreen = bypassNoDataScreenPaths.some((path) =>
location.pathname.includes(path)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ApmServiceContextProvider } from '../../context/apm_service/apm_service
import { UrlParamsProvider } from '../../context/url_params_context/url_params_context';
import type { ApmUrlParams } from '../../context/url_params_context/types';
import * as useFetcherHook from '../../hooks/use_fetcher';
import * as useApmDataViewHook from '../../hooks/use_apm_data_view';
import * as useServiceTransactionTypesHook from '../../context/apm_service/use_service_transaction_types_fetcher';
import { renderWithTheme } from '../../utils/test_helpers';
import { fromQuery } from './links/url_helpers';
Expand Down Expand Up @@ -45,6 +46,11 @@ function setup({
.spyOn(useServiceTransactionTypesHook, 'useServiceTransactionTypesFetcher')
.mockReturnValue(serviceTransactionTypes);

// mock transaction types
jest
.spyOn(useApmDataViewHook, 'useApmDataView')
.mockReturnValue({ dataView: undefined });

jest.spyOn(useFetcherHook, 'useFetcher').mockReturnValue({} as any);

return renderWithTheme(
Expand Down
39 changes: 4 additions & 35 deletions x-pack/plugins/apm/public/hooks/use_apm_data_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,10 @@

import { DataView } from '@kbn/data-views-plugin/common';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import { SavedObjectNotFound } from '@kbn/kibana-utils-plugin/common';
import { useEffect, useState } from 'react';
import { APM_STATIC_DATA_VIEW_ID } from '../../common/data_view_constants';
import { useApmPluginContext } from '../context/apm_plugin/use_apm_plugin_context';
import { ApmPluginStartDeps } from '../plugin';
import { callApmApi } from '../services/rest/create_call_apm_api';

async function createStaticApmDataView() {
const res = await callApmApi('POST /internal/apm/data_view/static', {
signal: null,
});
return res.dataView;
}

async function getApmDataViewTitle() {
const res = await callApmApi('GET /internal/apm/data_view/title', {
signal: null,
Expand All @@ -30,37 +20,16 @@ async function getApmDataViewTitle() {

export function useApmDataView() {
const { services } = useKibana<ApmPluginStartDeps>();
const { core } = useApmPluginContext();
const [dataView, setDataView] = useState<DataView | undefined>();

const canCreateDataView =
core.application.capabilities.savedObjectsManagement.edit;

useEffect(() => {
async function fetchDataView() {
try {
// load static data view
return await services.dataViews.get(APM_STATIC_DATA_VIEW_ID);
} catch (e) {
// re-throw if an unhandled error occurred
const notFound = e instanceof SavedObjectNotFound;
if (!notFound) {
throw e;
}

// create static data view if user has permissions
if (canCreateDataView) {
return createStaticApmDataView();
} else {
// or create dynamic data view if user does not have permissions to create a static
const title = await getApmDataViewTitle();
return services.dataViews.create({ title });
}
}
const title = await getApmDataViewTitle();
return services.dataViews.create({ title });
}

fetchDataView().then((dv) => setDataView(dv));
}, [canCreateDataView, services.dataViews]);
fetchDataView().then(setDataView);
}, [services.dataViews]);

return { dataView };
}
2 changes: 1 addition & 1 deletion x-pack/plugins/apm/server/lib/helpers/setup_request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function setupRequest({
plugins,
request,
config,
}: APMRouteHandlerResources) {
}: APMRouteHandlerResources): Promise<Setup> {
return withApmSpan('setup_request', async () => {
const { query } = params;
const coreContext = await context.core;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
import { createStaticDataView } from './create_static_data_view';
import { Setup } from '../../lib/helpers/setup_request';
import * as HistoricalAgentData from '../historical_data/has_historical_agent_data';
import { APMConfig } from '../..';
import { DataViewsService } from '@kbn/data-views-plugin/common';
import { APMRouteHandlerResources, APMCore } from '../typings';
import { APMConfig } from '../..';

function getMockedDataViewService(existingDataViewTitle: string) {
return {
Expand All @@ -20,7 +21,7 @@ function getMockedDataViewService(existingDataViewTitle: string) {
} as unknown as DataViewsService;
}

const setup = {
const setupMock = {
indices: {
transaction: 'apm-*-transaction-*',
span: 'apm-*-span-*',
Expand All @@ -29,12 +30,28 @@ const setup = {
} as APMConfig['indices'],
} as unknown as Setup;

const coreMock = {
start: () => {
return {
savedObjects: {
getScopedClient: () => {
return {
updateObjectsSpaces: () => {},
};
},
},
};
},
} as unknown as APMCore;

describe('createStaticDataView', () => {
it(`should not create data view if 'xpack.apm.autocreateApmIndexPattern=false'`, async () => {
const dataViewService = getMockedDataViewService('apm-*');
await createStaticDataView({
setup,
config: { autoCreateApmDataView: false } as APMConfig,
setup: setupMock,
resources: {
config: { autoCreateApmDataView: false },
} as APMRouteHandlerResources,
dataViewService,
});
expect(dataViewService.createAndSave).not.toHaveBeenCalled();
Expand All @@ -49,8 +66,10 @@ describe('createStaticDataView', () => {
const dataViewService = getMockedDataViewService('apm-*');

await createStaticDataView({
setup,
config: { autoCreateApmDataView: true } as APMConfig,
setup: setupMock,
resources: {
config: { autoCreateApmDataView: false },
} as APMRouteHandlerResources,
dataViewService,
});
expect(dataViewService.createAndSave).not.toHaveBeenCalled();
Expand All @@ -65,8 +84,11 @@ describe('createStaticDataView', () => {
const dataViewService = getMockedDataViewService('apm-*');

await createStaticDataView({
setup,
config: { autoCreateApmDataView: true } as APMConfig,
setup: setupMock,
resources: {
core: coreMock,
config: { autoCreateApmDataView: true },
} as APMRouteHandlerResources,
dataViewService,
});

Expand All @@ -84,8 +106,11 @@ describe('createStaticDataView', () => {
'apm-*-transaction-*,apm-*-span-*,apm-*-error-*,apm-*-metrics-*';

await createStaticDataView({
setup,
config: { autoCreateApmDataView: true } as APMConfig,
setup: setupMock,
resources: {
core: coreMock,
config: { autoCreateApmDataView: true },
} as APMRouteHandlerResources,
dataViewService,
});

Expand All @@ -110,8 +135,11 @@ describe('createStaticDataView', () => {
);

await createStaticDataView({
setup,
config: { autoCreateApmDataView: true } as APMConfig,
setup: setupMock,
resources: {
core: coreMock,
config: { autoCreateApmDataView: true },
} as APMRouteHandlerResources,
dataViewService,
});

Expand Down
Loading

0 comments on commit 52e01a3

Please sign in to comment.