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

Feature anywhere create detector flyout page #487

Merged
merged 12 commits into from
May 24, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,12 @@ import './styles.scss';
import {
createAugmentVisSavedObject,
ISavedAugmentVis,
ISavedPluginResource,
VisLayerExpressionFn,
VisLayerTypes,
} from '../../../../../../src/plugins/vis_augmenter/public';
import { useDispatch } from 'react-redux';
import { snakeCase, find, isEmpty, get } from 'lodash';
import { isEmpty, get } from 'lodash';
import {
Field,
FieldArray,
Expand All @@ -50,7 +52,6 @@ import { EmbeddableRenderer } from '../../../../../../src/plugins/embeddable/pub
import './styles.scss';
import EnhancedAccordion from '../EnhancedAccordion';
import MinimalAccordion from '../MinimalAccordion';
import { FEATURE_TYPE } from '../../../../public/models/interfaces';
import { DataFilterList } from '../../../../public/pages/DefineDetector/components/DataFilterList/DataFilterList';
import {
getError,
Expand All @@ -68,7 +69,6 @@ import {
focusOnFirstWrongFeature,
initialFeatureValue,
} from '../../../../public/pages/ConfigureModel/utils/helpers';
import { FeaturesFormikValues } from '../../../../public/pages/ConfigureModel/models/interfaces';
import {
getIndices,
getMappings,
Expand All @@ -83,6 +83,12 @@ import {
} from '../../../../public/utils/constants';
import { getNotifications } from '../../../../public/services';
import { prettifyErrorMessage } from '../../../../server/utils/helpers';
import {
ORIGIN_PLUGIN_VIS_LAYER,
OVERLAY_ANOMALIES,
VIS_LAYER_PLUGIN_TYPE,
} from '../../../../public/expressions/constants';
import { formikToDetectorName, visFeatureListToFormik } from './helpers';

function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
const dispatch = useDispatch();
Expand Down Expand Up @@ -131,18 +137,7 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
(aggList.length < MAX_FEATURE_NUM ? aggList.length : MAX_FEATURE_NUM)
);

const getFeatureNameFromVisParams = (id) => {
let name = find(embeddable.vis.params.seriesParams, function (param) {
if (param.data.id === id) {
return true;
}
});

return name.data.label.replace(/[^a-zA-Z0-9-_]/g, '_');
};

const notifications = getNotifications();

const handleValidationAndSubmit = (formikProps) => {
if (!isEmpty(formikProps.errors)) {
focusOnFirstWrongFeature(formikProps.errors, formikProps.setFieldTouched);
Expand Down Expand Up @@ -177,20 +172,24 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
)
);
});
enum VisLayerTypes {
PointInTimeEvents = 'PointInTimeEvents',
}

const fn = {
type: VisLayerTypes.PointInTimeEvents,
name: 'overlay_anomalies',
name: OVERLAY_ANOMALIES,
args: {
detectorId: response.response.id,
},
} as VisLayerExpressionFn;

const pluginResource = {
type: VIS_LAYER_PLUGIN_TYPE,
id: response.response.id,
} as ISavedPluginResource;

const savedObjectToCreate = {
title: embeddable.vis.title,
pluginResourceId: response.response.id,
originPlugin: ORIGIN_PLUGIN_VIS_LAYER,
pluginResource: pluginResource,
visId: embeddable.vis.id,
savedObjectType: 'visualization',
visLayerExpressionFn: fn,
Expand Down Expand Up @@ -241,54 +240,15 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
description: '',
resultIndex: undefined,
filters: [],
featureList: visFeatureListToFormik(featureList),
featureList: visFeatureListToFormik(
featureList,
embeddable.vis.params.seriesParams
),
categoryFieldEnabled: false,
realTime: true,
historical: false,
};

function formikToDetectorName(title) {
const detectorName =
title +
'_anomaly_detector_' +
Math.floor(100000 + Math.random() * 900000);
detectorName.replace(/[^a-zA-Z0-9-_]/g, '_');
return detectorName;
}

function visAggregationToFormik(value) {
return [
{
label: value.params.field.name,
type: 'number',
},
];
}

function visAggregationQueryToFormik(value) {
return {
[snakeCase(getFeatureNameFromVisParams(value.id))]: {
sum: { field: value.params.field.name },
},
};
}

function visFeatureListToFormik(featureList): FeaturesFormikValues[] {
return featureList.map((feature) => {
return {
featureId: feature.id,
featureName: getFeatureNameFromVisParams(feature.id),
featureEnabled: true,
featureType: FEATURE_TYPE.SIMPLE,
importance: 1,
newFeature: false,
aggregationBy: 'sum',
aggregationOf: visAggregationToFormik(feature),
aggregationQuery: JSON.stringify(visAggregationQueryToFormik(feature)),
};
});
}

return (
<div className="add-anomaly-detector">
<Formik
Expand Down Expand Up @@ -505,7 +465,6 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
id="dataFilter"
title="Data Filter"
subTitle="Choose a data source subset to focus the data stream and reduce data noise."
initialIsOpen={false}
>
<EuiSpacer size="s" />
<EuiText size="xs">
Expand All @@ -522,7 +481,6 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
id="shingleSize"
title="Shingle size"
subTitle="Set number of intervals in the model's detection window."
initialIsOpen={false}
isUsingDivider={true}
>
<EuiSpacer size="m" />
Expand Down Expand Up @@ -570,7 +528,6 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
id="customResultIndex"
title="Custom result index"
subTitle="Store detector results to our own index."
initialIsOpen={false}
isUsingDivider={true}
>
<Field name="resultIndex">
Expand Down Expand Up @@ -627,7 +584,6 @@ function AddAnomalyDetector({ embeddable, closeFlyout, mode, setMode }) {
id="categoricalFields"
title="Categorical fields"
subTitle="Split a single time series into multiple time series based on categorical fields."
initialIsOpen={false}
isUsingDivider={true}
>
<EuiText size="s">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { FEATURE_TYPE } from '../../../../public/models/interfaces';
import { FeaturesFormikValues } from '../../../../public/pages/ConfigureModel/models/interfaces';
import { find, snakeCase } from 'lodash';

export function visFeatureListToFormik(
featureList,
seriesParams
): FeaturesFormikValues[] {
return featureList.map((feature) => {
return {
featureId: feature.id,
featureName: getFeatureNameFromVisParams(feature.id, seriesParams),
featureEnabled: true,
featureType: FEATURE_TYPE.SIMPLE,
importance: 1,
newFeature: false,
aggregationBy: 'sum',
aggregationOf: visAggregationToFormik(feature),
aggregationQuery: JSON.stringify(
visAggregationQueryToFormik(feature, seriesParams)
),
};
});
}

export function formikToDetectorName(title) {
const detectorName =
title + '_anomaly_detector_' + Math.floor(100000 + Math.random() * 900000);
detectorName.replace(/[^a-zA-Z0-9-_]/g, '_');
return detectorName;
}

const getFeatureNameFromVisParams = (id, seriesParams) => {
let name = find(seriesParams, function (param) {
if (param.data.id === id) {
return true;
}
});

return name.data.label.replace(/[^a-zA-Z0-9-_]/g, '_');
};

function visAggregationToFormik(value) {
return [
{
label: value.params.field.name,
type: 'number',
},
];
}

function visAggregationQueryToFormik(value, seriesParams) {
return {
[snakeCase(getFeatureNameFromVisParams(value.id, seriesParams))]: {
sum: { field: value.params.field.name },
},
};
}
2 changes: 2 additions & 0 deletions public/expressions/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ export const ORIGIN_PLUGIN_VIS_LAYER = 'anomalyDetectionDashboards';
export const VIS_LAYER_PLUGIN_TYPE = 'Anomaly Detectors';

export const TYPE_OF_EXPR_VIS_LAYERS = 'vis_layers';

export const OVERLAY_ANOMALIES = 'overlay_anomalies"';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can you consume this constant in overlay_anomalies.ts file as well. There is a name value there. We can set it to this constant instead of redefining there.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated overlay_anomalies.ts file with this constant

5 changes: 1 addition & 4 deletions public/utils/contextMenu/getActions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@ import { Provider } from 'react-redux';
import configureStore from '../../redux/configureStore';
import DocumentationTitle from '../../components/FeatureAnywhereContextMenu/DocumentationTitle/containers/DocumentationTitle';
import { AD_DOCS_LINK, APM_TRACE } from '../constants';
import {
getClient,
getOverlays,
} from '../../../public/services';
import { getClient, getOverlays } from '../../../public/services';

// This is used to create all actions in the same context menu
const grouping: Action['grouping'] = [
Expand Down