mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[SLOs] Configuration inspect api and flyout (#173723)
## Summary
It will show all the associated configs at one place in json form,
configuration, ingest pipeline config, roll up transform and summary
transform config !!
Motivation is to understand things while onboarding devs to slo and
during normal development.
a22ad292
-ba59-4145-989e-80803b6a1e3e
This commit is contained in:
parent
7c2b3f1301
commit
9dc9d8ff8f
16 changed files with 437 additions and 4 deletions
|
@ -50,6 +50,7 @@ const createSLOParamsSchema = t.type({
|
|||
settings: optionalSettingsSchema,
|
||||
tags: tagsSchema,
|
||||
groupBy: allOrAnyString,
|
||||
revision: t.number,
|
||||
}),
|
||||
]),
|
||||
});
|
||||
|
|
|
@ -10,3 +10,6 @@ import { IngestPipelinesPlugin } from './plugin';
|
|||
export function plugin() {
|
||||
return new IngestPipelinesPlugin();
|
||||
}
|
||||
|
||||
export { INGEST_PIPELINES_APP_LOCATOR, INGEST_PIPELINES_PAGES } from './locator';
|
||||
export type { IngestPipelinesListParams } from './locator';
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
"unifiedSearch",
|
||||
"stackAlerts",
|
||||
"spaces",
|
||||
"embeddable"
|
||||
"embeddable",
|
||||
"ingestPipelines"
|
||||
],
|
||||
"extraPublicDirs": [
|
||||
"common"
|
||||
|
|
|
@ -104,6 +104,7 @@ export const renderApp = ({
|
|||
>
|
||||
<PluginContext.Provider
|
||||
value={{
|
||||
isDev,
|
||||
config,
|
||||
appMountParameters,
|
||||
observabilityRuleTypeRegistry,
|
||||
|
|
|
@ -12,6 +12,7 @@ import type { ObservabilityRuleTypeRegistry } from '../../rules/create_observabi
|
|||
import type { ConfigSchema } from '../../plugin';
|
||||
|
||||
export interface PluginContextValue {
|
||||
isDev?: boolean;
|
||||
config: ConfigSchema;
|
||||
appMountParameters: AppMountParameters;
|
||||
observabilityRuleTypeRegistry: ObservabilityRuleTypeRegistry;
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { IHttpFetchError, ResponseErrorBody } from '@kbn/core/public';
|
||||
import type { FindSLOResponse, SLOResponse } from '@kbn/slo-schema';
|
||||
import { QueryKey, useMutation } from '@tanstack/react-query';
|
||||
import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { CreateSLOInput } from '@kbn/slo-schema';
|
||||
import { useKibana } from '../../utils/kibana_react';
|
||||
|
||||
type ServerError = IHttpFetchError<ResponseErrorBody>;
|
||||
|
||||
interface SLOInspectResponse {
|
||||
slo: SLOResponse;
|
||||
pipeline: Record<string, any>;
|
||||
rollUpTransform: TransformPutTransformRequest;
|
||||
summaryTransform: TransformPutTransformRequest;
|
||||
temporaryDoc: Record<string, any>;
|
||||
}
|
||||
|
||||
export function useInspectSlo() {
|
||||
const { http } = useKibana().services;
|
||||
|
||||
return useMutation<
|
||||
SLOInspectResponse,
|
||||
ServerError,
|
||||
{ slo: CreateSLOInput },
|
||||
{ previousData?: FindSLOResponse; queryKey?: QueryKey }
|
||||
>(
|
||||
['inspectSlo'],
|
||||
({ slo }) => {
|
||||
const body = JSON.stringify(slo);
|
||||
return http.post<SLOInspectResponse>(`/internal/api/observability/slos/_inspect`, { body });
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { InPortal } from 'react-reverse-portal';
|
||||
import { GetSLOResponse } from '@kbn/slo-schema';
|
||||
import { CreateSLOForm } from '../../types';
|
||||
import { SLOInspectWrapper } from './slo_inspect';
|
||||
import { InspectSLOPortalNode } from '../../slo_edit';
|
||||
|
||||
export interface SloInspectPortalProps {
|
||||
getValues: () => CreateSLOForm;
|
||||
trigger: () => Promise<boolean>;
|
||||
slo?: GetSLOResponse;
|
||||
}
|
||||
export function InspectSLOPortal(props: SloInspectPortalProps) {
|
||||
return (
|
||||
<InPortal node={InspectSLOPortalNode}>
|
||||
<SLOInspectWrapper {...props} />
|
||||
</InPortal>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* 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 { i18n } from '@kbn/i18n';
|
||||
|
||||
import React, { ReactNode, useState } from 'react';
|
||||
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||
import { useFetcher } from '@kbn/observability-shared-plugin/public';
|
||||
import {
|
||||
EuiFlyout,
|
||||
EuiButton,
|
||||
EuiCodeBlock,
|
||||
EuiFlyoutHeader,
|
||||
EuiTitle,
|
||||
EuiFlyoutFooter,
|
||||
EuiSpacer,
|
||||
EuiFlyoutBody,
|
||||
EuiToolTip,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiLoadingSpinner,
|
||||
EuiAccordion,
|
||||
EuiButtonIcon,
|
||||
} from '@elastic/eui';
|
||||
import {
|
||||
INGEST_PIPELINES_APP_LOCATOR,
|
||||
INGEST_PIPELINES_PAGES,
|
||||
IngestPipelinesListParams,
|
||||
} from '@kbn/ingest-pipelines-plugin/public';
|
||||
import { SloInspectPortalProps } from './inspect_slo_portal';
|
||||
import { ObservabilityPublicPluginsStart } from '../../../..';
|
||||
import { useInspectSlo } from '../../../../hooks/slo/use_inspect_slo';
|
||||
import { transformCreateSLOFormToCreateSLOInput } from '../../helpers/process_slo_form_values';
|
||||
import { enableInspectEsQueries } from '../../../../../common';
|
||||
import { usePluginContext } from '../../../../hooks/use_plugin_context';
|
||||
|
||||
export function SLOInspectWrapper(props: SloInspectPortalProps) {
|
||||
const {
|
||||
services: { uiSettings },
|
||||
} = useKibana();
|
||||
|
||||
const { isDev } = usePluginContext();
|
||||
|
||||
const isInspectorEnabled = uiSettings?.get<boolean>(enableInspectEsQueries);
|
||||
|
||||
return isDev || isInspectorEnabled ? <SLOInspect {...props} /> : null;
|
||||
}
|
||||
|
||||
function SLOInspect({ getValues, trigger, slo }: SloInspectPortalProps) {
|
||||
const { share, http } = useKibana<ObservabilityPublicPluginsStart>().services;
|
||||
const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
|
||||
const { mutateAsync: inspectSlo, data, isLoading } = useInspectSlo();
|
||||
|
||||
const { data: sloData } = useFetcher(async () => {
|
||||
if (!isFlyoutVisible) {
|
||||
return;
|
||||
}
|
||||
const isValid = await trigger();
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
const sloForm = transformCreateSLOFormToCreateSLOInput(getValues());
|
||||
inspectSlo({ slo: { ...sloForm, id: slo?.id, revision: slo?.revision } });
|
||||
return sloForm;
|
||||
}, [isFlyoutVisible, trigger, getValues, inspectSlo, slo]);
|
||||
|
||||
const { data: pipeLineUrl } = useFetcher(async () => {
|
||||
const ingestPipeLocator = share.url.locators.get<IngestPipelinesListParams>(
|
||||
INGEST_PIPELINES_APP_LOCATOR
|
||||
);
|
||||
const ingestPipeLineId = data?.pipeline?.id;
|
||||
return ingestPipeLocator?.getUrl({
|
||||
pipelineId: ingestPipeLineId,
|
||||
page: INGEST_PIPELINES_PAGES.LIST,
|
||||
});
|
||||
}, [data?.pipeline?.id, share.url.locators]);
|
||||
|
||||
const closeFlyout = () => {
|
||||
setIsFlyoutVisible(false);
|
||||
setIsInspecting(false);
|
||||
};
|
||||
|
||||
const [isInspecting, setIsInspecting] = useState(false);
|
||||
const onButtonClick = () => {
|
||||
trigger().then((isValid) => {
|
||||
if (isValid) {
|
||||
setIsInspecting(() => !isInspecting);
|
||||
setIsFlyoutVisible(() => !isFlyoutVisible);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
let flyout;
|
||||
|
||||
if (isFlyoutVisible) {
|
||||
flyout = (
|
||||
<EuiFlyout ownFocus onClose={closeFlyout} aria-labelledby="flyoutTitle">
|
||||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle size="m">
|
||||
<h2 id="flyoutTitle">{CONFIG_LABEL}</h2>
|
||||
</EuiTitle>
|
||||
</EuiFlyoutHeader>
|
||||
<EuiFlyoutBody>
|
||||
{isLoading && <LoadingState />}
|
||||
<EuiSpacer size="m" />
|
||||
{data && (
|
||||
<>
|
||||
<CodeBlockAccordion
|
||||
id="slo"
|
||||
label={i18n.translate(
|
||||
'xpack.observability.sLOInspect.codeBlockAccordion.sloConfigurationLabel',
|
||||
{ defaultMessage: 'SLO configuration' }
|
||||
)}
|
||||
json={data.slo}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
<CodeBlockAccordion
|
||||
id="rollUpTransform"
|
||||
label={i18n.translate(
|
||||
'xpack.observability.sLOInspect.codeBlockAccordion.rollupTransformLabel',
|
||||
{ defaultMessage: 'Rollup transform' }
|
||||
)}
|
||||
json={data.rollUpTransform}
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="link"
|
||||
data-test-subj="o11ySLOInspectDetailsButton"
|
||||
href={http?.basePath.prepend('/app/management/data/transform')}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<CodeBlockAccordion
|
||||
id="summaryTransform"
|
||||
label={i18n.translate(
|
||||
'xpack.observability.sLOInspect.codeBlockAccordion.summaryTransformLabel',
|
||||
{ defaultMessage: 'Summary transform' }
|
||||
)}
|
||||
json={data.summaryTransform}
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="link"
|
||||
data-test-subj="o11ySLOInspectDetailsButton"
|
||||
href={http?.basePath.prepend('/app/management/data/transform')}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<CodeBlockAccordion
|
||||
id="pipeline"
|
||||
label={i18n.translate(
|
||||
'xpack.observability.sLOInspect.codeBlockAccordion.ingestPipelineLabel',
|
||||
{ defaultMessage: 'SLO Ingest pipeline' }
|
||||
)}
|
||||
extraAction={
|
||||
<EuiButtonIcon
|
||||
iconType="link"
|
||||
data-test-subj="o11ySLOInspectDetailsButton"
|
||||
href={pipeLineUrl}
|
||||
/>
|
||||
}
|
||||
json={data.pipeline}
|
||||
/>
|
||||
<EuiSpacer size="s" />
|
||||
|
||||
<CodeBlockAccordion
|
||||
id="temporaryDoc"
|
||||
label={i18n.translate(
|
||||
'xpack.observability.sLOInspect.codeBlockAccordion.temporaryDocumentLabel',
|
||||
{ defaultMessage: 'Temporary document' }
|
||||
)}
|
||||
json={data.temporaryDoc}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</EuiFlyoutBody>
|
||||
<EuiFlyoutFooter>
|
||||
<EuiButton
|
||||
data-test-subj="syntheticsMonitorInspectCloseButton"
|
||||
onClick={closeFlyout}
|
||||
fill
|
||||
>
|
||||
{i18n.translate('xpack.observability.sLOInspect.closeButtonLabel', {
|
||||
defaultMessage: 'Close',
|
||||
})}
|
||||
</EuiButton>
|
||||
</EuiFlyoutFooter>
|
||||
</EuiFlyout>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<EuiToolTip
|
||||
content={sloData ? VIEW_FORMATTED_CONFIG_LABEL : VALID_CONFIG_LABEL}
|
||||
repositionOnScroll
|
||||
>
|
||||
<EuiButton
|
||||
data-test-subj="syntheticsMonitorInspectShowFlyoutExampleButton"
|
||||
onClick={onButtonClick}
|
||||
iconType="inspect"
|
||||
iconSide="left"
|
||||
>
|
||||
{SLO_INSPECT_LABEL}
|
||||
</EuiButton>
|
||||
</EuiToolTip>
|
||||
|
||||
{flyout}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function CodeBlockAccordion({
|
||||
id,
|
||||
label,
|
||||
json,
|
||||
extraAction,
|
||||
}: {
|
||||
id: string;
|
||||
label: string;
|
||||
json: any;
|
||||
extraAction?: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<EuiAccordion
|
||||
id={id}
|
||||
extraAction={extraAction}
|
||||
buttonContent={
|
||||
<EuiTitle size="xs">
|
||||
<h3>{label}</h3>
|
||||
</EuiTitle>
|
||||
}
|
||||
>
|
||||
<EuiCodeBlock language="json" fontSize="m" paddingSize="m" isCopyable={true}>
|
||||
{JSON.stringify(json, null, 2)}
|
||||
</EuiCodeBlock>
|
||||
</EuiAccordion>
|
||||
);
|
||||
}
|
||||
|
||||
export function LoadingState() {
|
||||
return (
|
||||
<EuiFlexGroup alignItems="center" justifyContent="center" style={{ height: '100%' }}>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiLoadingSpinner size="xl" />
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
}
|
||||
|
||||
const SLO_INSPECT_LABEL = i18n.translate('xpack.observability.sLOInspect.sLOInspectButtonLabel', {
|
||||
defaultMessage: 'SLO Inspect',
|
||||
});
|
||||
|
||||
const VIEW_FORMATTED_CONFIG_LABEL = i18n.translate(
|
||||
'xpack.observability.slo.viewFormattedResourcesConfigsButtonLabel',
|
||||
{ defaultMessage: 'View formatted resources configs for SLO' }
|
||||
);
|
||||
|
||||
const VALID_CONFIG_LABEL = i18n.translate('xpack.observability.slo.formattedConfigLabel.valid', {
|
||||
defaultMessage: 'Only valid form configurations can be inspected.',
|
||||
});
|
||||
|
||||
const CONFIG_LABEL = i18n.translate('xpack.observability.monitorInspect.configLabel', {
|
||||
defaultMessage: 'SLO Configurations',
|
||||
});
|
|
@ -18,6 +18,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import type { GetSLOResponse } from '@kbn/slo-schema';
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { InspectSLOPortal } from './common/inspect_slo_portal';
|
||||
import { EquivalentApiRequest } from './common/equivalent_api_request';
|
||||
import { BurnRateRuleFlyout } from '../../slos/components/common/burn_rate_rule_flyout';
|
||||
import { paths } from '../../../../common/locators/paths';
|
||||
|
@ -191,7 +192,7 @@ export function SloEditForm({ slo }: Props) {
|
|||
defaultMessage: 'SLO burn rate alert rule',
|
||||
})}
|
||||
</strong>
|
||||
</span>{' '}
|
||||
</span>
|
||||
<EuiIconTip
|
||||
content={
|
||||
'Selecting this will allow you to create a new alert rule for this SLO upon saving.'
|
||||
|
@ -240,6 +241,7 @@ export function SloEditForm({ slo }: Props) {
|
|||
/>
|
||||
</EuiFlexGroup>
|
||||
</EuiFlexGroup>
|
||||
<InspectSLOPortal trigger={trigger} getValues={getValues} slo={slo} />
|
||||
</FormProvider>
|
||||
|
||||
<BurnRateRuleFlyout
|
||||
|
|
|
@ -10,6 +10,7 @@ import { useParams } from 'react-router-dom';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { useBreadcrumbs } from '@kbn/observability-shared-plugin/public';
|
||||
|
||||
import { createHtmlPortalNode, OutPortal } from 'react-reverse-portal';
|
||||
import { paths } from '../../../common/locators/paths';
|
||||
import { useKibana } from '../../utils/kibana_react';
|
||||
import { usePluginContext } from '../../hooks/use_plugin_context';
|
||||
|
@ -21,6 +22,8 @@ import { FeedbackButton } from '../../components/slo/feedback_button/feedback_bu
|
|||
import { SloEditForm } from './components/slo_edit_form';
|
||||
import { HeaderMenu } from '../overview/components/header_menu/header_menu';
|
||||
|
||||
export const InspectSLOPortalNode = createHtmlPortalNode();
|
||||
|
||||
export function SloEditPage() {
|
||||
const {
|
||||
application: { navigateToUrl },
|
||||
|
@ -76,7 +79,7 @@ export function SloEditPage() {
|
|||
: i18n.translate('xpack.observability.sloCreatePageTitle', {
|
||||
defaultMessage: 'Create new SLO',
|
||||
}),
|
||||
rightSideItems: [<FeedbackButton />],
|
||||
rightSideItems: [<FeedbackButton />, <OutPortal node={InspectSLOPortalNode} />],
|
||||
bottomBorder: false,
|
||||
}}
|
||||
data-test-subj="slosEditPage"
|
||||
|
|
|
@ -114,6 +114,42 @@ const createSLORoute = createObservabilityServerRoute({
|
|||
},
|
||||
});
|
||||
|
||||
const inspectSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'POST /internal/api/observability/slos/_inspect 2023-10-31',
|
||||
options: {
|
||||
tags: ['access:slo_write'],
|
||||
access: 'public',
|
||||
},
|
||||
params: createSLOParamsSchema,
|
||||
handler: async ({ context, params, logger, dependencies, request }) => {
|
||||
await assertPlatinumLicense(context);
|
||||
|
||||
const spaceId =
|
||||
(await dependencies.spaces?.spacesService?.getActiveSpace(request))?.id ?? 'default';
|
||||
|
||||
const esClient = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const soClient = (await context.core).savedObjects.client;
|
||||
const repository = new KibanaSavedObjectsSLORepository(soClient);
|
||||
const transformManager = new DefaultTransformManager(transformGenerators, esClient, logger);
|
||||
const summaryTransformManager = new DefaultSummaryTransformManager(
|
||||
new DefaultSummaryTransformGenerator(),
|
||||
esClient,
|
||||
logger
|
||||
);
|
||||
|
||||
const createSLO = new CreateSLO(
|
||||
esClient,
|
||||
repository,
|
||||
transformManager,
|
||||
summaryTransformManager,
|
||||
logger,
|
||||
spaceId
|
||||
);
|
||||
|
||||
return createSLO.inspect(params.body);
|
||||
},
|
||||
});
|
||||
|
||||
const updateSLORoute = createObservabilityServerRoute({
|
||||
endpoint: 'PUT /api/observability/slos/{id} 2023-10-31',
|
||||
options: {
|
||||
|
@ -481,6 +517,7 @@ const getPreviewData = createObservabilityServerRoute({
|
|||
|
||||
export const sloRouteRepository = {
|
||||
...createSLORoute,
|
||||
...inspectSLORoute,
|
||||
...deleteSLORoute,
|
||||
...deleteSloInstancesRoute,
|
||||
...disableSLORoute,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
import { ALL_VALUE, CreateSLOParams, CreateSLOResponse } from '@kbn/slo-schema';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import {
|
||||
getSLOSummaryPipelineId,
|
||||
getSLOSummaryTransformId,
|
||||
|
@ -83,6 +84,32 @@ export class CreateSLO {
|
|||
return this.toResponse(slo);
|
||||
}
|
||||
|
||||
public inspect(params: CreateSLOParams): {
|
||||
slo: CreateSLOParams;
|
||||
pipeline: Record<string, any>;
|
||||
rollUpTransform: TransformPutTransformRequest;
|
||||
summaryTransform: TransformPutTransformRequest;
|
||||
temporaryDoc: Record<string, any>;
|
||||
} {
|
||||
const slo = this.toSLO(params);
|
||||
validateSLO(slo);
|
||||
|
||||
const rollUpTransform = this.transformManager.inspect(slo);
|
||||
const pipeline = getSLOSummaryPipelineTemplate(slo, this.spaceId);
|
||||
|
||||
const summaryTransform = this.summaryTransformManager.inspect(slo);
|
||||
|
||||
const temporaryDoc = createTempSummaryDocument(slo, this.spaceId);
|
||||
|
||||
return {
|
||||
pipeline,
|
||||
temporaryDoc,
|
||||
summaryTransform,
|
||||
rollUpTransform,
|
||||
slo,
|
||||
};
|
||||
}
|
||||
|
||||
private toSLO(params: CreateSLOParams): SLO {
|
||||
const now = new Date();
|
||||
return {
|
||||
|
@ -92,7 +119,7 @@ export class CreateSLO {
|
|||
syncDelay: params.settings?.syncDelay ?? new Duration(1, DurationUnit.Minute),
|
||||
frequency: params.settings?.frequency ?? new Duration(1, DurationUnit.Minute),
|
||||
},
|
||||
revision: 1,
|
||||
revision: params.revision ?? 1,
|
||||
enabled: true,
|
||||
tags: params.tags ?? [],
|
||||
createdAt: now,
|
||||
|
|
|
@ -25,6 +25,7 @@ const createTransformManagerMock = (): jest.Mocked<TransformManager> => {
|
|||
uninstall: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
inspect: jest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -35,6 +36,7 @@ const createSummaryTransformManagerMock = (): jest.Mocked<TransformManager> => {
|
|||
uninstall: jest.fn(),
|
||||
start: jest.fn(),
|
||||
stop: jest.fn(),
|
||||
inspect: jest.fn(),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
|
||||
import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/types';
|
||||
import { SLO } from '../../domain/models';
|
||||
import { SecurityException } from '../../errors';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
|
@ -40,6 +41,10 @@ export class DefaultSummaryTransformManager implements TransformManager {
|
|||
return transformParams.transform_id;
|
||||
}
|
||||
|
||||
inspect(slo: SLO): TransformPutTransformRequest {
|
||||
return this.generator.generate(slo);
|
||||
}
|
||||
|
||||
async preview(transformId: string): Promise<void> {
|
||||
try {
|
||||
await retryTransientEsErrors(
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { ElasticsearchClient, Logger } from '@kbn/core/server';
|
||||
|
||||
import { TransformPutTransformRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
import { SLO, IndicatorTypes } from '../../domain/models';
|
||||
import { SecurityException } from '../../errors';
|
||||
import { retryTransientEsErrors } from '../../utils/retry';
|
||||
|
@ -16,6 +17,7 @@ type TransformId = string;
|
|||
|
||||
export interface TransformManager {
|
||||
install(slo: SLO): Promise<TransformId>;
|
||||
inspect(slo: SLO): TransformPutTransformRequest;
|
||||
preview(transformId: TransformId): Promise<void>;
|
||||
start(transformId: TransformId): Promise<void>;
|
||||
stop(transformId: TransformId): Promise<void>;
|
||||
|
@ -53,6 +55,16 @@ export class DefaultTransformManager implements TransformManager {
|
|||
return transformParams.transform_id;
|
||||
}
|
||||
|
||||
inspect(slo: SLO): TransformPutTransformRequest {
|
||||
const generator = this.generators[slo.indicator.type];
|
||||
if (!generator) {
|
||||
this.logger.error(`No transform generator found for indicator type [${slo.indicator.type}]`);
|
||||
throw new Error(`Unsupported indicator type [${slo.indicator.type}]`);
|
||||
}
|
||||
|
||||
return generator.getTransformParams(slo);
|
||||
}
|
||||
|
||||
async preview(transformId: string): Promise<void> {
|
||||
try {
|
||||
await retryTransientEsErrors(
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
"@kbn/presentation-util-plugin",
|
||||
"@kbn/task-manager-plugin",
|
||||
"@kbn/core-elasticsearch-client-server-mocks",
|
||||
"@kbn/ingest-pipelines-plugin",
|
||||
"@kbn/core-saved-objects-api-server-mocks"
|
||||
],
|
||||
"exclude": [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue