Skip to content

Commit

Permalink
[ML] Data frame analytics: Fix job types (#44376) (#44491)
Browse files Browse the repository at this point in the history
Fixes support for different types of analysis in the data frame analytics jobs list.
- A new column Type lists the analysis type.
- Adds a check to enable the View action only for outlier_detection jobs.
- Fixing missing translations for the View button.
  • Loading branch information
walterra authored Aug 30, 2019
1 parent 3a6ebda commit ffbb7e7
Show file tree
Hide file tree
Showing 11 changed files with 117 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { getAnalysisType, isOutlierAnalysis } from './analytics';

describe('Data Frame Analytics: Analytics utils', () => {
test('getAnalysisType()', () => {
const outlierAnalysis = { outlier_detection: {} };
expect(getAnalysisType(outlierAnalysis)).toBe('outlier_detection');

const regressionAnalysis = { regression: {} };
expect(getAnalysisType(regressionAnalysis)).toBe('regression');

// test against a job type that does not exist yet.
const otherAnalysis = { other: {} };
expect(getAnalysisType(otherAnalysis)).toBe('other');

// if the analysis object has a shape that is not just a single property,
// the job type will be returned as 'unknown'.
const unknownAnalysis = { outlier_detection: {}, regression: {} };
expect(getAnalysisType(unknownAnalysis)).toBe('unknown');
});

test('isOutlierAnalysis()', () => {
const outlierAnalysis = { outlier_detection: {} };
expect(isOutlierAnalysis(outlierAnalysis)).toBe(true);

const regressionAnalysis = { regression: {} };
expect(isOutlierAnalysis(regressionAnalysis)).toBe(false);

const unknownAnalysis = { outlier_detection: {}, regression: {} };
expect(isOutlierAnalysis(unknownAnalysis)).toBe(false);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,51 @@ import { Subscription } from 'rxjs';
// @ts-ignore
import { isJobIdValid } from '../../../common/util/job_utils';

// TODO
export const moveToAnalyticsWizard = () => {};

export const isAnalyticsIdValid = isJobIdValid;

export type IndexName = string;
export type IndexPattern = string;
export type DataFrameAnalyticsId = string;

export interface DataFrameAnalyticsOutlierConfig {
interface OutlierAnalysis {
outlier_detection: {};
}

interface RegressionAnalysis {
regression: {
dependent_variable: string;
training_percent?: number;
};
}

interface GenericAnalysis {
[key: string]: Record<string, any>;
}

type AnalysisConfig = OutlierAnalysis | RegressionAnalysis | GenericAnalysis;

enum ANALYSIS_CONFIG_TYPE {
OUTLIER_DETECTION = 'outlier_detection',
REGRESSION = 'regression',
UNKNOWN = 'unknown',
}

export const getAnalysisType = (analysis: AnalysisConfig) => {
const keys = Object.keys(analysis);

if (keys.length === 1) {
return keys[0];
}

return ANALYSIS_CONFIG_TYPE.UNKNOWN;
};

export const isOutlierAnalysis = (arg: any): arg is OutlierAnalysis => {
const keys = Object.keys(arg);
return keys.length === 1 && keys[0] === ANALYSIS_CONFIG_TYPE.OUTLIER_DETECTION;
};

export interface DataFrameAnalyticsConfig {
id: DataFrameAnalyticsId;
// Description attribute is not supported yet
// description?: string;
Expand All @@ -32,9 +67,7 @@ export interface DataFrameAnalyticsOutlierConfig {
source: {
index: IndexName;
};
analysis: {
outlier_detection: {};
};
analysis: AnalysisConfig;
analyzed_fields: {
includes: string[];
excludes: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
*/

export {
getAnalysisType,
isAnalyticsIdValid,
moveToAnalyticsWizard,
isOutlierAnalysis,
refreshAnalyticsList$,
useRefreshAnalyticsList,
DataFrameAnalyticsId,
DataFrameAnalyticsOutlierConfig,
DataFrameAnalyticsConfig,
IndexName,
IndexPattern,
REFRESH_ANALYTICS_LIST_STATE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { ml } from '../../../../../services/ml_api_service';
import {
sortColumns,
toggleSelectedField,
DataFrameAnalyticsOutlierConfig,
DataFrameAnalyticsConfig,
EsFieldName,
EsDoc,
MAX_COLUMNS,
Expand All @@ -62,7 +62,7 @@ const FEATURE_INFLUENCE = 'feature_influence';

interface GetDataFrameAnalyticsResponse {
count: number;
data_frame_analytics: DataFrameAnalyticsOutlierConfig[];
data_frame_analytics: DataFrameAnalyticsConfig[];
}

// Defining our own ENUM here.
Expand Down Expand Up @@ -98,9 +98,7 @@ interface Props {
}

export const Exploration: FC<Props> = React.memo(({ jobId }) => {
const [jobConfig, setJobConfig] = useState<DataFrameAnalyticsOutlierConfig | undefined>(
undefined
);
const [jobConfig, setJobConfig] = useState<DataFrameAnalyticsConfig | undefined>(undefined);

useEffect(() => {
(async function() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { getNestedProperty } from '../../../../../util/object_utils';
import {
getDefaultSelectableFields,
getFlattenedFields,
DataFrameAnalyticsOutlierConfig,
DataFrameAnalyticsConfig,
EsDoc,
EsDocSource,
EsFieldName,
Expand All @@ -36,7 +36,7 @@ export interface UseExploreDataReturnType {
}

export const useExploreData = (
jobConfig: DataFrameAnalyticsOutlierConfig | undefined,
jobConfig: DataFrameAnalyticsConfig | undefined,
selectedFields: EsFieldName[],
setSelectedFields: React.Dispatch<React.SetStateAction<EsFieldName[]>>
): UseExploreDataReturnType => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
createPermissionFailureMessage,
} from '../../../../../privilege/check_privilege';

import { isOutlierAnalysis } from '../../../../common/analytics';

import { getResultsUrl, isDataFrameAnalyticsRunning, DataFrameAnalyticsListRow } from './common';
import { stopAnalytics } from '../../services/analytics_service';

Expand All @@ -28,13 +30,18 @@ export const getActions = () => {
render: (item: DataFrameAnalyticsListRow) => {
return (
<EuiButtonEmpty
href={getResultsUrl(item.id)}
disabled={!isOutlierAnalysis(item.config.analysis)}
onClick={() => (window.location.href = getResultsUrl(item.id))}
size="xs"
color="text"
iconType="visTable"
aria-label={'View'}
aria-label={i18n.translate('xpack.ml.dataframe.analyticsList.viewAriaLabel', {
defaultMessage: 'View',
})}
>
{'View'}
{i18n.translate('xpack.ml.dataframe.analyticsList.viewActionName', {
defaultMessage: 'View',
})}
</EuiButtonEmpty>
);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
RIGHT_ALIGNMENT,
} from '@elastic/eui';

import { DataFrameAnalyticsId } from '../../../../common';
import { getAnalysisType, DataFrameAnalyticsId } from '../../../../common';
import {
getDataFrameAnalyticsProgress,
DataFrameAnalyticsListColumn,
Expand Down Expand Up @@ -106,7 +106,6 @@ export const getColumns = (
name: 'ID',
sortable: true,
truncateText: true,
width: isManagementTable === true ? '20%' : undefined,
},
// Description is not supported yet by API
/*
Expand All @@ -126,7 +125,6 @@ export const getColumns = (
}),
sortable: true,
truncateText: true,
width: isManagementTable === true ? '25%' : undefined,
},
{
field: DataFrameAnalyticsListColumn.configDestIndex,
Expand All @@ -135,7 +133,15 @@ export const getColumns = (
}),
sortable: true,
truncateText: true,
width: isManagementTable === true ? '20%' : undefined,
},
{
name: i18n.translate('xpack.ml.dataframe.analyticsList.type', { defaultMessage: 'Type' }),
sortable: (item: DataFrameAnalyticsListRow) => getAnalysisType(item.config.analysis),
truncateText: true,
render(item: DataFrameAnalyticsListRow) {
return <EuiBadge color="hollow">{getAnalysisType(item.config.analysis)}</EuiBadge>;
},
width: '150px',
},
{
name: i18n.translate('xpack.ml.dataframe.analyticsList.status', { defaultMessage: 'Status' }),
Expand Down Expand Up @@ -218,6 +224,7 @@ export const getColumns = (
defaultMessage: 'Spaces',
}),
render: () => <EuiBadge color={'hollow'}>{'all'}</EuiBadge>,
width: '75px',
});
} else {
columns.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { DataFrameAnalyticsId, DataFrameAnalyticsOutlierConfig } from '../../../../common';
import { DataFrameAnalyticsId, DataFrameAnalyticsConfig } from '../../../../common';

export enum DATA_FRAME_TASK_STATE {
ANALYZING = 'analyzing',
Expand Down Expand Up @@ -85,7 +85,7 @@ export function getDataFrameAnalyticsProgress(stats: DataFrameAnalyticsStats) {
export interface DataFrameAnalyticsListRow {
id: DataFrameAnalyticsId;
checkpointing: object;
config: DataFrameAnalyticsOutlierConfig;
config: DataFrameAnalyticsConfig;
mode: string;
stats: DataFrameAnalyticsStats;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { DeepPartial } from '../../../../../../common/types/common';
import { checkPermission } from '../../../../../privilege/check_privilege';

import { DataFrameAnalyticsId, DataFrameAnalyticsOutlierConfig } from '../../../../common';
import { DataFrameAnalyticsId, DataFrameAnalyticsConfig } from '../../../../common';

const ANALYTICS_DETAULT_MODEL_MEMORY_LIMIT = '50mb';

Expand Down Expand Up @@ -48,7 +48,7 @@ export interface State {
isModalButtonDisabled: boolean;
isModalVisible: boolean;
isValid: boolean;
jobConfig: DeepPartial<DataFrameAnalyticsOutlierConfig>;
jobConfig: DeepPartial<DataFrameAnalyticsConfig>;
jobIds: DataFrameAnalyticsId[];
requestMessages: FormMessage[];
}
Expand Down Expand Up @@ -91,7 +91,7 @@ export const getInitialState = (): State => ({

export const getJobConfigFromFormState = (
formState: State['form']
): DeepPartial<DataFrameAnalyticsOutlierConfig> => {
): DeepPartial<DataFrameAnalyticsConfig> => {
return {
source: {
index: formState.sourceIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { useKibanaContext } from '../../../../../contexts/kibana';
import {
useRefreshAnalyticsList,
DataFrameAnalyticsId,
DataFrameAnalyticsOutlierConfig,
DataFrameAnalyticsConfig,
} from '../../../../common';

import { ActionDispatchers, ACTION } from './actions';
Expand Down Expand Up @@ -198,7 +198,7 @@ export const useCreateAnalyticsForm = () => {
try {
setJobIds(
(await ml.dataFrameAnalytics.getDataFrameAnalytics()).data_frame_analytics.map(
(job: DataFrameAnalyticsOutlierConfig) => job.id
(job: DataFrameAnalyticsConfig) => job.id
)
);
} catch (e) {
Expand Down Expand Up @@ -285,9 +285,9 @@ export const useCreateAnalyticsForm = () => {
addRequestMessage({
error: getErrorMessage(e),
message: i18n.translate(
'xpack.ml.dataframe.analytics.create.errorCreatingDataFrameAnalyticsJob',
'xpack.ml.dataframe.analytics.create.errorStartingDataFrameAnalyticsJob',
{
defaultMessage: 'An error occurred creating the data frame analytics job:',
defaultMessage: 'An error occurred starting the data frame analytics job:',
}
),
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import { ml } from '../../../../../services/ml_api_service';
import {
DataFrameAnalyticsOutlierConfig,
DataFrameAnalyticsConfig,
refreshAnalyticsList$,
REFRESH_ANALYTICS_LIST_STATE,
} from '../../../../common';
Expand All @@ -20,7 +20,7 @@ import {

interface GetDataFrameAnalyticsResponse {
count: number;
data_frame_analytics: DataFrameAnalyticsOutlierConfig[];
data_frame_analytics: DataFrameAnalyticsConfig[];
}

interface GetDataFrameAnalyticsStatsResponseOk {
Expand Down

0 comments on commit ffbb7e7

Please sign in to comment.