[Logs UI] Add sorting capabilities to categories page (#88051)
* Add sorting capabilities to categories page Co-authored-by: Felix Stürmer <weltenwort@users.noreply.github.com>
This commit is contained in:
parent
b8d43139f3
commit
53f4b21a81
|
@ -30,6 +30,23 @@ export type LogEntryCategoriesHistogramParameters = rt.TypeOf<
|
||||||
typeof logEntryCategoriesHistogramParametersRT
|
typeof logEntryCategoriesHistogramParametersRT
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
const sortOptionsRT = rt.keyof({
|
||||||
|
maximumAnomalyScore: null,
|
||||||
|
logEntryCount: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const sortDirectionsRT = rt.keyof({
|
||||||
|
asc: null,
|
||||||
|
desc: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const categorySortRT = rt.type({
|
||||||
|
field: sortOptionsRT,
|
||||||
|
direction: sortDirectionsRT,
|
||||||
|
});
|
||||||
|
|
||||||
|
export type CategorySort = rt.TypeOf<typeof categorySortRT>;
|
||||||
|
|
||||||
export const getLogEntryCategoriesRequestPayloadRT = rt.type({
|
export const getLogEntryCategoriesRequestPayloadRT = rt.type({
|
||||||
data: rt.intersection([
|
data: rt.intersection([
|
||||||
rt.type({
|
rt.type({
|
||||||
|
@ -41,6 +58,8 @@ export const getLogEntryCategoriesRequestPayloadRT = rt.type({
|
||||||
timeRange: timeRangeRT,
|
timeRange: timeRangeRT,
|
||||||
// a list of histograms to create
|
// a list of histograms to create
|
||||||
histograms: rt.array(logEntryCategoriesHistogramParametersRT),
|
histograms: rt.array(logEntryCategoriesHistogramParametersRT),
|
||||||
|
// the criteria to the categories by
|
||||||
|
sort: categorySortRT,
|
||||||
}),
|
}),
|
||||||
rt.partial({
|
rt.partial({
|
||||||
// the datasets to filter for (optional, unfiltered if not present)
|
// the datasets to filter for (optional, unfiltered if not present)
|
||||||
|
|
|
@ -87,6 +87,8 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent<LogEntryC
|
||||||
isLoadingTopLogEntryCategories,
|
isLoadingTopLogEntryCategories,
|
||||||
logEntryCategoryDatasets,
|
logEntryCategoryDatasets,
|
||||||
topLogEntryCategories,
|
topLogEntryCategories,
|
||||||
|
sortOptions,
|
||||||
|
changeSortOptions,
|
||||||
} = useLogEntryCategoriesResults({
|
} = useLogEntryCategoriesResults({
|
||||||
categoriesCount: 25,
|
categoriesCount: 25,
|
||||||
endTime: categoryQueryTimeRange.timeRange.endTime,
|
endTime: categoryQueryTimeRange.timeRange.endTime,
|
||||||
|
@ -145,7 +147,12 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent<LogEntryC
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getTopLogEntryCategories();
|
getTopLogEntryCategories();
|
||||||
}, [getTopLogEntryCategories, categoryQueryDatasets, categoryQueryTimeRange.lastChangedTime]);
|
}, [
|
||||||
|
getTopLogEntryCategories,
|
||||||
|
categoryQueryDatasets,
|
||||||
|
categoryQueryTimeRange.lastChangedTime,
|
||||||
|
sortOptions,
|
||||||
|
]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getLogEntryCategoryDatasets();
|
getLogEntryCategoryDatasets();
|
||||||
|
@ -219,6 +226,8 @@ export const LogEntryCategoriesResultsContent: React.FunctionComponent<LogEntryC
|
||||||
sourceId={sourceId}
|
sourceId={sourceId}
|
||||||
timeRange={categoryQueryTimeRange.timeRange}
|
timeRange={categoryQueryTimeRange.timeRange}
|
||||||
topCategories={topLogEntryCategories}
|
topCategories={topLogEntryCategories}
|
||||||
|
sortOptions={sortOptions}
|
||||||
|
changeSortOptions={changeSortOptions}
|
||||||
/>
|
/>
|
||||||
</EuiPanel>
|
</EuiPanel>
|
||||||
</EuiFlexItem>
|
</EuiFlexItem>
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { RecreateJobButton } from '../../../../../components/logging/log_analysi
|
||||||
import { AnalyzeInMlButton } from '../../../../../components/logging/log_analysis_results';
|
import { AnalyzeInMlButton } from '../../../../../components/logging/log_analysis_results';
|
||||||
import { DatasetsSelector } from '../../../../../components/logging/log_analysis_results/datasets_selector';
|
import { DatasetsSelector } from '../../../../../components/logging/log_analysis_results/datasets_selector';
|
||||||
import { TopCategoriesTable } from './top_categories_table';
|
import { TopCategoriesTable } from './top_categories_table';
|
||||||
|
import { SortOptions, ChangeSortOptions } from '../../use_log_entry_categories_results';
|
||||||
|
|
||||||
export const TopCategoriesSection: React.FunctionComponent<{
|
export const TopCategoriesSection: React.FunctionComponent<{
|
||||||
availableDatasets: string[];
|
availableDatasets: string[];
|
||||||
|
@ -29,6 +30,8 @@ export const TopCategoriesSection: React.FunctionComponent<{
|
||||||
sourceId: string;
|
sourceId: string;
|
||||||
timeRange: TimeRange;
|
timeRange: TimeRange;
|
||||||
topCategories: LogEntryCategory[];
|
topCategories: LogEntryCategory[];
|
||||||
|
sortOptions: SortOptions;
|
||||||
|
changeSortOptions: ChangeSortOptions;
|
||||||
}> = ({
|
}> = ({
|
||||||
availableDatasets,
|
availableDatasets,
|
||||||
hasSetupCapabilities,
|
hasSetupCapabilities,
|
||||||
|
@ -41,6 +44,8 @@ export const TopCategoriesSection: React.FunctionComponent<{
|
||||||
sourceId,
|
sourceId,
|
||||||
timeRange,
|
timeRange,
|
||||||
topCategories,
|
topCategories,
|
||||||
|
sortOptions,
|
||||||
|
changeSortOptions,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -80,6 +85,8 @@ export const TopCategoriesSection: React.FunctionComponent<{
|
||||||
sourceId={sourceId}
|
sourceId={sourceId}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
topCategories={topCategories}
|
topCategories={topCategories}
|
||||||
|
sortOptions={sortOptions}
|
||||||
|
changeSortOptions={changeSortOptions}
|
||||||
/>
|
/>
|
||||||
</LoadingOverlayWrapper>
|
</LoadingOverlayWrapper>
|
||||||
</>
|
</>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
|
||||||
import numeral from '@elastic/numeral';
|
import numeral from '@elastic/numeral';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import React, { useMemo } from 'react';
|
import React, { useMemo, useCallback } from 'react';
|
||||||
import useSet from 'react-use/lib/useSet';
|
import useSet from 'react-use/lib/useSet';
|
||||||
|
|
||||||
import { euiStyled } from '../../../../../../../observability/public';
|
import { euiStyled } from '../../../../../../../observability/public';
|
||||||
|
@ -24,6 +24,7 @@ import { RegularExpressionRepresentation } from './category_expression';
|
||||||
import { DatasetActionsList } from './datasets_action_list';
|
import { DatasetActionsList } from './datasets_action_list';
|
||||||
import { DatasetsList } from './datasets_list';
|
import { DatasetsList } from './datasets_list';
|
||||||
import { LogEntryCountSparkline } from './log_entry_count_sparkline';
|
import { LogEntryCountSparkline } from './log_entry_count_sparkline';
|
||||||
|
import { SortOptions, ChangeSortOptions } from '../../use_log_entry_categories_results';
|
||||||
|
|
||||||
export const TopCategoriesTable = euiStyled(
|
export const TopCategoriesTable = euiStyled(
|
||||||
({
|
({
|
||||||
|
@ -32,13 +33,28 @@ export const TopCategoriesTable = euiStyled(
|
||||||
sourceId,
|
sourceId,
|
||||||
timeRange,
|
timeRange,
|
||||||
topCategories,
|
topCategories,
|
||||||
|
sortOptions,
|
||||||
|
changeSortOptions,
|
||||||
}: {
|
}: {
|
||||||
categorizationJobId: string;
|
categorizationJobId: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
sourceId: string;
|
sourceId: string;
|
||||||
timeRange: TimeRange;
|
timeRange: TimeRange;
|
||||||
topCategories: LogEntryCategory[];
|
topCategories: LogEntryCategory[];
|
||||||
|
sortOptions: SortOptions;
|
||||||
|
changeSortOptions: ChangeSortOptions;
|
||||||
}) => {
|
}) => {
|
||||||
|
const tableSortOptions = useMemo(() => {
|
||||||
|
return { sort: sortOptions };
|
||||||
|
}, [sortOptions]);
|
||||||
|
|
||||||
|
const handleTableChange = useCallback(
|
||||||
|
({ sort = {} }) => {
|
||||||
|
changeSortOptions(sort);
|
||||||
|
},
|
||||||
|
[changeSortOptions]
|
||||||
|
);
|
||||||
|
|
||||||
const [expandedCategories, { add: expandCategory, remove: collapseCategory }] = useSet<number>(
|
const [expandedCategories, { add: expandCategory, remove: collapseCategory }] = useSet<number>(
|
||||||
new Set()
|
new Set()
|
||||||
);
|
);
|
||||||
|
@ -80,6 +96,8 @@ export const TopCategoriesTable = euiStyled(
|
||||||
itemId="categoryId"
|
itemId="categoryId"
|
||||||
items={topCategories}
|
items={topCategories}
|
||||||
rowProps={{ className: `${className} euiTableRow--topAligned` }}
|
rowProps={{ className: `${className} euiTableRow--topAligned` }}
|
||||||
|
onChange={handleTableChange}
|
||||||
|
sorting={tableSortOptions}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -102,6 +120,7 @@ const createColumns = (
|
||||||
name: i18n.translate('xpack.infra.logs.logEntryCategories.countColumnTitle', {
|
name: i18n.translate('xpack.infra.logs.logEntryCategories.countColumnTitle', {
|
||||||
defaultMessage: 'Message count',
|
defaultMessage: 'Message count',
|
||||||
}),
|
}),
|
||||||
|
sortable: true,
|
||||||
render: (logEntryCount: number) => {
|
render: (logEntryCount: number) => {
|
||||||
return numeral(logEntryCount).format('0,0');
|
return numeral(logEntryCount).format('0,0');
|
||||||
},
|
},
|
||||||
|
@ -147,6 +166,7 @@ const createColumns = (
|
||||||
name: i18n.translate('xpack.infra.logs.logEntryCategories.maximumAnomalyScoreColumnTitle', {
|
name: i18n.translate('xpack.infra.logs.logEntryCategories.maximumAnomalyScoreColumnTitle', {
|
||||||
defaultMessage: 'Maximum anomaly score',
|
defaultMessage: 'Maximum anomaly score',
|
||||||
}),
|
}),
|
||||||
|
sortable: true,
|
||||||
render: (_maximumAnomalyScore: number, item) => (
|
render: (_maximumAnomalyScore: number, item) => (
|
||||||
<AnomalySeverityIndicatorList datasets={item.datasets} />
|
<AnomalySeverityIndicatorList datasets={item.datasets} />
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
getLogEntryCategoriesRequestPayloadRT,
|
getLogEntryCategoriesRequestPayloadRT,
|
||||||
getLogEntryCategoriesSuccessReponsePayloadRT,
|
getLogEntryCategoriesSuccessReponsePayloadRT,
|
||||||
LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH,
|
LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH,
|
||||||
|
CategorySort,
|
||||||
} from '../../../../../common/http_api/log_analysis';
|
} from '../../../../../common/http_api/log_analysis';
|
||||||
import { decodeOrThrow } from '../../../../../common/runtime_types';
|
import { decodeOrThrow } from '../../../../../common/runtime_types';
|
||||||
|
|
||||||
|
@ -19,13 +20,14 @@ interface RequestArgs {
|
||||||
endTime: number;
|
endTime: number;
|
||||||
categoryCount: number;
|
categoryCount: number;
|
||||||
datasets?: string[];
|
datasets?: string[];
|
||||||
|
sort: CategorySort;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const callGetTopLogEntryCategoriesAPI = async (
|
export const callGetTopLogEntryCategoriesAPI = async (
|
||||||
requestArgs: RequestArgs,
|
requestArgs: RequestArgs,
|
||||||
fetch: HttpHandler
|
fetch: HttpHandler
|
||||||
) => {
|
) => {
|
||||||
const { sourceId, startTime, endTime, categoryCount, datasets } = requestArgs;
|
const { sourceId, startTime, endTime, categoryCount, datasets, sort } = requestArgs;
|
||||||
const intervalDuration = endTime - startTime;
|
const intervalDuration = endTime - startTime;
|
||||||
|
|
||||||
const response = await fetch(LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH, {
|
const response = await fetch(LOG_ANALYSIS_GET_LOG_ENTRY_CATEGORIES_PATH, {
|
||||||
|
@ -58,6 +60,7 @@ export const callGetTopLogEntryCategoriesAPI = async (
|
||||||
bucketCount: 1,
|
bucketCount: 1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
sort,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { useMemo, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
GetLogEntryCategoriesSuccessResponsePayload,
|
GetLogEntryCategoriesSuccessResponsePayload,
|
||||||
GetLogEntryCategoryDatasetsSuccessResponsePayload,
|
GetLogEntryCategoryDatasetsSuccessResponsePayload,
|
||||||
|
CategorySort,
|
||||||
} from '../../../../common/http_api/log_analysis';
|
} from '../../../../common/http_api/log_analysis';
|
||||||
import { useTrackedPromise, CanceledPromiseError } from '../../../utils/use_tracked_promise';
|
import { useTrackedPromise, CanceledPromiseError } from '../../../utils/use_tracked_promise';
|
||||||
import { callGetTopLogEntryCategoriesAPI } from './service_calls/get_top_log_entry_categories';
|
import { callGetTopLogEntryCategoriesAPI } from './service_calls/get_top_log_entry_categories';
|
||||||
|
@ -18,6 +19,9 @@ import { useKibanaContextForPlugin } from '../../../hooks/use_kibana';
|
||||||
type TopLogEntryCategories = GetLogEntryCategoriesSuccessResponsePayload['data']['categories'];
|
type TopLogEntryCategories = GetLogEntryCategoriesSuccessResponsePayload['data']['categories'];
|
||||||
type LogEntryCategoryDatasets = GetLogEntryCategoryDatasetsSuccessResponsePayload['data']['datasets'];
|
type LogEntryCategoryDatasets = GetLogEntryCategoryDatasetsSuccessResponsePayload['data']['datasets'];
|
||||||
|
|
||||||
|
export type SortOptions = CategorySort;
|
||||||
|
export type ChangeSortOptions = (sortOptions: CategorySort) => void;
|
||||||
|
|
||||||
export const useLogEntryCategoriesResults = ({
|
export const useLogEntryCategoriesResults = ({
|
||||||
categoriesCount,
|
categoriesCount,
|
||||||
filteredDatasets: filteredDatasets,
|
filteredDatasets: filteredDatasets,
|
||||||
|
@ -35,6 +39,10 @@ export const useLogEntryCategoriesResults = ({
|
||||||
sourceId: string;
|
sourceId: string;
|
||||||
startTime: number;
|
startTime: number;
|
||||||
}) => {
|
}) => {
|
||||||
|
const [sortOptions, setSortOptions] = useState<SortOptions>({
|
||||||
|
field: 'maximumAnomalyScore',
|
||||||
|
direction: 'desc',
|
||||||
|
});
|
||||||
const { services } = useKibanaContextForPlugin();
|
const { services } = useKibanaContextForPlugin();
|
||||||
const [topLogEntryCategories, setTopLogEntryCategories] = useState<TopLogEntryCategories>([]);
|
const [topLogEntryCategories, setTopLogEntryCategories] = useState<TopLogEntryCategories>([]);
|
||||||
const [
|
const [
|
||||||
|
@ -53,6 +61,7 @@ export const useLogEntryCategoriesResults = ({
|
||||||
endTime,
|
endTime,
|
||||||
categoryCount: categoriesCount,
|
categoryCount: categoriesCount,
|
||||||
datasets: filteredDatasets,
|
datasets: filteredDatasets,
|
||||||
|
sort: sortOptions,
|
||||||
},
|
},
|
||||||
services.http.fetch
|
services.http.fetch
|
||||||
);
|
);
|
||||||
|
@ -70,7 +79,7 @@ export const useLogEntryCategoriesResults = ({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[categoriesCount, endTime, filteredDatasets, sourceId, startTime]
|
[categoriesCount, endTime, filteredDatasets, sourceId, startTime, sortOptions]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [getLogEntryCategoryDatasetsRequest, getLogEntryCategoryDatasets] = useTrackedPromise(
|
const [getLogEntryCategoryDatasetsRequest, getLogEntryCategoryDatasets] = useTrackedPromise(
|
||||||
|
@ -121,5 +130,7 @@ export const useLogEntryCategoriesResults = ({
|
||||||
isLoadingTopLogEntryCategories,
|
isLoadingTopLogEntryCategories,
|
||||||
logEntryCategoryDatasets,
|
logEntryCategoryDatasets,
|
||||||
topLogEntryCategories,
|
topLogEntryCategories,
|
||||||
|
sortOptions,
|
||||||
|
changeSortOptions: setSortOptions,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
jobCustomSettingsRT,
|
jobCustomSettingsRT,
|
||||||
logEntryCategoriesJobTypes,
|
logEntryCategoriesJobTypes,
|
||||||
} from '../../../common/log_analysis';
|
} from '../../../common/log_analysis';
|
||||||
|
import { CategorySort } from '../../../common/http_api/log_analysis';
|
||||||
import { startTracingSpan } from '../../../common/performance_tracing';
|
import { startTracingSpan } from '../../../common/performance_tracing';
|
||||||
import { decodeOrThrow } from '../../../common/runtime_types';
|
import { decodeOrThrow } from '../../../common/runtime_types';
|
||||||
import type { MlAnomalyDetectors, MlSystem } from '../../types';
|
import type { MlAnomalyDetectors, MlSystem } from '../../types';
|
||||||
|
@ -49,7 +50,8 @@ export async function getTopLogEntryCategories(
|
||||||
endTime: number,
|
endTime: number,
|
||||||
categoryCount: number,
|
categoryCount: number,
|
||||||
datasets: string[],
|
datasets: string[],
|
||||||
histograms: HistogramParameters[]
|
histograms: HistogramParameters[],
|
||||||
|
sort: CategorySort
|
||||||
) {
|
) {
|
||||||
const finalizeTopLogEntryCategoriesSpan = startTracingSpan('get top categories');
|
const finalizeTopLogEntryCategoriesSpan = startTracingSpan('get top categories');
|
||||||
|
|
||||||
|
@ -68,7 +70,8 @@ export async function getTopLogEntryCategories(
|
||||||
startTime,
|
startTime,
|
||||||
endTime,
|
endTime,
|
||||||
categoryCount,
|
categoryCount,
|
||||||
datasets
|
datasets,
|
||||||
|
sort
|
||||||
);
|
);
|
||||||
|
|
||||||
const categoryIds = topLogEntryCategories.map(({ categoryId }) => categoryId);
|
const categoryIds = topLogEntryCategories.map(({ categoryId }) => categoryId);
|
||||||
|
@ -214,7 +217,8 @@ async function fetchTopLogEntryCategories(
|
||||||
startTime: number,
|
startTime: number,
|
||||||
endTime: number,
|
endTime: number,
|
||||||
categoryCount: number,
|
categoryCount: number,
|
||||||
datasets: string[]
|
datasets: string[],
|
||||||
|
sort: CategorySort
|
||||||
) {
|
) {
|
||||||
const finalizeEsSearchSpan = startTracingSpan('Fetch top categories from ES');
|
const finalizeEsSearchSpan = startTracingSpan('Fetch top categories from ES');
|
||||||
|
|
||||||
|
@ -225,7 +229,8 @@ async function fetchTopLogEntryCategories(
|
||||||
startTime,
|
startTime,
|
||||||
endTime,
|
endTime,
|
||||||
categoryCount,
|
categoryCount,
|
||||||
datasets
|
datasets,
|
||||||
|
sort
|
||||||
),
|
),
|
||||||
[logEntryCategoriesCountJobId]
|
[logEntryCategoriesCountJobId]
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,13 +14,33 @@ import {
|
||||||
createDatasetsFilters,
|
createDatasetsFilters,
|
||||||
} from './common';
|
} from './common';
|
||||||
|
|
||||||
|
import { CategorySort } from '../../../../common/http_api/log_analysis';
|
||||||
|
|
||||||
|
type CategoryAggregationOrder =
|
||||||
|
| 'filter_record>maximum_record_score'
|
||||||
|
| 'filter_model_plot>sum_actual';
|
||||||
|
const getAggregationOrderForSortField = (
|
||||||
|
field: CategorySort['field']
|
||||||
|
): CategoryAggregationOrder => {
|
||||||
|
switch (field) {
|
||||||
|
case 'maximumAnomalyScore':
|
||||||
|
return 'filter_record>maximum_record_score';
|
||||||
|
break;
|
||||||
|
case 'logEntryCount':
|
||||||
|
return 'filter_model_plot>sum_actual';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 'filter_model_plot>sum_actual';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const createTopLogEntryCategoriesQuery = (
|
export const createTopLogEntryCategoriesQuery = (
|
||||||
logEntryCategoriesJobId: string,
|
logEntryCategoriesJobId: string,
|
||||||
startTime: number,
|
startTime: number,
|
||||||
endTime: number,
|
endTime: number,
|
||||||
size: number,
|
size: number,
|
||||||
datasets: string[],
|
datasets: string[],
|
||||||
sortDirection: 'asc' | 'desc' = 'desc'
|
sort: CategorySort
|
||||||
) => ({
|
) => ({
|
||||||
...defaultRequestParameters,
|
...defaultRequestParameters,
|
||||||
body: {
|
body: {
|
||||||
|
@ -65,7 +85,7 @@ export const createTopLogEntryCategoriesQuery = (
|
||||||
field: 'by_field_value',
|
field: 'by_field_value',
|
||||||
size,
|
size,
|
||||||
order: {
|
order: {
|
||||||
'filter_model_plot>sum_actual': sortDirection,
|
[getAggregationOrderForSortField(sort.field)]: sort.direction,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
aggs: {
|
aggs: {
|
||||||
|
|
|
@ -33,6 +33,7 @@ export const initGetLogEntryCategoriesRoute = ({ framework }: InfraBackendLibs)
|
||||||
sourceId,
|
sourceId,
|
||||||
timeRange: { startTime, endTime },
|
timeRange: { startTime, endTime },
|
||||||
datasets,
|
datasets,
|
||||||
|
sort,
|
||||||
},
|
},
|
||||||
} = request.body;
|
} = request.body;
|
||||||
|
|
||||||
|
@ -51,7 +52,8 @@ export const initGetLogEntryCategoriesRoute = ({ framework }: InfraBackendLibs)
|
||||||
endTime: histogram.timeRange.endTime,
|
endTime: histogram.timeRange.endTime,
|
||||||
id: histogram.id,
|
id: histogram.id,
|
||||||
startTime: histogram.timeRange.startTime,
|
startTime: histogram.timeRange.startTime,
|
||||||
}))
|
})),
|
||||||
|
sort
|
||||||
);
|
);
|
||||||
|
|
||||||
return response.ok({
|
return response.ok({
|
||||||
|
|
Loading…
Reference in a new issue