Skip to content

Commit

Permalink
[7.x] [ML] Add indicator if there are stopped partitions in categoriz…
Browse files Browse the repository at this point in the history
…ation job wizard (#75709) (#76137)
  • Loading branch information
qn895 authored Aug 28, 2020
1 parent d4efae7 commit 9f630a2
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ export class ResultsLoader {
this._results$.next(this._results);
}

public get results$() {
return this._results$;
}

public subscribeToResults(func: ResultsSubscriber) {
return this._results$.subscribe(func);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
* 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 React, { FC, useContext, useEffect, useState, useMemo, useCallback } from 'react';
import { EuiBasicTable, EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import { i18n } from '@kbn/i18n';
import { from } from 'rxjs';
import { switchMap, takeWhile, tap } from 'rxjs/operators';
import { JobCreatorContext } from '../../../job_creator_context';
import { CategorizationJobCreator } from '../../../../../common/job_creator';
import { ml } from '../../../../../../../services/ml_api_service';
import { extractErrorProperties } from '../../../../../../../../../common/util/errors';

const NUMBER_OF_PREVIEW = 5;
export const CategoryStoppedPartitions: FC = () => {
const { jobCreator: jc, resultsLoader } = useContext(JobCreatorContext);
const jobCreator = jc as CategorizationJobCreator;
const [tableRow, setTableRow] = useState<Array<{ partitionName: string }>>([]);
const [stoppedPartitionsError, setStoppedPartitionsError] = useState<string | undefined>();

const columns = useMemo(
() => [
{
field: 'partitionName',
name: i18n.translate(
'xpack.ml.newJob.wizard.pickFieldsStep.stoppedPartitionsPreviewColumnName',
{
defaultMessage: 'Stopped partition names',
}
),
render: (partition: any) => (
<EuiText size="s">
<code>{partition}</code>
</EuiText>
),
},
],
[]
);

const loadCategoryStoppedPartitions = useCallback(async () => {
try {
const { jobs } = await ml.results.getCategoryStoppedPartitions([jobCreator.jobId]);

if (
!Array.isArray(jobs) && // if jobs is object of jobId: [partitions]
Array.isArray(jobs[jobCreator.jobId]) &&
jobs[jobCreator.jobId].length > 0
) {
return jobs[jobCreator.jobId];
}
} catch (e) {
const error = extractErrorProperties(e);
// might get 404 because job has not been created yet and that's ok
if (error.statusCode !== 404) {
setStoppedPartitionsError(error.message);
}
}
}, [jobCreator.jobId]);

useEffect(() => {
// only need to run this check if jobCreator.perPartitionStopOnWarn is turned on
if (jobCreator.perPartitionCategorization && jobCreator.perPartitionStopOnWarn) {
// subscribe to result updates
const resultsSubscription = resultsLoader.results$
.pipe(
switchMap(() => {
return from(loadCategoryStoppedPartitions());
}),
tap((results) => {
if (Array.isArray(results)) {
setTableRow(
results.slice(0, NUMBER_OF_PREVIEW).map((partitionName) => ({
partitionName,
}))
);
}
}),
takeWhile((results) => {
return !results || (Array.isArray(results) && results.length <= NUMBER_OF_PREVIEW);
})
)
.subscribe();
return () => resultsSubscription.unsubscribe();
}
}, []);

return (
<>
{stoppedPartitionsError && (
<>
<EuiSpacer />
<EuiCallOut
color={'danger'}
size={'s'}
title={
<FormattedMessage
id="xpack.ml.newJob.wizard.pickFieldsStep.stoppedPartitionsErrorCallout"
defaultMessage="An error occurred while fetching list of stopped partitions."
/>
}
/>
</>
)}
{Array.isArray(tableRow) && tableRow.length > 0 && (
<>
<EuiSpacer />
<div>
<FormattedMessage
id="xpack.ml.newJob.wizard.pickFieldsStep.categorizationStoppedPartitionsTitle"
defaultMessage="Stopped partitions"
/>
</div>
<EuiSpacer size={'s'} />
<EuiCallOut
color={'warning'}
size={'s'}
title={
<FormattedMessage
id="xpack.ml.newJob.wizard.pickFieldsStep.stoppedPartitionsExistCallout"
defaultMessage="Per-partition categorization and stop_on_warn settings are enabled. Some partitions in job '{jobId}' are unsuitable for categorization and have been excluded from further categorization or anomaly detection analysis."
values={{
jobId: jobCreator.jobId,
}}
/>
}
/>
<EuiBasicTable columns={columns} items={tableRow} />
</>
)}
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Results, Anomaly } from '../../../../../common/results_loader';
import { LineChartPoint } from '../../../../../common/chart_loader';
import { EventRateChart } from '../../../charts/event_rate_chart';
import { TopCategories } from './top_categories';
import { CategoryStoppedPartitions } from './category_stopped_partitions';

const DTR_IDX = 0;

Expand Down Expand Up @@ -73,6 +74,7 @@ export const CategorizationDetectorsSummary: FC = () => {
fadeChart={jobIsRunning}
/>
<TopCategories />
<CategoryStoppedPartitions />
</>
);
};

0 comments on commit 9f630a2

Please sign in to comment.