Skip to content

Commit

Permalink
[Metrics UI] Replace uses of any introduced by Lodash 4 (#75507)
Browse files Browse the repository at this point in the history
Co-authored-by: Felix Stürmer <[email protected]>
Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
3 people authored Aug 27, 2020
1 parent 8671db1 commit b98e2e4
Show file tree
Hide file tree
Showing 19 changed files with 82 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ interface Props {
nodeType: InventoryItemType;
filterQuery?: string;
filterQueryText?: string;
sourceId?: string;
sourceId: string;
alertOnNoData?: boolean;
};
alertInterval: string;
Expand Down Expand Up @@ -379,7 +379,7 @@ export const Expressions: React.FC<Props> = (props) => {
<AlertPreview
alertInterval={alertInterval}
alertType={METRIC_INVENTORY_THRESHOLD_ALERT_TYPE_ID}
alertParams={pick(alertParams as any, 'criteria', 'nodeType', 'sourceId', 'filterQuery')}
alertParams={pick(alertParams, 'criteria', 'nodeType', 'sourceId', 'filterQuery')}
validate={validateMetricThreshold}
fetch={alertsContext.http.fetch}
groupByDisplayName={alertParams.nodeType}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe('Expression', () => {
criteria: [],
groupBy: undefined,
filterQueryText: '',
sourceId: 'default',
};

const mocks = coreMock.createSetup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ export const Expressions: React.FC<Props> = (props) => {
<AlertPreview
alertInterval={alertInterval}
alertType={METRIC_THRESHOLD_ALERT_TYPE_ID}
alertParams={pick(alertParams as any, 'criteria', 'groupBy', 'filterQuery', 'sourceId')}
alertParams={pick(alertParams, 'criteria', 'groupBy', 'filterQuery', 'sourceId')}
showNoDataResults={alertParams.alertOnNoData}
validate={validateMetricThreshold}
fetch={alertsContext.http.fetch}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,16 @@ export const ExpressionChart: React.FC<Props> = ({
};
const isDarkMode = context.uiSettings?.get('theme:darkMode') || false;
const dateFormatter = useMemo(() => {
const firstSeries = data ? first(data.series) : null;
return firstSeries && firstSeries.rows.length > 0
? niceTimeFormatter([
(first(firstSeries.rows) as any).timestamp,
(last(firstSeries.rows) as any).timestamp,
])
: (value: number) => `${value}`;
}, [data]);
const firstSeries = first(data?.series);
const firstTimestamp = first(firstSeries?.rows)?.timestamp;
const lastTimestamp = last(firstSeries?.rows)?.timestamp;

if (firstTimestamp == null || lastTimestamp == null) {
return (value: number) => `${value}`;
}

return niceTimeFormatter([firstTimestamp, lastTimestamp]);
}, [data?.series]);

/* eslint-disable-next-line react-hooks/exhaustive-deps */
const yAxisFormater = useCallback(createFormatterForMetric(metric), [expression]);
Expand Down Expand Up @@ -138,8 +140,8 @@ export const ExpressionChart: React.FC<Props> = ({
}),
};

const firstTimestamp = (first(firstSeries.rows) as any).timestamp;
const lastTimestamp = (last(firstSeries.rows) as any).timestamp;
const firstTimestamp = first(firstSeries.rows)!.timestamp;
const lastTimestamp = last(firstSeries.rows)!.timestamp;
const dataDomain = calculateDomain(series, [metric], false);
const domain = {
max: Math.max(dataDomain.max, last(thresholds) || dataDomain.max) * 1.1, // add 10% headroom.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ export const transformMetricsExplorerData = (
data: MetricsExplorerResponse | null
) => {
const { criteria } = params;
if (criteria && data) {
const firstSeries = first(data.series) as any;
const series = firstSeries.rows.reduce((acc: any, row: any) => {
const firstSeries = first(data?.series);
if (criteria && firstSeries) {
const series = firstSeries.rows.reduce((acc, row) => {
const { timestamp } = row;
criteria.forEach((item, index) => {
if (!acc[index]) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export interface AlertParams {
criteria: MetricExpression[];
groupBy?: string[];
filterQuery?: string;
sourceId?: string;
sourceId: string;
filterQueryText?: string;
alertOnNoData?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ export const LegendControls = ({
fullWidth
label={
<SwatchLabel
color={first(paletteColors) as any}
color={first(paletteColors)!}
label={i18n.translate('xpack.infra.legendControls.minLabel', {
defaultMessage: 'Minimum',
})}
Expand Down Expand Up @@ -294,7 +294,7 @@ export const LegendControls = ({
display="columnCompressed"
label={
<SwatchLabel
color={last(paletteColors) as any}
color={last(paletteColors)!}
label={i18n.translate('xpack.infra.legendControls.maxLabel', {
defaultMessage: 'Maxium',
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,9 @@ export const calculateSteppedGradientColor = (

// Since the stepped legend matches a range we need to ensure anything outside
// the max bounds get's the maximum color.
if (gte(normalizedValue, (last(rules) as any).value)) {
return (last(rules) as any).color;
const lastRule = last(rules);
if (lastRule && gte(normalizedValue, lastRule.value)) {
return lastRule.color;
}

return rules.reduce((color: string, rule) => {
Expand All @@ -79,7 +80,7 @@ export const calculateSteppedGradientColor = (
return rule.color;
}
return color;
}, (first(rules) as any).color || defaultColor);
}, first(rules)?.color ?? defaultColor);
};

export const calculateStepColor = (
Expand All @@ -106,7 +107,7 @@ export const calculateGradientColor = (
return defaultColor;
}
if (rules.length === 1) {
return (last(rules) as any).color;
return last(rules)!.color;
}
const { min, max } = bounds;
const sortedRules = sortBy(rules, 'value');
Expand All @@ -116,10 +117,8 @@ export const calculateGradientColor = (
return rule;
}
return acc;
}, first(sortedRules)) as any;
const endRule = sortedRules
.filter((r) => r !== startRule)
.find((r) => r.value >= normValue) as any;
}, first(sortedRules))!;
const endRule = sortedRules.filter((r) => r !== startRule).find((r) => r.value >= normValue);
if (!endRule) {
return startRule.color;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ function findOrCreateGroupWithNodes(
* look for the full id. Otherwise we need to find the parent group and
* then look for the group in it's sub groups.
*/
if (path.length === 2) {
const parentId = (first(path) as any).value;
const firstPath = first(path);
if (path.length === 2 && firstPath) {
const parentId = firstPath.value;
const existingParentGroup = groups.find((g) => g.id === parentId);
if (isWaffleMapGroupWithGroups(existingParentGroup)) {
const existingSubGroup = existingParentGroup.groups.find((g) => g.id === id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,16 +74,13 @@ export const MetricsExplorerChart = ({
const [from, to] = x;
onTimeChange(moment(from).toISOString(), moment(to).toISOString());
};
const dateFormatter = useMemo(
() =>
series.rows.length > 0
? niceTimeFormatter([
(first(series.rows) as any).timestamp,
(last(series.rows) as any).timestamp,
])
: (value: number) => `${value}`,
[series.rows]
);
const dateFormatter = useMemo(() => {
const firstRow = first(series.rows);
const lastRow = last(series.rows);
return firstRow && lastRow
? niceTimeFormatter([firstRow.timestamp, lastRow.timestamp])
: (value: number) => `${value}`;
}, [series.rows]);
const tooltipProps = {
headerFormatter: useCallback(
(data: TooltipValue) => moment(data.value).format(dateFormat || 'Y-MM-DD HH:mm:ss.SSS'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,14 @@ const getData = async (
if (!nodes.length) return { [UNGROUPED_FACTORY_KEY]: null }; // No Data state

return nodes.reduce((acc, n) => {
const nodePathItem = last(n.path) as any;
const { name: nodeName } = n;
const m = first(n.metrics);
if (m && m.value && m.timeseries) {
const { timeseries } = m;
const values = timeseries.rows.map((row) => row.metric_0) as Array<number | null>;
acc[nodePathItem.label] = values;
acc[nodeName] = values;
} else {
acc[nodePathItem.label] = m && m.value;
acc[nodeName] = m && m.value;
}
return acc;
}, {} as Record<string, number | Array<number | string | null | undefined> | undefined | null>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
alertOnNoData,
} = params as InventoryMetricThresholdParams;

if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions');

const source = await libs.sources.getSourceConfiguration(
services.savedObjectsClient,
sourceId || 'default'
Expand All @@ -53,7 +55,7 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
)
);

const inventoryItems = Object.keys(first(results) as any);
const inventoryItems = Object.keys(first(results)!);
for (const item of inventoryItems) {
const alertInstance = services.alertInstanceFactory(`${item}`);
// AND logic; all criteria must be across the threshold
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export const previewInventoryMetricThresholdAlert = async ({
}: PreviewInventoryMetricThresholdAlertParams) => {
const { criteria, filterQuery, nodeType } = params as InventoryMetricThresholdParams;

if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions');

const { timeSize, timeUnit } = criteria[0];
const bucketInterval = `${timeSize}${timeUnit}`;
const bucketIntervalInSeconds = getIntervalInSeconds(bucketInterval);
Expand All @@ -57,7 +59,7 @@ export const previewInventoryMetricThresholdAlert = async ({
)
);

const inventoryItems = Object.keys(first(results) as any);
const inventoryItems = Object.keys(first(results)!);
const previewResults = inventoryItems.map((item) => {
const numberOfResultBuckets = lookbackSize;
const numberOfExecutionBuckets = Math.floor(numberOfResultBuckets / alertResultsPerExecution);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export const createMetricThresholdExecutor = (libs: InfraBackendLibs) =>
async function (options: AlertExecutorOptions) {
const { services, params } = options;
const { criteria } = params;
if (criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions');

const { sourceId, alertOnNoData } = params as {
sourceId?: string;
alertOnNoData: boolean;
Expand All @@ -34,8 +36,8 @@ export const createMetricThresholdExecutor = (libs: InfraBackendLibs) =>
const config = source.configuration;
const alertResults = await evaluateAlert(services.callCluster, params, config);

// Because each alert result has the same group definitions, just grap the groups from the first one.
const groups = Object.keys(first(alertResults) as any);
// Because each alert result has the same group definitions, just grab the groups from the first one.
const groups = Object.keys(first(alertResults)!);
for (const group of groups) {
const alertInstance = services.alertInstanceFactory(`${group}`);

Expand All @@ -60,7 +62,7 @@ export const createMetricThresholdExecutor = (libs: InfraBackendLibs) =>
let reason;
if (nextState === AlertStates.ALERT) {
reason = alertResults
.map((result) => buildFiredAlertReason(formatAlertResult(result[group]) as any))
.map((result) => buildFiredAlertReason(formatAlertResult(result[group])))
.join('\n');
}
if (alertOnNoData) {
Expand Down Expand Up @@ -121,11 +123,13 @@ const mapToConditionsLookup = (
{}
);

const formatAlertResult = (alertResult: {
metric: string;
currentValue: number;
threshold: number[];
}) => {
const formatAlertResult = <AlertResult>(
alertResult: {
metric: string;
currentValue: number;
threshold: number[];
} & AlertResult
) => {
const { metric, currentValue, threshold } = alertResult;
if (!metric.endsWith('.pct')) return alertResult;
const formatter = createFormatter('percent');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export const previewMetricThresholdAlert: (
iterations = 0,
precalculatedNumberOfGroups
) => {
if (params.criteria.length === 0) throw new Error('Cannot execute an alert with 0 conditions');

// There are three different "intervals" we're dealing with here, so to disambiguate:
// - The lookback interval, which is how long of a period of time we want to examine to count
// how many times the alert fired
Expand All @@ -70,7 +72,7 @@ export const previewMetricThresholdAlert: (
// Get a date histogram using the bucket interval and the lookback interval
try {
const alertResults = await evaluateAlert(callCluster, params, config, timeframe);
const groups = Object.keys(first(alertResults) as any);
const groups = Object.keys(first(alertResults)!);

// Now determine how to interpolate this histogram based on the alert interval
const alertIntervalInSeconds = getIntervalInSeconds(alertInterval);
Expand All @@ -81,7 +83,7 @@ export const previewMetricThresholdAlert: (
// buckets would have fired the alert. If the alert interval and bucket interval are the same,
// this will be a 1:1 evaluation of the alert results. If these are different, the interpolation
// will skip some buckets or read some buckets more than once, depending on the differential
const numberOfResultBuckets = (first(alertResults) as any)[group].shouldFire.length;
const numberOfResultBuckets = first(alertResults)![group].shouldFire.length;
const numberOfExecutionBuckets = Math.floor(
numberOfResultBuckets / alertResultsPerExecution
);
Expand Down Expand Up @@ -120,8 +122,7 @@ export const previewMetricThresholdAlert: (
? await evaluateAlert(callCluster, params, config)
: [];
const numberOfGroups =
precalculatedNumberOfGroups ??
Math.max(Object.keys(first(currentAlertResults) as any).length, 1);
precalculatedNumberOfGroups ?? Math.max(Object.keys(first(currentAlertResults)!).length, 1);
const estimatedTotalBuckets =
(lookbackIntervalInSeconds / bucketIntervalInSeconds) * numberOfGroups;
// The minimum number of slices is 2. In case we underestimate the total number of buckets
Expand Down Expand Up @@ -152,14 +153,16 @@ export const previewMetricThresholdAlert: (
// `undefined` values occur if there is no data at all in a certain slice, and that slice
// returns an empty array. This is different from an error or no data state,
// so filter these results out entirely and only regard the resultA portion
.filter((value) => typeof value !== 'undefined')
.filter(
<Value>(value: Value): value is NonNullable<Value> => typeof value !== 'undefined'
)
.reduce((a, b) => {
if (!a) return b;
if (!b) return a;
return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
})
);
return zippedResult as any;
return zippedResult;
} else throw e;
}
};
3 changes: 2 additions & 1 deletion x-pack/plugins/infra/server/lib/snapshot/response_helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ export const getNodeMetrics = (
avg: null,
}));
}
const lastBucket = findLastFullBucket(nodeBuckets, options) as any;
const lastBucket = findLastFullBucket(nodeBuckets, options);
if (!lastBucket) return [];
return options.metrics.map((metric, index) => {
const metricResult: SnapshotNodeMetric = {
name: metric.type,
Expand Down
7 changes: 5 additions & 2 deletions x-pack/plugins/infra/server/lib/snapshot/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ import { InfraSnapshotRequestOptions } from './types';
import { createTimeRangeWithInterval } from './create_timerange_with_interval';
import { SnapshotNode } from '../../../common/http_api/snapshot_api';

type NamedSnapshotNode = SnapshotNode & { name: string };

export type ESSearchClient = <Hit = {}, Aggregation = undefined>(
options: CallWithRequestParams
) => Promise<InfraDatabaseSearchResponse<Hit, Aggregation>>;
export class InfraSnapshot {
public async getNodes(
client: ESSearchClient,
options: InfraSnapshotRequestOptions
): Promise<{ nodes: SnapshotNode[]; interval: string }> {
): Promise<{ nodes: NamedSnapshotNode[]; interval: string }> {
// Both requestGroupedNodes and requestNodeMetrics may send several requests to elasticsearch
// in order to page through the results of their respective composite aggregations.
// Both chains of requests are supposed to run in parallel, and their results be merged
Expand Down Expand Up @@ -184,11 +186,12 @@ const mergeNodeBuckets = (
nodeGroupByBuckets: InfraSnapshotNodeGroupByBucket[],
nodeMetricsBuckets: InfraSnapshotNodeMetricsBucket[],
options: InfraSnapshotRequestOptions
): SnapshotNode[] => {
): NamedSnapshotNode[] => {
const nodeMetricsForLookup = getNodeMetricsForLookup(nodeMetricsBuckets);

return nodeGroupByBuckets.map((node) => {
return {
name: node.key.name || node.key.id, // For type safety; name can be derived from getNodePath but not in a TS-friendly way
path: getNodePath(node, options),
metrics: getNodeMetrics(nodeMetricsForLookup[node.key.id], options),
};
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/infra/server/routes/ip_to_hostname.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const initIpToHostName = ({ framework }: InfraBackendLibs) => {
body: { message: 'Host with matching IP address not found.' },
});
}
const hostDoc = first(hits.hits) as any;
const hostDoc = first(hits.hits)!;
return response.ok({ body: { host: hostDoc._source.host.name } });
} catch ({ statusCode = 500, message = 'Unknown error occurred' }) {
return response.customError({
Expand Down
Loading

0 comments on commit b98e2e4

Please sign in to comment.