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

[Observability] Change appLink passing the date range #71259

Merged
merged 13 commits into from
Jul 14, 2020
8 changes: 3 additions & 5 deletions x-pack/plugins/apm/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ import { toggleAppLinkInNav } from './toggleAppLinkInNav';
import { setReadonlyBadge } from './updateBadge';
import { createStaticIndexPattern } from './services/rest/index_pattern';
import {
fetchLandingPageData,
fetchOverviewPageData,
hasData,
} from './services/rest/observability_dashboard';
} from './services/rest/apm_overview_fetchers';

export type ApmPluginSetup = void;
export type ApmPluginStart = void;
Expand Down Expand Up @@ -81,9 +81,7 @@ export class ApmPlugin implements Plugin<ApmPluginSetup, ApmPluginStart> {
if (plugins.observability) {
plugins.observability.dashboard.register({
appName: 'apm',
fetchData: async (params) => {
return fetchLandingPageData(params);
},
fetchData: fetchOverviewPageData,
hasData,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { fetchLandingPageData, hasData } from './observability_dashboard';
import moment from 'moment';
import { fetchOverviewPageData, hasData } from './apm_overview_fetchers';
import * as createCallApmApi from './createCallApmApi';

describe('Observability dashboard data', () => {
const callApmApiMock = jest.spyOn(createCallApmApi, 'callApmApi');
const params = {
absoluteTime: {
start: moment('2020-07-02T13:25:11.629Z').valueOf(),
end: moment('2020-07-09T14:25:11.629Z').valueOf(),
},
relativeTime: {
start: 'now-15m',
end: 'now',
},
bucketSize: '600s',
};
afterEach(() => {
callApmApiMock.mockClear();
});
Expand All @@ -25,7 +37,7 @@ describe('Observability dashboard data', () => {
});
});

describe('fetchLandingPageData', () => {
describe('fetchOverviewPageData', () => {
it('returns APM data with series and stats', async () => {
callApmApiMock.mockImplementation(() =>
Promise.resolve({
Expand All @@ -37,14 +49,9 @@ describe('Observability dashboard data', () => {
],
})
);
const response = await fetchLandingPageData({
startTime: '1',
endTime: '2',
bucketSize: '3',
});
const response = await fetchOverviewPageData(params);
expect(response).toEqual({
title: 'APM',
appLink: '/app/apm',
appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now',
stats: {
services: {
type: 'number',
Expand Down Expand Up @@ -73,14 +80,9 @@ describe('Observability dashboard data', () => {
transactionCoordinates: [],
})
);
const response = await fetchLandingPageData({
startTime: '1',
endTime: '2',
bucketSize: '3',
});
const response = await fetchOverviewPageData(params);
expect(response).toEqual({
title: 'APM',
appLink: '/app/apm',
appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now',
stats: {
services: {
type: 'number',
Expand All @@ -105,14 +107,9 @@ describe('Observability dashboard data', () => {
transactionCoordinates: [{ x: 1 }, { x: 2 }, { x: 3 }],
})
);
const response = await fetchLandingPageData({
startTime: '1',
endTime: '2',
bucketSize: '3',
});
const response = await fetchOverviewPageData(params);
expect(response).toEqual({
title: 'APM',
appLink: '/app/apm',
appLink: '/app/apm#/services?rangeFrom=now-15m&rangeTo=now',
stats: {
services: {
type: 'number',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,33 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';
import { mean } from 'lodash';
import {
ApmFetchDataResponse,
FetchDataParams,
} from '../../../../observability/public';
import { callApmApi } from './createCallApmApi';

export const fetchLandingPageData = async ({
startTime,
endTime,
export const fetchOverviewPageData = async ({
absoluteTime,
relativeTime,
bucketSize,
}: FetchDataParams): Promise<ApmFetchDataResponse> => {
const data = await callApmApi({
pathname: '/api/apm/observability_dashboard',
params: { query: { start: startTime, end: endTime, bucketSize } },
pathname: '/api/apm/observability_overview',
params: {
query: {
start: new Date(absoluteTime.start).toISOString(),
end: new Date(absoluteTime.end).toISOString(),
bucketSize,
},
},
});

const { serviceCount, transactionCoordinates } = data;

return {
title: i18n.translate('xpack.apm.observabilityDashboard.title', {
defaultMessage: 'APM',
}),
appLink: '/app/apm',
appLink: `/app/apm#/services?rangeFrom=${relativeTime.start}&rangeTo=${relativeTime.end}`,
stats: {
services: {
type: 'number',
Expand All @@ -54,6 +56,6 @@ export const fetchLandingPageData = async ({

export async function hasData() {
return await callApmApi({
pathname: '/api/apm/observability_dashboard/has_data',
pathname: '/api/apm/observability_overview/has_data',
});
}
10 changes: 5 additions & 5 deletions x-pack/plugins/apm/server/routes/create_apm_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,9 @@ import {
rumServicesRoute,
} from './rum_client';
import {
observabilityDashboardHasDataRoute,
observabilityDashboardDataRoute,
} from './observability_dashboard';
observabilityOverviewHasDataRoute,
observabilityOverviewRoute,
} from './observability_overview';
import {
anomalyDetectionJobsRoute,
createAnomalyDetectionJobsRoute,
Expand Down Expand Up @@ -176,8 +176,8 @@ const createApmApi = () => {
.add(rumServicesRoute)

// Observability dashboard
.add(observabilityDashboardHasDataRoute)
.add(observabilityDashboardDataRoute)
.add(observabilityOverviewHasDataRoute)
.add(observabilityOverviewRoute)

// Anomaly detection
.add(anomalyDetectionJobsRoute)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
*/
import * as t from 'io-ts';
import { setupRequest } from '../lib/helpers/setup_request';
import { hasData } from '../lib/observability_dashboard/has_data';
import { getServiceCount } from '../lib/observability_overview/get_service_count';
import { getTransactionCoordinates } from '../lib/observability_overview/get_transaction_coordinates';
import { hasData } from '../lib/observability_overview/has_data';
import { createRoute } from './create_route';
import { rangeRt } from './default_api_types';
import { getServiceCount } from '../lib/observability_dashboard/get_service_count';
import { getTransactionCoordinates } from '../lib/observability_dashboard/get_transaction_coordinates';

export const observabilityDashboardHasDataRoute = createRoute(() => ({
path: '/api/apm/observability_dashboard/has_data',
export const observabilityOverviewHasDataRoute = createRoute(() => ({
path: '/api/apm/observability_overview/has_data',
handler: async ({ context, request }) => {
const setup = await setupRequest(context, request);
return await hasData({ setup });
},
}));

export const observabilityDashboardDataRoute = createRoute(() => ({
path: '/api/apm/observability_dashboard',
export const observabilityOverviewRoute = createRoute(() => ({
path: '/api/apm/observability_overview',
params: {
query: t.intersection([rangeRt, t.type({ bucketSize: t.string })]),
},
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 9 additions & 3 deletions x-pack/plugins/infra/public/metrics_overview_fetchers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,18 @@ describe('Metrics UI Observability Homepage Functions', () => {
const { core, mockedGetStartServices } = setup();
core.http.post.mockResolvedValue(FAKE_SNAPSHOT_RESPONSE);
const fetchData = createMetricsFetchData(mockedGetStartServices);
const endTime = moment();
const endTime = moment('2020-07-02T13:25:11.629Z');
const startTime = endTime.clone().subtract(1, 'h');
const bucketSize = '300s';
const response = await fetchData({
startTime: startTime.toISOString(),
endTime: endTime.toISOString(),
absoluteTime: {
start: startTime.valueOf(),
end: endTime.valueOf(),
},
relativeTime: {
start: 'now-15m',
end: 'now',
},
bucketSize,
});
expect(core.http.post).toHaveBeenCalledTimes(1);
Expand Down
27 changes: 10 additions & 17 deletions x-pack/plugins/infra/public/metrics_overview_fetchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import moment from 'moment';
import { sum, isFinite, isNumber } from 'lodash';
import { i18n } from '@kbn/i18n';
import { MetricsFetchDataResponse, FetchDataParams } from '../../observability/public';
import { isFinite, isNumber, sum } from 'lodash';
import { FetchDataParams, MetricsFetchDataResponse } from '../../observability/public';
import {
SnapshotRequest,
SnapshotMetricInput,
SnapshotNode,
SnapshotNodeResponse,
SnapshotRequest,
} from '../common/http_api/snapshot_api';
import { SnapshotMetricType } from '../common/inventory_models/types';
import { InfraClientCoreSetup } from './types';
Expand Down Expand Up @@ -77,22 +75,21 @@ export const combineNodeTimeseriesBy = (

export const createMetricsFetchData = (
getStartServices: InfraClientCoreSetup['getStartServices']
) => async ({
startTime,
endTime,
bucketSize,
}: FetchDataParams): Promise<MetricsFetchDataResponse> => {
) => async ({ absoluteTime, bucketSize }: FetchDataParams): Promise<MetricsFetchDataResponse> => {
const [coreServices] = await getStartServices();
const { http } = coreServices;

const { start, end } = absoluteTime;

const snapshotRequest: SnapshotRequest = {
sourceId: 'default',
metrics: ['cpu', 'memory', 'rx', 'tx'].map((type) => ({ type })) as SnapshotMetricInput[],
groupBy: [],
nodeType: 'host',
includeTimeseries: true,
timerange: {
from: moment(startTime).valueOf(),
to: moment(endTime).valueOf(),
from: start,
to: end,
interval: bucketSize,
forceInterval: true,
ignoreLookback: true,
Expand All @@ -102,12 +99,8 @@ export const createMetricsFetchData = (
const results = await http.post<SnapshotNodeResponse>('/api/metrics/snapshot', {
body: JSON.stringify(snapshotRequest),
});

return {
title: i18n.translate('xpack.infra.observabilityHomepage.metrics.title', {
defaultMessage: 'Metrics',
}),
appLink: '/app/metrics',
appLink: `/app/metrics/inventory?waffleTime=(currentTime:${end},isAutoReloading:!f)`,
stats: {
hosts: {
type: 'number',
Expand Down
23 changes: 9 additions & 14 deletions x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,17 @@
*/

import { encode } from 'rison-node';
import { i18n } from '@kbn/i18n';
import { SearchResponse } from 'src/plugins/data/public';
import { DEFAULT_SOURCE_ID } from '../../common/constants';
import { InfraClientCoreSetup, InfraClientStartDeps } from '../types';
import {
FetchData,
LogsFetchDataResponse,
HasData,
FetchDataParams,
HasData,
LogsFetchDataResponse,
} from '../../../observability/public';
import { DEFAULT_SOURCE_ID } from '../../common/constants';
import { callFetchLogSourceConfigurationAPI } from '../containers/logs/log_source/api/fetch_log_source_configuration';
import { callFetchLogSourceStatusAPI } from '../containers/logs/log_source/api/fetch_log_source_status';
import { InfraClientCoreSetup, InfraClientStartDeps } from '../types';

interface StatsAggregation {
buckets: Array<{ key: string; doc_count: number }>;
Expand Down Expand Up @@ -69,15 +68,11 @@ export function getLogsOverviewDataFetcher(
data
);

const timeSpanInMinutes =
(Date.parse(params.endTime).valueOf() - Date.parse(params.startTime).valueOf()) / (1000 * 60);
const timeSpanInMinutes = (params.absoluteTime.end - params.absoluteTime.start) / (1000 * 60);

return {
title: i18n.translate('xpack.infra.logs.logOverview.logOverviewTitle', {
defaultMessage: 'Logs',
}),
appLink: `/app/logs/stream?logPosition=(end:${encode(params.endTime)},start:${encode(
params.startTime
appLink: `/app/logs/stream?logPosition=(end:${encode(params.relativeTime.end)},start:${encode(
params.relativeTime.start
)})`,
stats: normalizeStats(stats, timeSpanInMinutes),
series: normalizeSeries(series),
Expand Down Expand Up @@ -122,8 +117,8 @@ function buildLogOverviewQuery(logParams: LogParams, params: FetchDataParams) {
return {
range: {
[logParams.timestampField]: {
gt: params.startTime,
lte: params.endTime,
gt: new Date(params.absoluteTime.start).toISOString(),
lte: new Date(params.absoluteTime.end).toISOString(),
format: 'strict_date_optional_time',
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,16 @@ export const AlertsSection = ({ alerts }: Props) => {

return (
<SectionContainer
title="Alerts"
appLink={'/app/management/insightsAndAlerting/triggersActions/alerts'}
hasError={false}
appLinkName={i18n.translate('xpack.observability.overview.alert.appLink', {
defaultMessage: 'Manage alerts',
title={i18n.translate('xpack.observability.overview.alerts.title', {
defaultMessage: 'Alerts',
})}
appLink={{
href: '/app/management/insightsAndAlerting/triggersActions/alerts',
label: i18n.translate('xpack.observability.overview.alert.appLink', {
defaultMessage: 'Manage alerts',
}),
}}
hasError={false}
>
<EuiFlexGroup direction="column" gutterSize="none">
<EuiFlexItem grow={false}>
Expand Down
Loading