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

[7.x] [ML] Removing full lodash library imports (#74742) #74832

Merged
merged 1 commit into from
Aug 12, 2020
Merged
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
18 changes: 11 additions & 7 deletions x-pack/plugins/ml/common/util/job_utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@
* you may not use this file except in compliance with the Elastic License.
*/

import _ from 'lodash';
import isEmpty from 'lodash/isEmpty';
import isEqual from 'lodash/isEqual';
import each from 'lodash/each';
import pick from 'lodash/pick';

import semver from 'semver';
import moment, { Duration } from 'moment';
// @ts-ignore
Expand Down Expand Up @@ -307,7 +311,7 @@ export function getSafeAggregationName(fieldName: string, index: number): string

export function uniqWithIsEqual<T extends any[]>(arr: T): T {
return arr.reduce((dedupedArray, value) => {
if (dedupedArray.filter((compareValue: any) => _.isEqual(compareValue, value)).length === 0) {
if (dedupedArray.filter((compareValue: any) => isEqual(compareValue, value)).length === 0) {
dedupedArray.push(value);
}
return dedupedArray;
Expand All @@ -328,7 +332,7 @@ export function basicJobValidation(

if (job) {
// Job details
if (_.isEmpty(job.job_id)) {
if (isEmpty(job.job_id)) {
messages.push({ id: 'job_id_empty' });
valid = false;
} else if (isJobIdValid(job.job_id) === false) {
Expand All @@ -350,7 +354,7 @@ export function basicJobValidation(
// Analysis Configuration
if (job.analysis_config.categorization_filters) {
let v = true;
_.each(job.analysis_config.categorization_filters, (d) => {
each(job.analysis_config.categorization_filters, (d) => {
try {
new RegExp(d);
} catch (e) {
Expand Down Expand Up @@ -382,8 +386,8 @@ export function basicJobValidation(
valid = false;
} else {
let v = true;
_.each(job.analysis_config.detectors, (d) => {
if (_.isEmpty(d.function)) {
each(job.analysis_config.detectors, (d) => {
if (isEmpty(d.function)) {
v = false;
}
});
Expand All @@ -400,7 +404,7 @@ export function basicJobValidation(
// create an array of objects with a subset of the attributes
// where we want to make sure they are not be the same across detectors
const compareSubSet = job.analysis_config.detectors.map((d) =>
_.pick(d, [
pick(d, [
'function',
'field_name',
'by_field_name',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
* This version supports both fetching the annotations by itself (used in the jobs list) and
* getting the annotations via props (used in Anomaly Explorer and Single Series Viewer).
*/
import _ from 'lodash';

import uniq from 'lodash/uniq';

import PropTypes from 'prop-types';
import rison from 'rison-node';
import React, { Component, Fragment } from 'react';
Expand Down Expand Up @@ -255,18 +257,18 @@ export class AnnotationsTable extends Component {

// if the annotation is at the series level
// then pass the partitioning field(s) and detector index to the Single Metric Viewer
if (_.has(annotation, 'detector_index')) {
if (annotation.detector_index !== undefined) {
mlTimeSeriesExplorer.detectorIndex = annotation.detector_index;
}
if (_.has(annotation, 'partition_field_value')) {
if (annotation.partition_field_value !== undefined) {
entityCondition[annotation.partition_field_name] = annotation.partition_field_value;
}

if (_.has(annotation, 'over_field_value')) {
if (annotation.over_field_value !== undefined) {
entityCondition[annotation.over_field_name] = annotation.over_field_value;
}

if (_.has(annotation, 'by_field_value')) {
if (annotation.by_field_value !== undefined) {
// Note that analyses with by and over fields, will have a top-level by_field_name,
// but the by_field_value(s) will be in the nested causes array.
entityCondition[annotation.by_field_name] = annotation.by_field_value;
Expand Down Expand Up @@ -421,7 +423,7 @@ export class AnnotationsTable extends Component {
},
];

const jobIds = _.uniq(annotations.map((a) => a.job_id));
const jobIds = uniq(annotations.map((a) => a.job_id));
if (jobIds.length > 1) {
columns.unshift({
field: 'job_id',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/

import PropTypes from 'prop-types';
import _ from 'lodash';
import get from 'lodash/get';

import React, { Component } from 'react';

Expand Down Expand Up @@ -70,7 +70,7 @@ class AnomaliesTable extends Component {
} else {
const examples =
item.entityName === 'mlcategory'
? _.get(this.props.tableData, ['examplesByJobId', item.jobId, item.entityValue])
? get(this.props.tableData, ['examplesByJobId', item.jobId, item.entityValue])
: undefined;
let definition = undefined;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import { EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui';

import React from 'react';
import _ from 'lodash';
import get from 'lodash/get';

import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
Expand Down Expand Up @@ -251,7 +251,7 @@ export function getColumns(
sortable: false,
truncateText: true,
render: (item) => {
const examples = _.get(examplesByJobId, [item.jobId, item.entityValue], []);
const examples = get(examplesByJobId, [item.jobId, item.entityValue], []);
return (
<EuiLink
className="mlAnomalyCategoryExamples__link"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@

import PropTypes from 'prop-types';
import React, { Component, Fragment } from 'react';
import _ from 'lodash';
import get from 'lodash/get';
import pick from 'lodash/pick';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';

Expand Down Expand Up @@ -63,16 +64,12 @@ function getDetailsItems(anomaly, examples, filter) {
}
} else {
causes = sourceCauses.map((cause) => {
const simplified = _.pick(cause, 'typical', 'actual', 'probability');
const simplified = pick(cause, 'typical', 'actual', 'probability');
// Get the 'entity field name/value' to display in the cause -
// For by and over, use by_field_name/value (over_field_name/value are in the top level fields)
// For just an 'over' field - the over_field_name/value appear in both top level and cause.
simplified.entityName = _.has(cause, 'by_field_name')
? cause.by_field_name
: cause.over_field_name;
simplified.entityValue = _.has(cause, 'by_field_value')
? cause.by_field_value
: cause.over_field_value;
simplified.entityName = cause.by_field_name ? cause.by_field_name : cause.over_field_name;
simplified.entityValue = cause.by_field_value ? cause.by_field_value : cause.over_field_value;
return simplified;
});
}
Expand Down Expand Up @@ -471,7 +468,7 @@ export class AnomalyDetails extends Component {

renderDetails() {
const detailItems = getDetailsItems(this.props.anomaly, this.props.examples, this.props.filter);
const isInterimResult = _.get(this.props.anomaly, 'source.is_interim', false);
const isInterimResult = get(this.props.anomaly, 'source.is_interim', false);
return (
<React.Fragment>
<EuiText size="xs">
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 _ from 'lodash';
import each from 'lodash/each';
import PropTypes from 'prop-types';
import React, { Component } from 'react';

Expand Down Expand Up @@ -148,7 +148,7 @@ export class InfluencersCell extends Component {

const influencers = [];
recordInfluencers.forEach((influencer) => {
_.each(influencer, (influencerFieldValue, influencerFieldName) => {
each(influencer, (influencerFieldValue, influencerFieldName) => {
influencers.push({
influencerFieldName,
influencerFieldValue,
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 _ from 'lodash';
import cloneDeep from 'lodash/cloneDeep';
import moment from 'moment';
import rison from 'rison-node';
import PropTypes from 'prop-types';
Expand Down Expand Up @@ -58,7 +58,7 @@ class LinksMenuUI extends Component {

// If url_value contains $earliest$ and $latest$ tokens, add in times to the source record.
// Create a copy of the record as we are adding properties into it.
const record = _.cloneDeep(anomaly.source);
const record = cloneDeep(anomaly.source);
const timestamp = record.timestamp;
const configuredUrlValue = customUrl.url_value;
const timeRangeInterval = parseInterval(customUrl.time_range);
Expand Down Expand Up @@ -99,7 +99,7 @@ class LinksMenuUI extends Component {
if (
(configuredUrlValue.includes('$mlcategoryterms$') ||
configuredUrlValue.includes('$mlcategoryregex$')) &&
_.has(record, 'mlcategory')
record.mlcategory !== undefined
) {
const jobId = record.job_id;

Expand Down Expand Up @@ -156,15 +156,15 @@ class LinksMenuUI extends Component {
// Extract the by, over and partition fields for the record.
const entityCondition = {};

if (_.has(record, 'partition_field_value')) {
if (record.partition_field_value !== undefined) {
entityCondition[record.partition_field_name] = record.partition_field_value;
}

if (_.has(record, 'over_field_value')) {
if (record.over_field_value !== undefined) {
entityCondition[record.over_field_name] = record.over_field_value;
}

if (_.has(record, 'by_field_value')) {
if (record.by_field_value !== undefined) {
// Note that analyses with by and over fields, will have a top-level by_field_name,
// but the by_field_value(s) will be in the nested causes array.
// TODO - drilldown from cause in expanded row only?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
* the raw data in the Explorer dashboard.
*/

import _ from 'lodash';

import { parseInterval } from '../../../../common/util/parse_interval';
import { getEntityFieldList } from '../../../../common/util/anomaly_utils';
import { buildConfigFromDetector } from '../../util/chart_config_builder';
Expand All @@ -30,7 +28,7 @@ export function buildConfig(record) {

config.detectorLabel = record.function;
if (
_.has(mlJobService.detectorsByJob, record.job_id) &&
mlJobService.detectorsByJob[record.job_id] !== undefined &&
detectorIndex < mlJobService.detectorsByJob[record.job_id].length
) {
config.detectorLabel =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@

import PropTypes from 'prop-types';
import React from 'react';
import { i18n } from '@kbn/i18n';

import _ from 'lodash';
import d3 from 'd3';
import $ from 'jquery';
import moment from 'moment';
Expand All @@ -33,8 +33,6 @@ import { mlFieldFormatService } from '../../services/field_format_service';

import { CHART_TYPE } from '../explorer_constants';

import { i18n } from '@kbn/i18n';

const CONTENT_WRAPPER_HEIGHT = 215;

// If a rare/event-distribution chart has a cardinality of 10 or less,
Expand Down Expand Up @@ -403,7 +401,7 @@ export class ExplorerChartDistribution extends React.Component {
.attr('cy', (d) => lineChartYScale(d[CHART_Y_ATTRIBUTE]))
.attr('class', (d) => {
let markerClass = 'metric-value';
if (_.has(d, 'anomalyScore') && Number(d.anomalyScore) >= severity) {
if (d.anomalyScore !== undefined && Number(d.anomalyScore) >= severity) {
markerClass += ' anomaly-marker ';
markerClass += getSeverityWithLow(d.anomalyScore).id;
}
Expand Down Expand Up @@ -444,7 +442,7 @@ export class ExplorerChartDistribution extends React.Component {
const tooltipData = [{ label: formattedDate }];
const seriesKey = config.detectorLabel;

if (_.has(marker, 'entity')) {
if (marker.entity !== undefined) {
tooltipData.push({
label: i18n.translate('xpack.ml.explorer.distributionChart.entityLabel', {
defaultMessage: 'entity',
Expand All @@ -457,7 +455,7 @@ export class ExplorerChartDistribution extends React.Component {
});
}

if (_.has(marker, 'anomalyScore')) {
if (marker.anomalyScore !== undefined) {
const score = parseInt(marker.anomalyScore);
const displayScore = score > 0 ? score : '< 1';
tooltipData.push({
Expand Down Expand Up @@ -494,7 +492,7 @@ export class ExplorerChartDistribution extends React.Component {
valueAccessor: 'typical',
});
}
if (typeof marker.byFieldName !== 'undefined' && _.has(marker, 'numberOfCauses')) {
if (typeof marker.byFieldName !== 'undefined' && marker.numberOfCauses !== undefined) {
tooltipData.push({
label: i18n.translate(
'xpack.ml.explorer.distributionChart.unusualByFieldValuesLabel',
Expand Down Expand Up @@ -532,7 +530,7 @@ export class ExplorerChartDistribution extends React.Component {
});
}

if (_.has(marker, 'scheduledEvents')) {
if (marker.scheduledEvents !== undefined) {
marker.scheduledEvents.forEach((scheduledEvent, i) => {
tooltipData.push({
label: i18n.translate(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
import PropTypes from 'prop-types';
import React from 'react';

import _ from 'lodash';
import d3 from 'd3';
import $ from 'jquery';
import moment from 'moment';
import { i18n } from '@kbn/i18n';

import { formatHumanReadableDateTime } from '../../util/date_utils';
import { formatValue } from '../../formatters/format_value';
Expand All @@ -40,8 +40,6 @@ import { getTimeBucketsFromCache } from '../../util/time_buckets';
import { mlEscape } from '../../util/string_utils';
import { mlFieldFormatService } from '../../services/field_format_service';

import { i18n } from '@kbn/i18n';

const CONTENT_WRAPPER_HEIGHT = 215;
const CONTENT_WRAPPER_CLASS = 'ml-explorer-chart-content-wrapper';

Expand Down Expand Up @@ -307,7 +305,7 @@ export class ExplorerChartSingleMetric extends React.Component {
.on('mouseout', () => tooltipService.hide());

const isAnomalyVisible = (d) =>
_.has(d, 'anomalyScore') && Number(d.anomalyScore) >= severity;
d.anomalyScore !== undefined && Number(d.anomalyScore) >= severity;

// Update all dots to new positions.
dots
Expand Down Expand Up @@ -380,7 +378,7 @@ export class ExplorerChartSingleMetric extends React.Component {
const tooltipData = [{ label: formattedDate }];
const seriesKey = config.detectorLabel;

if (_.has(marker, 'anomalyScore')) {
if (marker.anomalyScore !== undefined) {
const score = parseInt(marker.anomalyScore);
const displayScore = score > 0 ? score : '< 1';
tooltipData.push({
Expand Down Expand Up @@ -411,7 +409,7 @@ export class ExplorerChartSingleMetric extends React.Component {
// Show actual/typical when available except for rare detectors.
// Rare detectors always have 1 as actual and the probability as typical.
// Exposing those values in the tooltip with actual/typical labels might irritate users.
if (_.has(marker, 'actual') && config.functionDescription !== 'rare') {
if (marker.actual !== undefined && config.functionDescription !== 'rare') {
// Display the record actual in preference to the chart value, which may be
// different depending on the aggregation interval of the chart.
tooltipData.push({
Expand Down Expand Up @@ -445,7 +443,7 @@ export class ExplorerChartSingleMetric extends React.Component {
},
valueAccessor: 'value',
});
if (_.has(marker, 'byFieldName') && _.has(marker, 'numberOfCauses')) {
if (marker.byFieldName !== undefined && marker.numberOfCauses !== undefined) {
tooltipData.push({
label: i18n.translate(
'xpack.ml.explorer.distributionChart.unusualByFieldValuesLabel',
Expand Down Expand Up @@ -483,7 +481,7 @@ export class ExplorerChartSingleMetric extends React.Component {
});
}

if (_.has(marker, 'scheduledEvents')) {
if (marker.scheduledEvents !== undefined) {
tooltipData.push({
label: i18n.translate('xpack.ml.explorer.singleMetricChart.scheduledEventsLabel', {
defaultMessage: 'Scheduled events',
Expand Down
Loading