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

feat(slo): introduce new search capabilities #162665

Merged
merged 9 commits into from
Aug 1, 2023
14 changes: 2 additions & 12 deletions x-pack/packages/kbn-slo-schema/src/models/duration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ describe('Duration', () => {
expect(new Duration(1, DurationUnit.Day).format()).toBe('1d');
expect(new Duration(1, DurationUnit.Week).format()).toBe('1w');
expect(new Duration(1, DurationUnit.Month).format()).toBe('1M');
expect(new Duration(1, DurationUnit.Quarter).format()).toBe('1Q');
expect(new Duration(1, DurationUnit.Year).format()).toBe('1Y');
});
});

Expand All @@ -39,31 +37,25 @@ describe('Duration', () => {
expect(short.isShorterThan(new Duration(1, DurationUnit.Day))).toBe(true);
expect(short.isShorterThan(new Duration(1, DurationUnit.Week))).toBe(true);
expect(short.isShorterThan(new Duration(1, DurationUnit.Month))).toBe(true);
expect(short.isShorterThan(new Duration(1, DurationUnit.Quarter))).toBe(true);
expect(short.isShorterThan(new Duration(1, DurationUnit.Year))).toBe(true);
});

it('returns false when the current duration is longer (or equal) than the other duration', () => {
const long = new Duration(1, DurationUnit.Year);
const long = new Duration(1, DurationUnit.Month);
expect(long.isShorterThan(new Duration(1, DurationUnit.Minute))).toBe(false);
expect(long.isShorterThan(new Duration(1, DurationUnit.Hour))).toBe(false);
expect(long.isShorterThan(new Duration(1, DurationUnit.Day))).toBe(false);
expect(long.isShorterThan(new Duration(1, DurationUnit.Week))).toBe(false);
expect(long.isShorterThan(new Duration(1, DurationUnit.Month))).toBe(false);
expect(long.isShorterThan(new Duration(1, DurationUnit.Quarter))).toBe(false);
expect(long.isShorterThan(new Duration(1, DurationUnit.Year))).toBe(false);
});
});

describe('isLongerOrEqualThan', () => {
it('returns true when the current duration is longer or equal than the other duration', () => {
const long = new Duration(2, DurationUnit.Year);
const long = new Duration(2, DurationUnit.Month);
expect(long.isLongerOrEqualThan(new Duration(1, DurationUnit.Hour))).toBe(true);
expect(long.isLongerOrEqualThan(new Duration(1, DurationUnit.Day))).toBe(true);
expect(long.isLongerOrEqualThan(new Duration(1, DurationUnit.Week))).toBe(true);
expect(long.isLongerOrEqualThan(new Duration(1, DurationUnit.Month))).toBe(true);
expect(long.isLongerOrEqualThan(new Duration(1, DurationUnit.Quarter))).toBe(true);
expect(long.isLongerOrEqualThan(new Duration(1, DurationUnit.Year))).toBe(true);
});

it('returns false when the current duration is shorter than the other duration', () => {
Expand All @@ -73,8 +65,6 @@ describe('Duration', () => {
expect(short.isLongerOrEqualThan(new Duration(1, DurationUnit.Day))).toBe(false);
expect(short.isLongerOrEqualThan(new Duration(1, DurationUnit.Week))).toBe(false);
expect(short.isLongerOrEqualThan(new Duration(1, DurationUnit.Month))).toBe(false);
expect(short.isLongerOrEqualThan(new Duration(1, DurationUnit.Quarter))).toBe(false);
expect(short.isLongerOrEqualThan(new Duration(1, DurationUnit.Year))).toBe(false);
});
});

Expand Down
14 changes: 4 additions & 10 deletions x-pack/packages/kbn-slo-schema/src/models/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ enum DurationUnit {
'Day' = 'd',
'Week' = 'w',
'Month' = 'M',
'Quarter' = 'Q',
'Year' = 'Y',
}

class Duration {
Expand Down Expand Up @@ -55,6 +53,10 @@ class Duration {
format(): string {
return `${this.value}${this.unit}`;
}

asSeconds(): number {
return moment.duration(this.value, toMomentUnitOfTime(this.unit)).asSeconds();
}
}

const toDurationUnit = (unit: string): DurationUnit => {
Expand All @@ -69,10 +71,6 @@ const toDurationUnit = (unit: string): DurationUnit => {
return DurationUnit.Week;
case 'M':
return DurationUnit.Month;
case 'Q':
return DurationUnit.Quarter;
case 'y':
return DurationUnit.Year;
default:
throw new Error('invalid duration unit');
}
Expand All @@ -90,10 +88,6 @@ const toMomentUnitOfTime = (unit: DurationUnit): moment.unitOfTime.Diff => {
return 'weeks';
case DurationUnit.Month:
return 'months';
case DurationUnit.Quarter:
return 'quarters';
case DurationUnit.Year:
return 'years';
default:
assertNever(unit);
}
Expand Down
19 changes: 11 additions & 8 deletions x-pack/packages/kbn-slo-schema/src/rest_specs/slo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@

import * as t from 'io-ts';
import {
apmTransactionDurationIndicatorSchema,
apmTransactionErrorRateIndicatorSchema,
budgetingMethodSchema,
dateType,
durationType,
histogramIndicatorSchema,
historicalSummarySchema,
indicatorSchema,
indicatorTypesArraySchema,
indicatorTypesSchema,
kqlCustomIndicatorSchema,
metricCustomIndicatorSchema,
histogramIndicatorSchema,
objectiveSchema,
optionalSettingsSchema,
previewDataSchema,
Expand All @@ -24,9 +26,6 @@ import {
summarySchema,
tagsSchema,
timeWindowSchema,
apmTransactionErrorRateIndicatorSchema,
apmTransactionDurationIndicatorSchema,
durationType,
timeWindowTypeSchema,
} from '../schema';

Expand Down Expand Up @@ -69,12 +68,16 @@ const getSLOParamsSchema = t.type({
});

const sortDirectionSchema = t.union([t.literal('asc'), t.literal('desc')]);
const sortBySchema = t.union([t.literal('creationTime'), t.literal('indicatorType')]);
const sortBySchema = t.union([
t.literal('error_budget_consumed'),
t.literal('error_budget_remaining'),
t.literal('sli_value'),
t.literal('status'),
]);

const findSLOParamsSchema = t.partial({
query: t.partial({
name: t.string,
indicatorTypes: indicatorTypesArraySchema,
kqlQuery: t.string,
page: t.string,
perPage: t.string,
sortBy: sortBySchema,
Expand Down
4 changes: 0 additions & 4 deletions x-pack/packages/kbn-slo-schema/src/schema/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ const summarySchema = t.type({
errorBudget: errorBudgetSchema,
});

type SummarySchema = t.TypeOf<typeof summarySchema>;

const historicalSummarySchema = t.intersection([
t.type({
date: dateType,
Expand All @@ -59,8 +57,6 @@ const previewDataSchema = t.type({

const dateRangeSchema = t.type({ from: dateType, to: dateType });

export type { SummarySchema };

export {
ALL_VALUE,
allOrAnyString,
Expand Down
35 changes: 12 additions & 23 deletions x-pack/plugins/observability/docs/openapi/slo/bundled.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,27 +136,13 @@
"$ref": "#/components/parameters/space_id"
},
{
"name": "name",
"name": "kqlQuery",
"in": "query",
"description": "Filter by name",
"description": "A valid kql query to filter the SLO with",
"schema": {
"type": "string"
},
"example": "awesome-service"
},
{
"name": "indicatorTypes",
"in": "query",
"description": "Filter by indicator type",
"schema": {
"type": "array",
"items": {
"type": "string"
}
},
"example": [
"sli.kql.custom"
]
"example": "slo.name:latency* and slo.tags : \"prod\""
},
{
"name": "page",
Expand All @@ -176,7 +162,7 @@
"type": "integer",
"default": 25
},
"example": 20
"example": 25
},
{
"name": "sortBy",
Expand All @@ -185,12 +171,14 @@
"schema": {
"type": "string",
"enum": [
"creationTime",
"indicatorType"
"sli_value",
"status",
"error_budget_consumed",
"error_budget_remaining"
],
"default": "creationTime"
"default": "status"
},
"example": "creationTime"
"example": "status"
},
{
"name": "sortDirection",
Expand Down Expand Up @@ -1333,7 +1321,8 @@
"sli.apm.transactionErrorRate": "#/components/schemas/indicator_properties_apm_availability",
"sli.kql.custom": "#/components/schemas/indicator_properties_custom_kql",
"sli.apm.transactionDuration": "#/components/schemas/indicator_properties_apm_latency",
"sli.apm.sli.metric.custom": "#/components/schemas/indicator_properties_custom_metric"
"sli.metric.custom": "#/components/schemas/indicator_properties_custom_metric",
"sli.histogram.custom": "#/components/schemas/indicator_properties_histogram"
}
},
"oneOf": [
Expand Down
30 changes: 12 additions & 18 deletions x-pack/plugins/observability/docs/openapi/slo/bundled.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,21 +80,12 @@ paths:
parameters:
- $ref: '#/components/parameters/kbn_xsrf'
- $ref: '#/components/parameters/space_id'
- name: name
- name: kqlQuery
in: query
description: Filter by name
description: A valid kql query to filter the SLO with
schema:
type: string
example: awesome-service
- name: indicatorTypes
in: query
description: Filter by indicator type
schema:
type: array
items:
type: string
example:
- sli.kql.custom
example: 'slo.name:latency* and slo.tags : "prod"'
- name: page
in: query
description: The page number to return
Expand All @@ -108,17 +99,19 @@ paths:
schema:
type: integer
default: 25
example: 20
example: 25
- name: sortBy
in: query
description: Sort by field
schema:
type: string
enum:
- creationTime
- indicatorType
default: creationTime
example: creationTime
- sli_value
- status
- error_budget_consumed
- error_budget_remaining
default: status
example: status
- name: sortDirection
in: query
description: Sort order
Expand Down Expand Up @@ -920,7 +913,8 @@ components:
sli.apm.transactionErrorRate: '#/components/schemas/indicator_properties_apm_availability'
sli.kql.custom: '#/components/schemas/indicator_properties_custom_kql'
sli.apm.transactionDuration: '#/components/schemas/indicator_properties_apm_latency'
sli.apm.sli.metric.custom: '#/components/schemas/indicator_properties_custom_metric'
sli.metric.custom: '#/components/schemas/indicator_properties_custom_metric'
sli.histogram.custom: '#/components/schemas/indicator_properties_histogram'
oneOf:
- $ref: '#/components/schemas/indicator_properties_custom_kql'
- $ref: '#/components/schemas/indicator_properties_apm_availability'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,12 @@ get:
parameters:
- $ref: ../components/headers/kbn_xsrf.yaml
- $ref: ../components/parameters/space_id.yaml
- name: name
- name: kqlQuery
in: query
description: Filter by name
description: A valid kql query to filter the SLO with
schema:
type: string
example: awesome-service
- name: indicatorTypes
in: query
description: Filter by indicator type
schema:
type: array
items:
type: string
example: ['sli.kql.custom']
example: 'slo.name:latency* and slo.tags : "prod"'
- name: page
in: query
description: The page number to return
Expand All @@ -87,15 +79,15 @@ get:
schema:
type: integer
default: 25
example: 20
example: 25
- name: sortBy
in: query
description: Sort by field
schema:
type: string
enum: [creationTime, indicatorType]
default: creationTime
example: creationTime
enum: [sli_value, status, error_budget_consumed, error_budget_remaining]
default: status
example: status
- name: sortDirection
in: query
description: Sort order
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('SLO Selector', () => {
render(<SloSelector onSelected={onSelectedSpy} />);

expect(screen.getByTestId('sloSelector')).toBeTruthy();
expect(useFetchSloListMock).toHaveBeenCalledWith({ name: '' });
expect(useFetchSloListMock).toHaveBeenCalledWith({ kqlQuery: 'slo.name:*' });
});

it('searches SLOs when typing', async () => {
Expand All @@ -42,6 +42,6 @@ describe('SLO Selector', () => {
await wait(310); // debounce delay
});

expect(useFetchSloListMock).toHaveBeenCalledWith({ name: 'latency' });
expect(useFetchSloListMock).toHaveBeenCalledWith({ kqlQuery: 'slo.name:latency*' });
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ function SloSelector({ initialSlo, onSelected, errors }: Props) {
const [options, setOptions] = useState<Array<EuiComboBoxOptionOption<string>>>([]);
const [selectedOptions, setSelectedOptions] = useState<Array<EuiComboBoxOptionOption<string>>>();
const [searchValue, setSearchValue] = useState<string>('');
const { isLoading, sloList } = useFetchSloList({ name: searchValue });
const { isLoading, sloList } = useFetchSloList({ kqlQuery: `slo.name:${searchValue}*` });
const hasError = errors !== undefined && errors.length > 0;

useEffect(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import React from 'react';
import { EuiBadge, EuiFlexItem } from '@elastic/eui';
import { EuiBadge, EuiFlexItem, EuiToolTip } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { SLOWithSummaryResponse } from '@kbn/slo-schema';

Expand All @@ -19,11 +19,18 @@ export function SloStatusBadge({ slo }: SloStatusProps) {
<>
<EuiFlexItem grow={false}>
{slo.summary.status === 'NO_DATA' && (
<EuiBadge color="default">
{i18n.translate('xpack.observability.slo.sloStatusBadge.noData', {
defaultMessage: 'No data',
<EuiToolTip
position="top"
content={i18n.translate('xpack.observability.slo.sloStatusBadge.noDataTooltip', {
defaultMessage: 'It may take some time before the data is aggregated and available.',
})}
</EuiBadge>
>
<EuiBadge color="default">
{i18n.translate('xpack.observability.slo.sloStatusBadge.noData', {
defaultMessage: 'No data',
})}
</EuiBadge>
</EuiToolTip>
)}

{slo.summary.status === 'HEALTHY' && (
Expand Down
Loading