Skip to content

Commit

Permalink
[SLOs] Add/edit form show tags suggestions (#181075)
Browse files Browse the repository at this point in the history
## Summary

Show tags as suggestions from existing SLOs

<img width="1194" alt="image"
src="https://github.com/elastic/kibana/assets/3505601/12699ed3-ff26-436d-a63f-a3b9422a1cfc">
  • Loading branch information
shahzad31 authored Apr 18, 2024
1 parent ef5af17 commit d3207ec
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 * as t from 'io-ts';

const getSLOSuggestionsResponseSchema = t.type({
tags: t.array(
t.type({
label: t.string,
value: t.string,
count: t.number,
})
),
});

type GetSLOSuggestionsResponse = t.OutputOf<typeof getSLOSuggestionsResponseSchema>;

export { getSLOSuggestionsResponseSchema };
export type { GetSLOSuggestionsResponse };
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export * from './manage';
export * from './delete_instance';
export * from './fetch_historical_summary';
export * from './put_settings';
export * from './get_suggestions';
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
import { i18n } from '@kbn/i18n';
import React from 'react';
import { Controller, useFormContext } from 'react-hook-form';
import { useFetchSLOSuggestions } from '../hooks/use_fetch_suggestions';
import { OptionalText } from './common/optional_text';
import { CreateSLOForm } from '../types';
import { maxWidth } from './slo_edit_form';
Expand All @@ -29,6 +30,8 @@ export function SloEditFormDescriptionSection() {
const descriptionId = useGeneratedHtmlId({ prefix: 'sloDescription' });
const tagsId = useGeneratedHtmlId({ prefix: 'tags' });

const { suggestions } = useFetchSLOSuggestions();

return (
<EuiPanel
hasBorder={false}
Expand Down Expand Up @@ -121,8 +124,7 @@ export function SloEditFormDescriptionSection() {
defaultMessage: 'Add tags',
})}
isInvalid={fieldState.invalid}
options={[]}
noSuggestions
options={suggestions?.tags ?? []}
selectedOptions={generateTagOptions(field.value)}
onChange={(selected: EuiComboBoxOptionOption[]) => {
if (selected.length) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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 { useQuery } from '@tanstack/react-query';
import { GetSLOSuggestionsResponse } from '@kbn/slo-schema';
import { useKibana } from '../../../utils/kibana_react';

export function useFetchSLOSuggestions() {
const { http } = useKibana().services;

const { isLoading, isError, isSuccess, data } = useQuery({
queryKey: ['fetchSLOSuggestions'],
queryFn: async ({ signal }) => {
try {
return await http.get<GetSLOSuggestionsResponse>(
'/internal/api/observability/slos/suggestions',
{
signal,
}
);
} catch (error) {
// ignore error
}
},
refetchOnWindowFocus: false,
keepPreviousData: true,
});

return {
suggestions: data,
isLoading,
isSuccess,
isError,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
resetSLOParamsSchema,
updateSLOParamsSchema,
} from '@kbn/slo-schema';
import { GetSLOSuggestions } from '../../services/get_slo_suggestions';
import type { IndicatorTypes } from '../../domain/models';
import {
CreateSLO,
Expand Down Expand Up @@ -445,6 +446,21 @@ const findSLOGroupsRoute = createSloServerRoute({
},
});

const getSLOSuggestionsRoute = createSloServerRoute({
endpoint: 'GET /internal/api/observability/slos/suggestions',
options: {
tags: ['access:slo_read'],
access: 'internal',
},
handler: async ({ context }) => {
await assertPlatinumLicense(context);

const soClient = (await context.core).savedObjects.client;
const getSLOSuggestions = new GetSLOSuggestions(soClient);
return await getSLOSuggestions.execute();
},
});

const deleteSloInstancesRoute = createSloServerRoute({
endpoint: 'POST /api/observability/slos/_delete_instances 2023-10-31',
options: {
Expand Down Expand Up @@ -642,4 +658,5 @@ export const sloRouteRepository = {
...getSLOInstancesRoute,
...resetSLORoute,
...findSLOGroupsRoute,
...getSLOSuggestionsRoute,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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 { SavedObjectsClientContract } from '@kbn/core/server';
import { GetSLOSuggestionsResponse } from '@kbn/slo-schema';
import { SO_SLO_TYPE } from '../saved_objects';
type Buckets = Array<{
key: string;
doc_count: number;
}>;

interface AggsResponse {
tagsAggs: {
buckets: Buckets;
};
}
export class GetSLOSuggestions {
constructor(private soClient: SavedObjectsClientContract) {}

public async execute(): Promise<GetSLOSuggestionsResponse> {
const findResponse = await this.soClient.find({
type: SO_SLO_TYPE,
perPage: 0,
aggs: {
tagsAggs: {
terms: {
field: `${SO_SLO_TYPE}.attributes.tags`,
size: 10000,
},
},
},
});
const { tagsAggs } = (findResponse?.aggregations as AggsResponse) ?? {};

return {
tags:
tagsAggs?.buckets?.map(({ key, doc_count: count }) => ({
label: key,
value: key,
count,
})) ?? [],
};
}
}

0 comments on commit d3207ec

Please sign in to comment.