function getMetricsForScaling()

in src/scaler/scaler-core/scaling-methods/linear.js [55:135]


function getMetricsForScaling(cluster, direction, engineAnalysis) {
  if (!engineAnalysis) return [];

  const /** @type {Condition[]} */ matchedConditions =
      engineAnalysis.matchedConditions[direction];
  if (!matchedConditions) return [];

  const /** @type {!Set<string>} */ scalingMetrics =
      engineAnalysis.scalingMetrics[direction];
  if (!scalingMetrics) return [];

  // Doing a map and filter would be more elegant, but filter() does not
  // properly narrow down types.
  const /** @type {ScalingMetricList} */ matchedMetrics = [];
  for (const matchedCondition of matchedConditions) {
    const metricName = matchedCondition.fact;
    if (!scalingMetrics.has(metricName)) continue;

    const metricValue = matchedCondition.factResult;
    const metricThreshold = matchedCondition.value;

    // This should not happen since the rules engine won't be able to trigger
    // this rule if the metric (fact) is not defined.
    if (metricValue === null || metricValue === undefined) {
      logger.error({
        message:
          `Unable to use this metric for linear scaling. ` +
          `No value for metric ${metricName} on the cluster. ` +
          `Consider removing this metric from scalingMetrics or adding a ` +
          `value to the condition for the fact with this name.`,
        projectId: cluster.projectId,
        regionId: cluster.regionId,
        instanceId: cluster.clusterId,
      });
      continue;
    }

    // This should not happen since the rules engine won't be able to trigger
    // this rule if there is not threshold (condition.value).
    if (typeof metricThreshold !== 'number') {
      logger.error({
        message:
          `Unable to use this metric for linear scaling. ` +
          `No numeric threshold value for ${metricName}. ` +
          `Consider removing this metric from scalingMetrics or adding a ` +
          `numeric value to the condition for the fact with this name. ` +
          `If a value is already added, ensure it is a number (numeric type).`,
        projectId: cluster.projectId,
        regionId: cluster.regionId,
        instanceId: cluster.clusterId,
      });
      continue;
    }

    if (metricThreshold === 0) {
      logger.error({
        message:
          `Unable to use this metric for linear scaling. ` +
          `The threshold value for ${metricName} is 0. Linear scaling uses ` +
          `threshold value as part of the cross multiplication to calculate ` +
          `the size and it is not possible to divide by 0. ` +
          `Consider removing this metric from scalingMetrics or adding a ` +
          `value other than 0 to the condition for the fact with this name.`,
        projectId: cluster.projectId,
        regionId: cluster.regionId,
        instanceId: cluster.clusterId,
      });
      continue;
    }

    const matchedMetric /** @type {MemorystoreClusterMetricValue} */ = {
      name: metricName,
      value: metricValue,
      threshold: metricThreshold,
    };

    matchedMetrics.push(matchedMetric);
  }

  return matchedMetrics;
}