Skip to content

Commit a81059b

Browse files
[ML] Removing full lodash library imports (#74742)
* [ML] Removing full lodash library imports * more has * fixing missing filter * removing _ * removing unused file * removing first use * removing comment
1 parent 506e953 commit a81059b

34 files changed

+365
-371
lines changed

x-pack/plugins/ml/common/util/job_utils.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import _ from 'lodash';
7+
import isEmpty from 'lodash/isEmpty';
8+
import isEqual from 'lodash/isEqual';
9+
import each from 'lodash/each';
10+
import pick from 'lodash/pick';
11+
812
import semver from 'semver';
913
import moment, { Duration } from 'moment';
1014
// @ts-ignore
@@ -307,7 +311,7 @@ export function getSafeAggregationName(fieldName: string, index: number): string
307311

308312
export function uniqWithIsEqual<T extends any[]>(arr: T): T {
309313
return arr.reduce((dedupedArray, value) => {
310-
if (dedupedArray.filter((compareValue: any) => _.isEqual(compareValue, value)).length === 0) {
314+
if (dedupedArray.filter((compareValue: any) => isEqual(compareValue, value)).length === 0) {
311315
dedupedArray.push(value);
312316
}
313317
return dedupedArray;
@@ -328,7 +332,7 @@ export function basicJobValidation(
328332

329333
if (job) {
330334
// Job details
331-
if (_.isEmpty(job.job_id)) {
335+
if (isEmpty(job.job_id)) {
332336
messages.push({ id: 'job_id_empty' });
333337
valid = false;
334338
} else if (isJobIdValid(job.job_id) === false) {
@@ -350,7 +354,7 @@ export function basicJobValidation(
350354
// Analysis Configuration
351355
if (job.analysis_config.categorization_filters) {
352356
let v = true;
353-
_.each(job.analysis_config.categorization_filters, (d) => {
357+
each(job.analysis_config.categorization_filters, (d) => {
354358
try {
355359
new RegExp(d);
356360
} catch (e) {
@@ -382,8 +386,8 @@ export function basicJobValidation(
382386
valid = false;
383387
} else {
384388
let v = true;
385-
_.each(job.analysis_config.detectors, (d) => {
386-
if (_.isEmpty(d.function)) {
389+
each(job.analysis_config.detectors, (d) => {
390+
if (isEmpty(d.function)) {
387391
v = false;
388392
}
389393
});
@@ -400,7 +404,7 @@ export function basicJobValidation(
400404
// create an array of objects with a subset of the attributes
401405
// where we want to make sure they are not be the same across detectors
402406
const compareSubSet = job.analysis_config.detectors.map((d) =>
403-
_.pick(d, [
407+
pick(d, [
404408
'function',
405409
'field_name',
406410
'by_field_name',

x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
* This version supports both fetching the annotations by itself (used in the jobs list) and
1010
* getting the annotations via props (used in Anomaly Explorer and Single Series Viewer).
1111
*/
12-
import _ from 'lodash';
12+
13+
import uniq from 'lodash/uniq';
14+
1315
import PropTypes from 'prop-types';
1416
import rison from 'rison-node';
1517
import React, { Component, Fragment } from 'react';
@@ -255,18 +257,18 @@ export class AnnotationsTable extends Component {
255257

256258
// if the annotation is at the series level
257259
// then pass the partitioning field(s) and detector index to the Single Metric Viewer
258-
if (_.has(annotation, 'detector_index')) {
260+
if (annotation.detector_index !== undefined) {
259261
mlTimeSeriesExplorer.detectorIndex = annotation.detector_index;
260262
}
261-
if (_.has(annotation, 'partition_field_value')) {
263+
if (annotation.partition_field_value !== undefined) {
262264
entityCondition[annotation.partition_field_name] = annotation.partition_field_value;
263265
}
264266

265-
if (_.has(annotation, 'over_field_value')) {
267+
if (annotation.over_field_value !== undefined) {
266268
entityCondition[annotation.over_field_name] = annotation.over_field_value;
267269
}
268270

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

424-
const jobIds = _.uniq(annotations.map((a) => a.job_id));
426+
const jobIds = uniq(annotations.map((a) => a.job_id));
425427
if (jobIds.length > 1) {
426428
columns.unshift({
427429
field: 'job_id',

x-pack/plugins/ml/public/application/components/anomalies_table/anomalies_table.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*/
1010

1111
import PropTypes from 'prop-types';
12-
import _ from 'lodash';
12+
import get from 'lodash/get';
1313

1414
import React, { Component } from 'react';
1515

@@ -70,7 +70,7 @@ class AnomaliesTable extends Component {
7070
} else {
7171
const examples =
7272
item.entityName === 'mlcategory'
73-
? _.get(this.props.tableData, ['examplesByJobId', item.jobId, item.entityValue])
73+
? get(this.props.tableData, ['examplesByJobId', item.jobId, item.entityValue])
7474
: undefined;
7575
let definition = undefined;
7676

x-pack/plugins/ml/public/application/components/anomalies_table/anomalies_table_columns.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import { EuiButtonIcon, EuiLink, EuiScreenReaderOnly } from '@elastic/eui';
88

99
import React from 'react';
10-
import _ from 'lodash';
10+
import get from 'lodash/get';
1111

1212
import { i18n } from '@kbn/i18n';
1313
import { FormattedMessage } from '@kbn/i18n/react';
@@ -251,7 +251,7 @@ export function getColumns(
251251
sortable: false,
252252
truncateText: true,
253253
render: (item) => {
254-
const examples = _.get(examplesByJobId, [item.jobId, item.entityValue], []);
254+
const examples = get(examplesByJobId, [item.jobId, item.entityValue], []);
255255
return (
256256
<EuiLink
257257
className="mlAnomalyCategoryExamples__link"

x-pack/plugins/ml/public/application/components/anomalies_table/anomaly_details.js

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111

1212
import PropTypes from 'prop-types';
1313
import React, { Component, Fragment } from 'react';
14-
import _ from 'lodash';
14+
import get from 'lodash/get';
15+
import pick from 'lodash/pick';
1516
import { i18n } from '@kbn/i18n';
1617
import { FormattedMessage } from '@kbn/i18n/react';
1718

@@ -63,16 +64,12 @@ function getDetailsItems(anomaly, examples, filter) {
6364
}
6465
} else {
6566
causes = sourceCauses.map((cause) => {
66-
const simplified = _.pick(cause, 'typical', 'actual', 'probability');
67+
const simplified = pick(cause, 'typical', 'actual', 'probability');
6768
// Get the 'entity field name/value' to display in the cause -
6869
// For by and over, use by_field_name/value (over_field_name/value are in the top level fields)
6970
// For just an 'over' field - the over_field_name/value appear in both top level and cause.
70-
simplified.entityName = _.has(cause, 'by_field_name')
71-
? cause.by_field_name
72-
: cause.over_field_name;
73-
simplified.entityValue = _.has(cause, 'by_field_value')
74-
? cause.by_field_value
75-
: cause.over_field_value;
71+
simplified.entityName = cause.by_field_name ? cause.by_field_name : cause.over_field_name;
72+
simplified.entityValue = cause.by_field_value ? cause.by_field_value : cause.over_field_value;
7673
return simplified;
7774
});
7875
}
@@ -471,7 +468,7 @@ export class AnomalyDetails extends Component {
471468

472469
renderDetails() {
473470
const detailItems = getDetailsItems(this.props.anomaly, this.props.examples, this.props.filter);
474-
const isInterimResult = _.get(this.props.anomaly, 'source.is_interim', false);
471+
const isInterimResult = get(this.props.anomaly, 'source.is_interim', false);
475472
return (
476473
<React.Fragment>
477474
<EuiText size="xs">

x-pack/plugins/ml/public/application/components/anomalies_table/influencers_cell.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import _ from 'lodash';
7+
import each from 'lodash/each';
88
import PropTypes from 'prop-types';
99
import React, { Component } from 'react';
1010

@@ -148,7 +148,7 @@ export class InfluencersCell extends Component {
148148

149149
const influencers = [];
150150
recordInfluencers.forEach((influencer) => {
151-
_.each(influencer, (influencerFieldValue, influencerFieldName) => {
151+
each(influencer, (influencerFieldValue, influencerFieldName) => {
152152
influencers.push({
153153
influencerFieldName,
154154
influencerFieldValue,

x-pack/plugins/ml/public/application/components/anomalies_table/links_menu.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* you may not use this file except in compliance with the Elastic License.
55
*/
66

7-
import _ from 'lodash';
7+
import cloneDeep from 'lodash/cloneDeep';
88
import moment from 'moment';
99
import rison from 'rison-node';
1010
import PropTypes from 'prop-types';
@@ -58,7 +58,7 @@ class LinksMenuUI extends Component {
5858

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

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

159-
if (_.has(record, 'partition_field_value')) {
159+
if (record.partition_field_value !== undefined) {
160160
entityCondition[record.partition_field_name] = record.partition_field_value;
161161
}
162162

163-
if (_.has(record, 'over_field_value')) {
163+
if (record.over_field_value !== undefined) {
164164
entityCondition[record.over_field_name] = record.over_field_value;
165165
}
166166

167-
if (_.has(record, 'by_field_value')) {
167+
if (record.by_field_value !== undefined) {
168168
// Note that analyses with by and over fields, will have a top-level by_field_name,
169169
// but the by_field_value(s) will be in the nested causes array.
170170
// TODO - drilldown from cause in expanded row only?

x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_config_builder.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
* the raw data in the Explorer dashboard.
1010
*/
1111

12-
import _ from 'lodash';
13-
1412
import { parseInterval } from '../../../../common/util/parse_interval';
1513
import { getEntityFieldList } from '../../../../common/util/anomaly_utils';
1614
import { buildConfigFromDetector } from '../../util/chart_config_builder';
@@ -30,7 +28,7 @@ export function buildConfig(record) {
3028

3129
config.detectorLabel = record.function;
3230
if (
33-
_.has(mlJobService.detectorsByJob, record.job_id) &&
31+
mlJobService.detectorsByJob[record.job_id] !== undefined &&
3432
detectorIndex < mlJobService.detectorsByJob[record.job_id].length
3533
) {
3634
config.detectorLabel =

x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_distribution.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111

1212
import PropTypes from 'prop-types';
1313
import React from 'react';
14+
import { i18n } from '@kbn/i18n';
1415

15-
import _ from 'lodash';
1616
import d3 from 'd3';
1717
import $ from 'jquery';
1818
import moment from 'moment';
@@ -33,8 +33,6 @@ import { mlFieldFormatService } from '../../services/field_format_service';
3333

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

36-
import { i18n } from '@kbn/i18n';
37-
3836
const CONTENT_WRAPPER_HEIGHT = 215;
3937

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

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

460-
if (_.has(marker, 'anomalyScore')) {
458+
if (marker.anomalyScore !== undefined) {
461459
const score = parseInt(marker.anomalyScore);
462460
const displayScore = score > 0 ? score : '< 1';
463461
tooltipData.push({
@@ -494,7 +492,7 @@ export class ExplorerChartDistribution extends React.Component {
494492
valueAccessor: 'typical',
495493
});
496494
}
497-
if (typeof marker.byFieldName !== 'undefined' && _.has(marker, 'numberOfCauses')) {
495+
if (typeof marker.byFieldName !== 'undefined' && marker.numberOfCauses !== undefined) {
498496
tooltipData.push({
499497
label: i18n.translate(
500498
'xpack.ml.explorer.distributionChart.unusualByFieldValuesLabel',
@@ -532,7 +530,7 @@ export class ExplorerChartDistribution extends React.Component {
532530
});
533531
}
534532

535-
if (_.has(marker, 'scheduledEvents')) {
533+
if (marker.scheduledEvents !== undefined) {
536534
marker.scheduledEvents.forEach((scheduledEvent, i) => {
537535
tooltipData.push({
538536
label: i18n.translate(

x-pack/plugins/ml/public/application/explorer/explorer_charts/explorer_chart_single_metric.js

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@
1212
import PropTypes from 'prop-types';
1313
import React from 'react';
1414

15-
import _ from 'lodash';
1615
import d3 from 'd3';
1716
import $ from 'jquery';
1817
import moment from 'moment';
18+
import { i18n } from '@kbn/i18n';
1919

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

43-
import { i18n } from '@kbn/i18n';
44-
4543
const CONTENT_WRAPPER_HEIGHT = 215;
4644
const CONTENT_WRAPPER_CLASS = 'ml-explorer-chart-content-wrapper';
4745

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

309307
const isAnomalyVisible = (d) =>
310-
_.has(d, 'anomalyScore') && Number(d.anomalyScore) >= severity;
308+
d.anomalyScore !== undefined && Number(d.anomalyScore) >= severity;
311309

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

383-
if (_.has(marker, 'anomalyScore')) {
381+
if (marker.anomalyScore !== undefined) {
384382
const score = parseInt(marker.anomalyScore);
385383
const displayScore = score > 0 ? score : '< 1';
386384
tooltipData.push({
@@ -411,7 +409,7 @@ export class ExplorerChartSingleMetric extends React.Component {
411409
// Show actual/typical when available except for rare detectors.
412410
// Rare detectors always have 1 as actual and the probability as typical.
413411
// Exposing those values in the tooltip with actual/typical labels might irritate users.
414-
if (_.has(marker, 'actual') && config.functionDescription !== 'rare') {
412+
if (marker.actual !== undefined && config.functionDescription !== 'rare') {
415413
// Display the record actual in preference to the chart value, which may be
416414
// different depending on the aggregation interval of the chart.
417415
tooltipData.push({
@@ -445,7 +443,7 @@ export class ExplorerChartSingleMetric extends React.Component {
445443
},
446444
valueAccessor: 'value',
447445
});
448-
if (_.has(marker, 'byFieldName') && _.has(marker, 'numberOfCauses')) {
446+
if (marker.byFieldName !== undefined && marker.numberOfCauses !== undefined) {
449447
tooltipData.push({
450448
label: i18n.translate(
451449
'xpack.ml.explorer.distributionChart.unusualByFieldValuesLabel',
@@ -483,7 +481,7 @@ export class ExplorerChartSingleMetric extends React.Component {
483481
});
484482
}
485483

486-
if (_.has(marker, 'scheduledEvents')) {
484+
if (marker.scheduledEvents !== undefined) {
487485
tooltipData.push({
488486
label: i18n.translate('xpack.ml.explorer.singleMetricChart.scheduledEventsLabel', {
489487
defaultMessage: 'Scheduled events',

0 commit comments

Comments
 (0)