Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/kbn-slo-schema/src/rest_specs/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const getSLOParamsSchema = t.type({
});

const sortDirectionSchema = t.union([t.literal('asc'), t.literal('desc')]);
const sortBySchema = t.union([t.literal('name'), t.literal('indicatorType')]);
const sortBySchema = t.union([t.literal('creationTime'), t.literal('indicatorType')]);

const findSLOParamsSchema = t.partial({
query: t.partial({
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/observability/docs/openapi/slo/bundled.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ paths:
schema:
type: string
enum:
- name
- creationTime
- indicatorType
default: name
example: name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ get:
description: Sort by field
schema:
type: string
enum: [name, indicatorType]
enum: [creationTime, indicatorType]
default: name
example: name
- name: sortDirection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const LONG_REFETCH_INTERVAL = 1000 * 60; // 1 minute
export function useFetchSloList({
name = '',
page = 1,
sortBy = 'name',
sortBy = 'creationTime',
indicatorTypes = [],
shouldRefetch,
}: SLOListParams | undefined = {}): UseFetchSloListResponse {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function SloList({ autoRefresh }: Props) {
const [activePage, setActivePage] = useState(0);

const [query, setQuery] = useState('');
const [sort, setSort] = useState<SortType>('name');
const [sort, setSort] = useState<SortType>('creationTime');
const [indicatorTypeFilter, setIndicatorTypeFilter] = useState<FilterType[]>([]);

const { isLoading, isError, sloList, refetch } = useFetchSloList({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export interface SloListSearchFilterSortBarProps {
onChangeIndicatorTypeFilter: (filter: FilterType[]) => void;
}

export type SortType = 'name' | 'indicatorType';
export type SortType = 'creationTime' | 'indicatorType';
export type FilterType =
| 'sli.apm.transactionDuration'
| 'sli.apm.transactionErrorRate'
Expand All @@ -46,10 +46,10 @@ export type Item<T> = EuiSelectableOption & {

const SORT_OPTIONS: Array<Item<SortType>> = [
{
label: i18n.translate('xpack.observability.slo.list.sortBy.name', {
defaultMessage: 'Name',
label: i18n.translate('xpack.observability.slo.list.sortBy.creationTime', {
defaultMessage: 'Creation time',
}),
type: 'name',
type: 'creationTime',
checked: 'on',
},
{
Expand Down Expand Up @@ -108,7 +108,7 @@ export function SloListSearchFilterSortBar({
};

useEffect(() => {
if (selectedSort?.type === 'name' || selectedSort?.type === 'indicatorType') {
if (selectedSort?.type === 'creationTime' || selectedSort?.type === 'indicatorType') {
onChangeSort(selectedSort.type);
}
}, [onChangeSort, selectedSort]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ name: undefined },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 1, perPage: 25 }
);

Expand Down Expand Up @@ -98,7 +98,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ name: undefined },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 1, perPage: 25 }
);
});
Expand All @@ -112,7 +112,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ name: 'Availability' },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 1, perPage: 25 }
);
});
Expand All @@ -126,7 +126,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ indicatorTypes: ['sli.kql.custom'] },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 1, perPage: 25 }
);
});
Expand All @@ -140,7 +140,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ name: 'My SLO*' },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 2, perPage: 100 }
);
});
Expand All @@ -154,7 +154,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ name: undefined },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 1, perPage: 25 }
);
});
Expand All @@ -168,7 +168,7 @@ describe('FindSLO', () => {

expect(mockRepository.find).toHaveBeenCalledWith(
{ name: undefined },
{ field: SortField.Name, direction: SortDirection.Asc },
{ field: SortField.CreationTime, direction: SortDirection.Asc },
{ page: 1, perPage: 25 }
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ function toCriteria(params: FindSLOParams): Criteria {

function toSort(params: FindSLOParams): Sort {
return {
field: params.sortBy === 'indicatorType' ? SortField.IndicatorType : SortField.Name,
field: params.sortBy === 'indicatorType' ? SortField.IndicatorType : SortField.CreationTime,
direction: params.sortDirection === 'desc' ? SortDirection.Desc : SortDirection.Asc,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,12 @@ describe('KibanaSavedObjectsSLORepository', () => {
describe('find', () => {
const DEFAULT_PAGINATION: Pagination = { page: 1, perPage: 25 };
const DEFAULT_SORTING: Sort = {
field: SortField.Name,
field: SortField.CreationTime,
direction: SortDirection.Asc,
};

describe('Name filter', () => {
it('includes the filter on name with wildcard when provided', async () => {
describe('Name search', () => {
it('includes the search on name with wildcard when provided', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(createFindResponse([SOME_SLO]));

Expand All @@ -146,13 +146,15 @@ describe('KibanaSavedObjectsSLORepository', () => {
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
filter: `(slo.attributes.name: *availability*)`,
sortField: 'name',
filter: undefined,
search: '*availability*',
searchFields: ['name'],
sortField: 'created_at',
sortOrder: 'asc',
});
});

it('includes the filter on name with added wildcard when not provided', async () => {
it('includes the search on name with added wildcard when not provided', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(createFindResponse([SOME_SLO]));

Expand All @@ -172,8 +174,10 @@ describe('KibanaSavedObjectsSLORepository', () => {
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
filter: `(slo.attributes.name: *availa*)`,
sortField: 'name',
filter: undefined,
search: '*availa*',
searchFields: ['name'],
sortField: 'created_at',
sortOrder: 'asc',
});
});
Expand Down Expand Up @@ -201,7 +205,9 @@ describe('KibanaSavedObjectsSLORepository', () => {
page: 1,
perPage: 25,
filter: `(slo.attributes.indicator.type: sli.kql.custom)`,
sortField: 'name',
search: undefined,
searchFields: undefined,
sortField: 'created_at',
sortOrder: 'asc',
});
});
Expand All @@ -227,13 +233,15 @@ describe('KibanaSavedObjectsSLORepository', () => {
page: 1,
perPage: 25,
filter: `(slo.attributes.indicator.type: sli.kql.custom or slo.attributes.indicator.type: sli.apm.transactionDuration)`,
sortField: 'name',
search: undefined,
searchFields: undefined,
sortField: 'created_at',
sortOrder: 'asc',
});
});
});

it('includes filter on name and indicator types', async () => {
it('includes search on name and filter on indicator types', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(createFindResponse([SOME_SLO]));

Expand All @@ -253,13 +261,15 @@ describe('KibanaSavedObjectsSLORepository', () => {
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
filter: `(slo.attributes.name: *latency*) and (slo.attributes.indicator.type: sli.kql.custom or slo.attributes.indicator.type: sli.apm.transactionDuration)`,
sortField: 'name',
filter: `(slo.attributes.indicator.type: sli.kql.custom or slo.attributes.indicator.type: sli.apm.transactionDuration)`,
search: '*latency*',
searchFields: ['name'],
sortField: 'created_at',
sortOrder: 'asc',
});
});

it('does not include the filter when no criteria provided', async () => {
it('does not include the search or filter when no criteria provided', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(createFindResponse([SOME_SLO]));

Expand All @@ -275,12 +285,14 @@ describe('KibanaSavedObjectsSLORepository', () => {
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
sortField: 'name',
search: undefined,
searchFields: undefined,
sortField: 'created_at',
sortOrder: 'asc',
});
});

it('sorts by name ascending', async () => {
it('sorts by creation time ascending', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(createFindResponse([SOME_SLO]));

Expand All @@ -290,26 +302,30 @@ describe('KibanaSavedObjectsSLORepository', () => {
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
sortField: 'name',
search: undefined,
searchFields: undefined,
sortField: 'created_at',
sortOrder: 'asc',
});
});

it('sorts by name descending', async () => {
it('sorts by creation time descending', async () => {
const repository = new KibanaSavedObjectsSLORepository(soClientMock);
soClientMock.find.mockResolvedValueOnce(createFindResponse([SOME_SLO]));

await repository.find(
{},
{ field: SortField.Name, direction: SortDirection.Desc },
{ field: SortField.CreationTime, direction: SortDirection.Desc },
DEFAULT_PAGINATION
);

expect(soClientMock.find).toHaveBeenCalledWith({
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
sortField: 'name',
search: undefined,
searchFields: undefined,
sortField: 'created_at',
sortOrder: 'desc',
});
});
Expand All @@ -328,6 +344,8 @@ describe('KibanaSavedObjectsSLORepository', () => {
type: SO_SLO_TYPE,
page: 1,
perPage: 25,
search: undefined,
searchFields: undefined,
sortField: 'indicator.type',
sortOrder: 'asc',
});
Expand Down
24 changes: 17 additions & 7 deletions x-pack/plugins/observability/server/services/slo/slo_repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export const SortDirection = {
type SortDirection = ObjectValues<typeof SortDirection>;

export const SortField = {
Name: 'Name',
CreationTime: 'CreationTime',
IndicatorType: 'IndicatorType',
};

Expand Down Expand Up @@ -99,12 +99,15 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
}

async find(criteria: Criteria, sort: Sort, pagination: Pagination): Promise<Paginated<SLO>> {
const { search, searchFields } = buildSearch(criteria);
const filterKuery = buildFilterKuery(criteria);
const { sortField, sortOrder } = buildSortQuery(sort);
const response = await this.soClient.find<StoredSLO>({
type: SO_SLO_TYPE,
page: pagination.page,
perPage: pagination.perPage,
search,
searchFields,
filter: filterKuery,
sortField,
sortOrder,
Expand Down Expand Up @@ -138,12 +141,19 @@ export class KibanaSavedObjectsSLORepository implements SLORepository {
}
}

function buildFilterKuery(criteria: Criteria): string | undefined {
const filters: string[] = [];
if (!!criteria.name) {
filters.push(`(slo.attributes.name: ${addWildcardsIfAbsent(criteria.name)})`);
function buildSearch(criteria: Criteria): {
search: string | undefined;
searchFields: string[] | undefined;
} {
if (!criteria.name) {
return { search: undefined, searchFields: undefined };
}

return { search: addWildcardsIfAbsent(criteria.name), searchFields: ['name'] };
}

function buildFilterKuery(criteria: Criteria): string | undefined {
const filters: string[] = [];
if (!!criteria.indicatorTypes) {
const indicatorTypesFilter: string[] = criteria.indicatorTypes.map(
(indicatorType) => `slo.attributes.indicator.type: ${indicatorType}`
Expand All @@ -160,9 +170,9 @@ function buildSortQuery(sort: Sort): { sortField: string; sortOrder: 'asc' | 'de
case SortField.IndicatorType:
sortField = 'indicator.type';
break;
case SortField.Name:
case SortField.CreationTime:
default:
sortField = 'name';
sortField = 'created_at';
break;
}

Expand Down