Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions x-pack/plugins/ml/common/constants/anomalies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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.
*/

export enum ANOMALY_SEVERITY {
CRITICAL = 'critical',
MAJOR = 'major',
MINOR = 'minor',
WARNING = 'warning',
LOW = 'low',
UNKNOWN = 'unknown',
}

export enum ANOMALY_THRESHOLD {
CRITICAL = 75,
MAJOR = 50,
MINOR = 25,
WARNING = 3,
LOW = 0,
}
21 changes: 20 additions & 1 deletion x-pack/plugins/ml/common/types/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ML_JOB_AGGREGATION } from '../../common/constants/aggregation_types';
export type FieldId = string;
export type AggId = ML_JOB_AGGREGATION;
export type SplitField = Field | null;
export type DslName = string;

export interface Field {
id: FieldId;
Expand All @@ -24,7 +25,7 @@ export interface Aggregation {
id: AggId;
title: string;
kibanaName: string;
dslName: string;
dslName: DslName;
type: string;
mlModelPlotAgg: {
min: string;
Expand All @@ -38,3 +39,21 @@ export interface NewJobCaps {
fields: Field[];
aggs: Aggregation[];
}

export interface AggFieldPair {
agg: Aggregation;
field: Field;
by?: {
field: SplitField;
value: string | null;
};
}

export interface AggFieldNamePair {
agg: string;
field: string;
by?: {
field: string | null;
value: string | null;
};
}
11 changes: 11 additions & 0 deletions x-pack/plugins/ml/common/util/anomaly_utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* 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 { ANOMALY_SEVERITY } from '../constants/anomalies';

export function getSeverity(normalizedScore: number): string;
export function getSeverityType(normalizedScore: number): ANOMALY_SEVERITY;
export function getSeverityColor(normalizedScore: number): string;
18 changes: 18 additions & 0 deletions x-pack/plugins/ml/common/util/anomaly_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import _ from 'lodash';
import { i18n } from '@kbn/i18n';
import { CONDITIONS_NOT_SUPPORTED_FUNCTIONS } from '../constants/detector_rule';
import { MULTI_BUCKET_IMPACT } from '../constants/multi_bucket_impact';
import { ANOMALY_SEVERITY } from '../constants/anomalies';


// List of function descriptions for which actual values from record level results should be displayed.
const DISPLAY_ACTUAL_FUNCTIONS = ['count', 'distinct_count', 'lat_long', 'mean', 'max', 'min', 'sum',
Expand Down Expand Up @@ -71,6 +73,22 @@ export function getSeverity(normalizedScore) {
}
}

export function getSeverityType(normalizedScore) {
if (normalizedScore >= 75) {
return ANOMALY_SEVERITY.CRITICAL;
} else if (normalizedScore >= 50) {
return ANOMALY_SEVERITY.MAJOR;
} else if (normalizedScore >= 25) {
return ANOMALY_SEVERITY.MINOR;
} else if (normalizedScore >= 3) {
return ANOMALY_SEVERITY.WARNING;
} else if (normalizedScore >= 0) {
return ANOMALY_SEVERITY.LOW;
} else {
return ANOMALY_SEVERITY.UNKNOWN;
}
}

// Returns a severity label (one of critical, major, minor, warning, low or unknown)
// for the supplied normalized anomaly score (a value between 0 and 100), where scores
// less than 3 are assigned a severity of 'low'.
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/ml/common/util/group_color_utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/*
* 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.
*/
export function tabColor(name: string): string;
13 changes: 13 additions & 0 deletions x-pack/plugins/ml/common/util/job_utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* 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.
*/

export function calculateDatafeedFrequencyDefaultSeconds(bucketSpanSeconds: number): number;

export function isTimeSeriesViewJob(job: any): boolean;

export const ML_MEDIAN_PERCENTS: number;

export const ML_DATA_PREVIEW_COUNT: number;
8 changes: 8 additions & 0 deletions x-pack/plugins/ml/common/util/string_utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* 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.
*/

export function renderTemplate(str: string, data: string): string;
export function stringHash(str: string): string;
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* 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 from 'react';

import { FormattedMessage } from '@kbn/i18n/react';
import { Query } from 'ui/embeddable';
import { IndexPattern } from 'ui/index_patterns';
import { EuiButton } from '@elastic/eui';
import { setFullTimeRange } from './full_time_range_selector_service';

interface Props {
indexPattern: IndexPattern;
query: Query;
disabled: boolean;
}

// Component for rendering a button which automatically sets the range of the time filter
// to the time range of data in the index(es) mapped to the supplied Kibana index pattern or query.
export const FullTimeRangeSelector: React.SFC<Props> = ({ indexPattern, query, disabled }) => {
return (
<EuiButton fill isDisabled={disabled} onClick={() => setFullTimeRange(indexPattern, query)}>
<FormattedMessage
id="xpack.ml.fullTimeRangeSelector.useFullDataButtonLabel"
defaultMessage="Use full {indexPatternTitle} data"
values={{
indexPatternTitle: indexPattern.title,
}}
/>
</EuiButton>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,14 @@ import { IndexPattern } from 'ui/index_patterns';
import { toastNotifications } from 'ui/notify';
import { timefilter } from 'ui/timefilter';
import { Query } from 'src/legacy/core_plugins/data/public';
import dateMath from '@elastic/datemath';
import { ml } from '../../services/ml_api_service';

export interface TimeRange {
from: number;
to: number;
}

export function setFullTimeRange(indexPattern: IndexPattern, query: Query) {
return ml
.getTimeFieldRange({
Expand All @@ -34,3 +40,24 @@ export function setFullTimeRange(indexPattern: IndexPattern, query: Query) {
);
});
}

export function getTimeFilterRange(): TimeRange {
let from = 0;
let to = 0;
const fromString = timefilter.getTime().from;
const toString = timefilter.getTime().to;
if (typeof fromString === 'string' && typeof toString === 'string') {
const fromMoment = dateMath.parse(fromString);
const toMoment = dateMath.parse(toString);
if (typeof fromMoment !== 'undefined' && typeof toMoment !== 'undefined') {
const fromMs = fromMoment.valueOf();
const toMs = toMoment.valueOf();
from = fromMs;
to = toMs;
}
}
return {
to,
from,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,5 @@
* 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 from 'react';

import { FormattedMessage } from '@kbn/i18n/react';
import { IndexPattern } from 'ui/index_patterns';
import { EuiButton } from '@elastic/eui';
import { Query } from 'src/legacy/core_plugins/data/public';
import { setFullTimeRange } from './full_time_range_selector_service';

interface Props {
indexPattern: IndexPattern;
query: Query;
disabled: boolean;
}

// Component for rendering a button which automatically sets the range of the time filter
// to the time range of data in the index(es) mapped to the supplied Kibana index pattern or query.
export const FullTimeRangeSelector: React.SFC<Props> = ({ indexPattern, query, disabled }) => {
return (
<EuiButton fill isDisabled={disabled} onClick={() => setFullTimeRange(indexPattern, query)}>
<FormattedMessage
id="xpack.ml.fullTimeRangeSelector.useFullDataButtonLabel"
defaultMessage="Use full {indexPatternTitle} data"
values={{
indexPatternTitle: indexPattern.title,
}}
/>
</EuiButton>
);
};
export { FullTimeRangeSelector } from './full_time_range_selector';
export { getTimeFilterRange } from './full_time_range_selector_service';
1 change: 1 addition & 0 deletions x-pack/plugins/ml/public/jobs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ import './new_job/simple/population';
import './new_job/simple/recognize';
import './new_job/wizard';
import 'plugins/ml/components/validate_job';
import './new_job_new';
17 changes: 17 additions & 0 deletions x-pack/plugins/ml/public/jobs/new_job/utils/new_job_utils.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* 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 { SavedSearch } from '../../../../../../../src/legacy/core_plugins/kibana/public/discover/types';
import { IndexPatternWithType, IndexPatternTitle } from '../../../../common/types/kibana';

export interface SearchItems {
indexPattern: IndexPatternWithType;
savedSearch: SavedSearch;
query: any;
combinedQuery: any;
}

export function SearchItemsProvider($route: Record<string, any>, config: any): () => SearchItems;
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,102 @@
</div>
</a>
</div>
<div class="euiFlexItem" ng-class='{disabled: isTimeBasedIndex===false}'>
<a ng-href="{{getUrl('#jobs/new_job/new_new_job/single_metric')}}" ng-class='{disabled: isTimeBasedIndex===false}' class="euiLink synopsis">
<div class="euiPanel euiPanel--paddingMedium synopsisPanel">
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--responsive">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<icon
type="'createSingleMetricJob'"
size="'xl'"
aria-label="{{ ::'xpack.ml.newJob.wizard.jobType.singleMetricAriaLabel' | i18n: {defaultMessage: 'Single metric job NEW'} }}"
class="synopsisIcon"
/>
</div>
<div class="euiFlexItem synopsisContent">
<h4
class="euiTitle euiTitle--small synopsisTitle"
i18n-id="xpack.ml.newJob.wizard.jobType.singleMetricTitle"
i18n-default-message="Single metric NEW"
></h4>
<div class="euiText synopsisBody">
<p>
<span
class="euiTextColor euiTextColor--subdued"
i18n-id="xpack.ml.newJob.wizard.jobType.singleMetricDescription"
i18n-default-message="Detect anomalies in a single time series."
></span>
</p>
</div>
</div>
</div>
</div>
</a>
</div>
<div class="euiFlexItem" ng-class='{disabled: isTimeBasedIndex===false}'>
<a ng-href="{{getUrl('#jobs/new_job/new_new_job/multi_metric')}}" ng-class='{disabled: isTimeBasedIndex===false}' class="euiLink synopsis">
<div class="euiPanel euiPanel--paddingMedium synopsisPanel">
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--responsive">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<icon
type="'createMultiMetricJob'"
size="'xl'"
aria-label="{{ ::'xpack.ml.newJob.wizard.jobType.multiMetricAriaLabel' | i18n: {defaultMessage: 'Multi metric job NEW'} }}"
class="synopsisIcon"
/>
</div>
<div class="euiFlexItem synopsisContent">
<h4
class="euiTitle euiTitle--small synopsisTitle"
i18n-id="xpack.ml.newJob.wizard.jobType.multiMetricTitle"
i18n-default-message="Multi metric NEW"
></h4>
<div class="euiText synopsisBody">
<p>
<span
class="euiTextColor euiTextColor--subdued"
i18n-id="xpack.ml.newJob.wizard.jobType.multiMetricDescription"
i18n-default-message="Detect anomalies in multiple metrics by splitting a time series by a categorical field."
></span>
</p>
</div>
</div>
</div>
</div>
</a>
</div>
<div class="euiFlexItem" ng-class='{disabled: isTimeBasedIndex===false}'>
<a ng-href="{{getUrl('#jobs/new_job/new_new_job/population')}}" ng-class='{disabled: isTimeBasedIndex===false}' class="euiLink synopsis">
<div class="euiPanel euiPanel--paddingMedium synopsisPanel">
<div class="euiFlexGroup euiFlexGroup--gutterLarge euiFlexGroup--responsive">
<div class="euiFlexItem euiFlexItem--flexGrowZero">
<icon
type="'createPopulationJob'"
size="'xl'"
aria-label="{{ ::'xpack.ml.newJob.wizard.jobType.populationAriaLabel' | i18n: {defaultMessage: 'Population job NEW'} }}"
class="synopsisIcon"
/>
</div>
<div class="euiFlexItem synopsisContent">
<h4
class="euiTitle euiTitle--small synopsisTitle"
i18n-id="xpack.ml.newJob.wizard.jobType.populationTitle"
i18n-default-message="Population NEW"
></h4>
<div class="euiText synopsisBody">
<p>
<span
class="euiTextColor euiTextColor--subdued"
i18n-id="xpack.ml.newJob.wizard.jobType.populationDescription"
i18n-default-message="Detect activity that is unusual compared to the behavior of the population."
></span>
</p>
</div>
</div>
</div>
</div>
</a>
</div>
</div>

<div class="euiSpacer euiSpacer--xxl"></div>
Expand Down
Loading