export async function getTotalCountAggregations()

in x-pack/platform/plugins/shared/alerting/server/usage/lib/get_telemetry_from_kibana.ts [78:460]


export async function getTotalCountAggregations({
  esClient,
  alertIndex,
  logger,
}: Opts): Promise<GetTotalCountsResults> {
  try {
    const query = {
      index: alertIndex,
      size: 0,
      query: {
        bool: {
          // Aggregate over all rule saved objects
          filter: [{ term: { type: 'alert' } }],
        },
      },
      runtime_mappings: {
        rule_action_count: {
          type: 'long' as const,
          script: {
            source: `
                def alert = params._source['alert'];
                if (alert != null) {
                  def actions = alert.actions;
                  if (actions != null) {
                    emit(actions.length);
                  } else {
                    emit(0);
                  }
                }`,
          },
        },
        // Convert schedule interval duration string from rule saved object to interval in seconds
        rule_schedule_interval: {
          type: 'long' as const,
          script: {
            source: `
                int parsed = 0;
                if (doc['alert.schedule.interval'].size() > 0) {
                  def interval = doc['alert.schedule.interval'].value;

                  if (interval.length() > 1) {
                      // get last char
                      String timeChar = interval.substring(interval.length() - 1);
                      // remove last char
                      interval = interval.substring(0, interval.length() - 1);

                      if (interval.chars().allMatch(Character::isDigit)) {
                        // using of regex is not allowed in painless language
                        parsed = Integer.parseInt(interval);

                        if (timeChar.equals("s")) {
                          parsed = parsed;
                        } else if (timeChar.equals("m")) {
                          parsed = parsed * 60;
                        } else if (timeChar.equals("h")) {
                          parsed = parsed * 60 * 60;
                        } else if (timeChar.equals("d")) {
                          parsed = parsed * 24 * 60 * 60;
                        }
                        emit(parsed);
                      }
                  }
                }
                emit(parsed);
              `,
          },
        },
        // Convert throttle interval duration string from rule saved object to interval in seconds
        rule_throttle_interval: {
          type: 'long' as const,
          script: {
            source: `
                int parsed = 0;
                if (doc['alert.throttle'].size() > 0) {
                def throttle = doc['alert.throttle'].value;

                if (throttle.length() > 1) {
                    // get last char
                    String timeChar = throttle.substring(throttle.length() - 1);
                    // remove last char
                    throttle = throttle.substring(0, throttle.length() - 1);

                    if (throttle.chars().allMatch(Character::isDigit)) {
                      // using of regex is not allowed in painless language
                      parsed = Integer.parseInt(throttle);

                      if (timeChar.equals("s")) {
                        parsed = parsed;
                      } else if (timeChar.equals("m")) {
                        parsed = parsed * 60;
                      } else if (timeChar.equals("h")) {
                        parsed = parsed * 60 * 60;
                      } else if (timeChar.equals("d")) {
                        parsed = parsed * 24 * 60 * 60;
                      }
                      emit(parsed);
                    }
                }
              }
              emit(parsed);
              `,
          },
        },
        rule_with_tags: {
          type: 'long' as const,
          script: {
            source: `
               def rule = params._source['alert'];
                if (rule != null && rule.tags != null) {
                  if (rule.tags.size() > 0) {
                    emit(1);
                  } else {
                    emit(0);
                  }
                }`,
          },
        },
        rule_snoozed: {
          type: 'long' as const,
          script: {
            source: `
                def rule = params._source['alert'];
                if (rule != null && rule.snoozeSchedule != null) {
                  if (rule.snoozeSchedule.size() > 0) {
                    emit(1);
                  } else {
                    emit(0);
                  }
                }`,
          },
        },
        rule_muted: {
          type: 'long' as const,
          script: {
            source: `
                if (doc['alert.muteAll'].value == true) {
                  emit(1);
                } else {
                  emit(0);
                }`,
          },
        },
        rule_with_muted_alerts: {
          type: 'long' as const,
          script: {
            source: `
                def rule = params._source['alert'];
                if (rule != null && rule.mutedInstanceIds != null) {
                  if (rule.mutedInstanceIds.size() > 0) {
                    emit(1);
                  } else {
                    emit(0);
                  }
                }`,
          },
        },
        rule_with_linked_dashboards: {
          type: 'long' as const,
          script: {
            source: `
               def rule = params._source['alert'];
                if (rule != null && rule.artifacts != null && rule.artifacts.dashboards != null) {
                  if (rule.artifacts.dashboards.size() > 0) {
                    emit(1);
                  } else {
                    emit(0);
                  }
                }`,
          },
        },
        rule_with_investigation_guide: {
          type: 'long' as const,
          script: {
            source: `
               def rule = params._source['alert'];
                if (rule != null && rule.artifacts != null && rule.artifacts.investigation_guide != null && rule.artifacts.investigation_guide.blob != null) {
                  if (rule.artifacts.investigation_guide.blob.trim() != '') {
                    emit(1);
                  } else {
                    emit(0);
                  }
                }`,
          },
        },
      },
      aggs: {
        by_rule_type_id: {
          terms: {
            field: 'alert.alertTypeId',
            size: NUM_ALERTING_RULE_TYPES,
          },
        },
        max_throttle_time: { max: { field: 'rule_throttle_interval' } },
        min_throttle_time: { min: { field: 'rule_throttle_interval' } },
        avg_throttle_time: { avg: { field: 'rule_throttle_interval' } },
        max_interval_time: { max: { field: 'rule_schedule_interval' } },
        min_interval_time: { min: { field: 'rule_schedule_interval' } },
        avg_interval_time: { avg: { field: 'rule_schedule_interval' } },
        max_actions_count: { max: { field: 'rule_action_count' } },
        min_actions_count: { min: { field: 'rule_action_count' } },
        avg_actions_count: { avg: { field: 'rule_action_count' } },
        by_execution_status: {
          terms: {
            field: 'alert.executionStatus.status',
          },
        },
        by_notify_when: {
          terms: {
            field: 'alert.notifyWhen',
          },
        },
        connector_types_by_consumers: {
          terms: {
            field: 'alert.consumer',
          },
          aggs: {
            actions: {
              nested: {
                path: 'alert.actions',
              },
              aggs: {
                connector_types: {
                  terms: {
                    field: 'alert.actions.actionTypeId',
                  },
                },
              },
            },
          },
        },
        by_search_type: {
          terms: {
            field: 'alert.params.searchType',
          },
        },
        sum_rules_with_tags: { sum: { field: 'rule_with_tags' } },
        sum_rules_snoozed: { sum: { field: 'rule_snoozed' } },
        sum_rules_muted: { sum: { field: 'rule_muted' } },
        sum_rules_with_muted_alerts: { sum: { field: 'rule_with_muted_alerts' } },
        sum_rules_with_linked_dashboards: { sum: { field: 'rule_with_linked_dashboards' } },
        sum_rules_with_investigation_guide: { sum: { field: 'rule_with_investigation_guide' } },
      },
    };

    logger.debug(() => `query for getTotalCountAggregations - ${JSON.stringify(query)}`);
    const results = await esClient.search(query);

    logger.debug(() => `results for getTotalCountAggregations query - ${JSON.stringify(results)}`);

    const aggregations = results.aggregations as {
      by_rule_type_id: AggregationsTermsAggregateBase<AggregationsStringTermsBucketKeys>;
      max_throttle_time: AggregationsSingleMetricAggregateBase;
      min_throttle_time: AggregationsSingleMetricAggregateBase;
      avg_throttle_time: AggregationsSingleMetricAggregateBase;
      max_interval_time: AggregationsSingleMetricAggregateBase;
      min_interval_time: AggregationsSingleMetricAggregateBase;
      avg_interval_time: AggregationsSingleMetricAggregateBase;
      max_actions_count: AggregationsSingleMetricAggregateBase;
      min_actions_count: AggregationsSingleMetricAggregateBase;
      avg_actions_count: AggregationsSingleMetricAggregateBase;
      by_execution_status: AggregationsTermsAggregateBase<AggregationsStringTermsBucketKeys>;
      by_notify_when: AggregationsTermsAggregateBase<AggregationsStringTermsBucketKeys>;
      connector_types_by_consumers: AggregationsTermsAggregateBase<ConnectorsByConsumersBucket>;
      by_search_type: AggregationsTermsAggregateBase<AggregationsStringTermsBucketKeys>;
      sum_rules_with_tags: AggregationsSingleMetricAggregateBase;
      sum_rules_snoozed: AggregationsSingleMetricAggregateBase;
      sum_rules_muted: AggregationsSingleMetricAggregateBase;
      sum_rules_with_muted_alerts: AggregationsSingleMetricAggregateBase;
      sum_rules_with_linked_dashboards: AggregationsSingleMetricAggregateBase;
      sum_rules_with_investigation_guide: AggregationsSingleMetricAggregateBase;
    };

    const totalRulesCount =
      typeof results.hits.total === 'number' ? results.hits.total : results.hits.total?.value;

    const countRulesByExecutionStatus = groupRulesByStatus(
      parseSimpleRuleTypeBucket(aggregations.by_execution_status.buckets)
    );

    const countRulesByNotifyWhen = groupRulesByNotifyWhen(
      parseSimpleRuleTypeBucket(aggregations.by_notify_when.buckets)
    );

    const countConnectorTypesByConsumers = groupConnectorsByConsumers(
      aggregations.connector_types_by_consumers.buckets
    );

    const countRulesBySearchType = groupRulesBySearchType(
      parseSimpleRuleTypeBucket(aggregations.by_search_type.buckets)
    );

    return {
      hasErrors: false,
      count_total: totalRulesCount ?? 0,
      count_by_type: {
        ...parseSimpleRuleTypeBucket(aggregations.by_rule_type_id.buckets),
        ...countRulesBySearchType,
      },
      count_rules_by_execution_status: countRulesByExecutionStatus,
      count_rules_with_tags: aggregations.sum_rules_with_tags.value ?? 0,
      count_rules_by_notify_when: countRulesByNotifyWhen,
      count_rules_snoozed: aggregations.sum_rules_snoozed.value ?? 0,
      count_rules_muted: aggregations.sum_rules_muted.value ?? 0,
      count_rules_with_muted_alerts: aggregations.sum_rules_with_muted_alerts.value ?? 0,
      count_rules_with_linked_dashboards: aggregations.sum_rules_with_linked_dashboards.value ?? 0,
      count_rules_with_investigation_guide:
        aggregations.sum_rules_with_investigation_guide.value ?? 0,
      count_connector_types_by_consumers: countConnectorTypesByConsumers,
      throttle_time: {
        min: `${aggregations.min_throttle_time.value ?? 0}s`,
        avg: `${aggregations.avg_throttle_time.value ?? 0}s`,
        max: `${aggregations.max_throttle_time.value ?? 0}s`,
      },
      schedule_time: {
        min: `${aggregations.min_interval_time.value ?? 0}s`,
        avg: `${aggregations.avg_interval_time.value ?? 0}s`,
        max: `${aggregations.max_interval_time.value ?? 0}s`,
      },
      throttle_time_number_s: {
        min: aggregations.min_throttle_time.value ?? 0,
        avg: aggregations.avg_throttle_time.value ?? 0,
        max: aggregations.max_throttle_time.value ?? 0,
      },
      schedule_time_number_s: {
        min: aggregations.min_interval_time.value ?? 0,
        avg: aggregations.avg_interval_time.value ?? 0,
        max: aggregations.max_interval_time.value ?? 0,
      },
      connectors_per_alert: {
        min: aggregations.min_actions_count.value ?? 0,
        avg: aggregations.avg_actions_count.value ?? 0,
        max: aggregations.max_actions_count.value ?? 0,
      },
    };
  } catch (err) {
    const errorMessage = parseAndLogError(err, `getTotalCountAggregations`, logger);

    return {
      hasErrors: true,
      errorMessage,
      count_total: 0,
      count_by_type: {},
      count_rules_by_execution_status: { success: 0, error: 0, warning: 0 },
      count_rules_by_notify_when: {
        on_throttle_interval: 0,
        on_active_alert: 0,
        on_action_group_change: 0,
      },
      count_rules_with_tags: 0,
      count_rules_snoozed: 0,
      count_rules_muted: 0,
      count_rules_with_muted_alerts: 0,
      count_rules_with_linked_dashboards: 0,
      count_rules_with_investigation_guide: 0,
      count_connector_types_by_consumers: {},
      throttle_time: {
        min: '0s',
        avg: '0s',
        max: '0s',
      },
      schedule_time: {
        min: '0s',
        avg: '0s',
        max: '0s',
      },
      throttle_time_number_s: {
        min: 0,
        avg: 0,
        max: 0,
      },
      schedule_time_number_s: {
        min: 0,
        avg: 0,
        max: 0,
      },
      connectors_per_alert: {
        min: 0,
        avg: 0,
        max: 0,
      },
    };
  }
}