Search in sources :

Example 1 with MultiResponsesDelegateActionListener

use of org.opensearch.ad.util.MultiResponsesDelegateActionListener in project anomaly-detection by opensearch-project.

the class StatsAnomalyDetectorTransportAction method getClusterStats.

/**
 * Make async request to get the number of detectors in AnomalyDetector.ANOMALY_DETECTORS_INDEX if necessary
 * and, onResponse, gather the cluster statistics
 *
 * @param client Client
 * @param listener MultiResponsesDelegateActionListener to be used once both requests complete
 * @param adStatsRequest Request containing stats to be retrieved
 */
private void getClusterStats(Client client, MultiResponsesDelegateActionListener<ADStatsResponse> listener, ADStatsRequest adStatsRequest) {
    ADStatsResponse adStatsResponse = new ADStatsResponse();
    if ((adStatsRequest.getStatsToBeRetrieved().contains(StatNames.DETECTOR_COUNT.getName()) || adStatsRequest.getStatsToBeRetrieved().contains(StatNames.SINGLE_ENTITY_DETECTOR_COUNT.getName()) || adStatsRequest.getStatsToBeRetrieved().contains(StatNames.MULTI_ENTITY_DETECTOR_COUNT.getName())) && clusterService.state().getRoutingTable().hasIndex(AnomalyDetector.ANOMALY_DETECTORS_INDEX)) {
        TermsAggregationBuilder termsAgg = AggregationBuilders.terms(DETECTOR_TYPE_AGG).field(AnomalyDetector.DETECTOR_TYPE_FIELD);
        SearchRequest request = new SearchRequest().indices(AnomalyDetector.ANOMALY_DETECTORS_INDEX).source(new SearchSourceBuilder().aggregation(termsAgg).size(0).trackTotalHits(true));
        client.search(request, ActionListener.wrap(r -> {
            StringTerms aggregation = r.getAggregations().get(DETECTOR_TYPE_AGG);
            List<StringTerms.Bucket> buckets = aggregation.getBuckets();
            long totalDetectors = r.getHits().getTotalHits().value;
            long totalSingleEntityDetectors = 0;
            long totalMultiEntityDetectors = 0;
            for (StringTerms.Bucket b : buckets) {
                if (AnomalyDetectorType.SINGLE_ENTITY.name().equals(b.getKeyAsString()) || AnomalyDetectorType.REALTIME_SINGLE_ENTITY.name().equals(b.getKeyAsString()) || AnomalyDetectorType.HISTORICAL_SINGLE_ENTITY.name().equals(b.getKeyAsString())) {
                    totalSingleEntityDetectors += b.getDocCount();
                }
                if (AnomalyDetectorType.MULTI_ENTITY.name().equals(b.getKeyAsString()) || AnomalyDetectorType.REALTIME_MULTI_ENTITY.name().equals(b.getKeyAsString()) || AnomalyDetectorType.HISTORICAL_MULTI_ENTITY.name().equals(b.getKeyAsString())) {
                    totalMultiEntityDetectors += b.getDocCount();
                }
            }
            if (adStatsRequest.getStatsToBeRetrieved().contains(StatNames.DETECTOR_COUNT.getName())) {
                adStats.getStat(StatNames.DETECTOR_COUNT.getName()).setValue(totalDetectors);
            }
            if (adStatsRequest.getStatsToBeRetrieved().contains(StatNames.SINGLE_ENTITY_DETECTOR_COUNT.getName())) {
                adStats.getStat(StatNames.SINGLE_ENTITY_DETECTOR_COUNT.getName()).setValue(totalSingleEntityDetectors);
            }
            if (adStatsRequest.getStatsToBeRetrieved().contains(StatNames.MULTI_ENTITY_DETECTOR_COUNT.getName())) {
                adStats.getStat(StatNames.MULTI_ENTITY_DETECTOR_COUNT.getName()).setValue(totalMultiEntityDetectors);
            }
            adStatsResponse.setClusterStats(getClusterStatsMap(adStatsRequest));
            listener.onResponse(adStatsResponse);
        }, e -> listener.onFailure(e)));
    } else {
        adStatsResponse.setClusterStats(getClusterStatsMap(adStatsRequest));
        listener.onResponse(adStatsResponse);
    }
}
Also used : HandledTransportAction(org.opensearch.action.support.HandledTransportAction) StringTerms(org.opensearch.search.aggregations.bucket.terms.StringTerms) ADStats(org.opensearch.ad.stats.ADStats) OpenSearchStatusException(org.opensearch.OpenSearchStatusException) HashMap(java.util.HashMap) ADStatsResponse(org.opensearch.ad.stats.ADStatsResponse) ThreadContext(org.opensearch.common.util.concurrent.ThreadContext) AnomalyDetectorType(org.opensearch.ad.model.AnomalyDetectorType) Map(java.util.Map) AnomalyDetector(org.opensearch.ad.model.AnomalyDetector) SearchRequest(org.opensearch.action.search.SearchRequest) Inject(org.opensearch.common.inject.Inject) ActionListener(org.opensearch.action.ActionListener) RestHandlerUtils.wrapRestActionListener(org.opensearch.ad.util.RestHandlerUtils.wrapRestActionListener) Client(org.opensearch.client.Client) Set(java.util.Set) Task(org.opensearch.tasks.Task) RestStatus(org.opensearch.rest.RestStatus) TransportService(org.opensearch.transport.TransportService) FAIL_TO_GET_STATS(org.opensearch.ad.constant.CommonErrorMessages.FAIL_TO_GET_STATS) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) ActionFilters(org.opensearch.action.support.ActionFilters) AggregationBuilders(org.opensearch.search.aggregations.AggregationBuilders) List(java.util.List) Logger(org.apache.logging.log4j.Logger) TermsAggregationBuilder(org.opensearch.search.aggregations.bucket.terms.TermsAggregationBuilder) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) ClusterService(org.opensearch.cluster.service.ClusterService) StatNames(org.opensearch.ad.stats.StatNames) LogManager(org.apache.logging.log4j.LogManager) SearchRequest(org.opensearch.action.search.SearchRequest) TermsAggregationBuilder(org.opensearch.search.aggregations.bucket.terms.TermsAggregationBuilder) StringTerms(org.opensearch.search.aggregations.bucket.terms.StringTerms) ADStatsResponse(org.opensearch.ad.stats.ADStatsResponse) List(java.util.List) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder)

Example 2 with MultiResponsesDelegateActionListener

use of org.opensearch.ad.util.MultiResponsesDelegateActionListener in project anomaly-detection by opensearch-project.

the class AbstractAnomalyDetectorActionHandler method validateAnomalyDetectorFeatures.

/**
 * Validate config/syntax, and runtime error of detector features
 * @param detectorId detector id
 * @param indexingDryRun if false, then will eventually index detector; true, skip indexing detector
 * @throws IOException when fail to parse feature aggregation
 */
// TODO: move this method to util class so that it can be re-usable for more use cases
// https://github.com/opensearch-project/anomaly-detection/issues/39
protected void validateAnomalyDetectorFeatures(String detectorId, boolean indexingDryRun) throws IOException {
    if (anomalyDetector != null && (anomalyDetector.getFeatureAttributes() == null || anomalyDetector.getFeatureAttributes().isEmpty())) {
        checkADNameExists(detectorId, indexingDryRun);
        return;
    }
    // checking configuration/syntax error of detector features
    String error = RestHandlerUtils.checkAnomalyDetectorFeaturesSyntax(anomalyDetector, maxAnomalyFeatures);
    if (StringUtils.isNotBlank(error)) {
        if (indexingDryRun) {
            listener.onFailure(new ADValidationException(error, DetectorValidationIssueType.FEATURE_ATTRIBUTES, ValidationAspect.DETECTOR));
            return;
        }
        listener.onFailure(new OpenSearchStatusException(error, RestStatus.BAD_REQUEST));
        return;
    }
    // checking runtime error from feature query
    ActionListener<MergeableList<Optional<double[]>>> validateFeatureQueriesListener = ActionListener.wrap(response -> {
        checkADNameExists(detectorId, indexingDryRun);
    }, exception -> {
        listener.onFailure(new ADValidationException(exception.getMessage(), DetectorValidationIssueType.FEATURE_ATTRIBUTES, ValidationAspect.DETECTOR));
    });
    MultiResponsesDelegateActionListener<MergeableList<Optional<double[]>>> multiFeatureQueriesResponseListener = new MultiResponsesDelegateActionListener<MergeableList<Optional<double[]>>>(validateFeatureQueriesListener, anomalyDetector.getFeatureAttributes().size(), String.format(Locale.ROOT, CommonErrorMessages.VALIDATION_FEATURE_FAILURE, anomalyDetector.getName()), false);
    for (Feature feature : anomalyDetector.getFeatureAttributes()) {
        SearchSourceBuilder ssb = new SearchSourceBuilder().size(1).query(QueryBuilders.matchAllQuery());
        AggregatorFactories.Builder internalAgg = parseAggregators(feature.getAggregation().toString(), xContentRegistry, feature.getId());
        ssb.aggregation(internalAgg.getAggregatorFactories().iterator().next());
        SearchRequest searchRequest = new SearchRequest().indices(anomalyDetector.getIndices().toArray(new String[0])).source(ssb);
        client.search(searchRequest, ActionListener.wrap(response -> {
            Optional<double[]> aggFeatureResult = searchFeatureDao.parseResponse(response, Arrays.asList(feature.getId()));
            if (aggFeatureResult.isPresent()) {
                multiFeatureQueriesResponseListener.onResponse(new MergeableList<Optional<double[]>>(new ArrayList<Optional<double[]>>(Arrays.asList(aggFeatureResult))));
            } else {
                String errorMessage = CommonErrorMessages.FEATURE_WITH_EMPTY_DATA_MSG + feature.getName();
                logger.error(errorMessage);
                multiFeatureQueriesResponseListener.onFailure(new OpenSearchStatusException(errorMessage, RestStatus.BAD_REQUEST));
            }
        }, e -> {
            String errorMessage;
            if (isExceptionCausedByInvalidQuery(e)) {
                errorMessage = CommonErrorMessages.FEATURE_WITH_INVALID_QUERY_MSG + feature.getName();
            } else {
                errorMessage = CommonErrorMessages.UNKNOWN_SEARCH_QUERY_EXCEPTION_MSG + feature.getName();
            }
            logger.error(errorMessage, e);
            multiFeatureQueriesResponseListener.onFailure(new OpenSearchStatusException(errorMessage, RestStatus.BAD_REQUEST, e));
        }));
    }
}
Also used : Arrays(java.util.Arrays) StringUtils(org.apache.commons.lang.StringUtils) ParseUtils.listEqualsWithoutConsideringOrder(org.opensearch.ad.util.ParseUtils.listEqualsWithoutConsideringOrder) IndexResponse(org.opensearch.action.index.IndexResponse) OpenSearchStatusException(org.opensearch.OpenSearchStatusException) FAIL_TO_FIND_DETECTOR_MSG(org.opensearch.ad.constant.CommonErrorMessages.FAIL_TO_FIND_DETECTOR_MSG) ThreadContext(org.opensearch.common.util.concurrent.ThreadContext) XContentParser(org.opensearch.common.xcontent.XContentParser) WriteRequest(org.opensearch.action.support.WriteRequest) Locale(java.util.Locale) Map(java.util.Map) ParseUtils.parseAggregators(org.opensearch.ad.util.ParseUtils.parseAggregators) XContentFactory(org.opensearch.common.xcontent.XContentFactory) ActionListener(org.opensearch.action.ActionListener) ActionResponse(org.opensearch.action.ActionResponse) GetResponse(org.opensearch.action.get.GetResponse) Client(org.opensearch.client.Client) NumericSetting(org.opensearch.ad.settings.NumericSetting) TimeValue(org.opensearch.common.unit.TimeValue) Feature(org.opensearch.ad.model.Feature) Set(java.util.Set) XContentParserUtils.ensureExpectedToken(org.opensearch.common.xcontent.XContentParserUtils.ensureExpectedToken) GetFieldMappingsRequest(org.opensearch.action.admin.indices.mapping.get.GetFieldMappingsRequest) ADTaskManager(org.opensearch.ad.task.ADTaskManager) Instant(java.time.Instant) RestStatus(org.opensearch.rest.RestStatus) Collectors(java.util.stream.Collectors) TransportService(org.opensearch.transport.TransportService) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) GetFieldMappingsAction(org.opensearch.action.admin.indices.mapping.get.GetFieldMappingsAction) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) List(java.util.List) Logger(org.apache.logging.log4j.Logger) QueryBuilder(org.opensearch.index.query.QueryBuilder) GetFieldMappingsResponse(org.opensearch.action.admin.indices.mapping.get.GetFieldMappingsResponse) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) SearchFeatureDao(org.opensearch.ad.feature.SearchFeatureDao) Optional(java.util.Optional) ReplicationResponse(org.opensearch.action.support.replication.ReplicationResponse) RestHandlerUtils(org.opensearch.ad.util.RestHandlerUtils) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) AggregatorFactories(org.opensearch.search.aggregations.AggregatorFactories) IndicesOptions(org.opensearch.action.support.IndicesOptions) ArrayList(java.util.ArrayList) XCONTENT_WITH_TYPE(org.opensearch.ad.util.RestHandlerUtils.XCONTENT_WITH_TYPE) HashSet(java.util.HashSet) IndexAnomalyDetectorResponse(org.opensearch.ad.transport.IndexAnomalyDetectorResponse) AnomalyDetector(org.opensearch.ad.model.AnomalyDetector) SearchRequest(org.opensearch.action.search.SearchRequest) SearchResponse(org.opensearch.action.search.SearchResponse) MergeableList(org.opensearch.ad.model.MergeableList) RestHandlerUtils.isExceptionCausedByInvalidQuery(org.opensearch.ad.util.RestHandlerUtils.isExceptionCausedByInvalidQuery) ValidationAspect(org.opensearch.ad.model.ValidationAspect) ValidateAnomalyDetectorResponse(org.opensearch.ad.transport.ValidateAnomalyDetectorResponse) HISTORICAL_DETECTOR_TASK_TYPES(org.opensearch.ad.model.ADTaskType.HISTORICAL_DETECTOR_TASK_TYPES) QueryBuilders(org.opensearch.index.query.QueryBuilders) RestValidateAnomalyDetectorAction(org.opensearch.ad.rest.RestValidateAnomalyDetectorAction) CommonName(org.opensearch.ad.constant.CommonName) ADValidationException(org.opensearch.ad.common.exception.ADValidationException) RestRequest(org.opensearch.rest.RestRequest) ANOMALY_DETECTORS_INDEX(org.opensearch.ad.model.AnomalyDetector.ANOMALY_DETECTORS_INDEX) GetRequest(org.opensearch.action.get.GetRequest) IOException(java.io.IOException) AnomalyDetectionIndices(org.opensearch.ad.indices.AnomalyDetectionIndices) CreateIndexResponse(org.opensearch.action.admin.indices.create.CreateIndexResponse) CommonErrorMessages(org.opensearch.ad.constant.CommonErrorMessages) User(org.opensearch.commons.authuser.User) DetectorValidationIssueType(org.opensearch.ad.model.DetectorValidationIssueType) NamedXContentRegistry(org.opensearch.common.xcontent.NamedXContentRegistry) ClusterService(org.opensearch.cluster.service.ClusterService) Clock(java.time.Clock) IndexRequest(org.opensearch.action.index.IndexRequest) LogManager(org.apache.logging.log4j.LogManager) SearchRequest(org.opensearch.action.search.SearchRequest) Optional(java.util.Optional) MergeableList(org.opensearch.ad.model.MergeableList) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) Feature(org.opensearch.ad.model.Feature) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) AggregatorFactories(org.opensearch.search.aggregations.AggregatorFactories) ADValidationException(org.opensearch.ad.common.exception.ADValidationException) OpenSearchStatusException(org.opensearch.OpenSearchStatusException)

Example 3 with MultiResponsesDelegateActionListener

use of org.opensearch.ad.util.MultiResponsesDelegateActionListener in project anomaly-detection by opensearch-project.

the class ModelValidationActionHandler method checkFeatureQueryDelegate.

private void checkFeatureQueryDelegate(long latestTime) throws IOException {
    ActionListener<MergeableList<double[]>> validateFeatureQueriesListener = ActionListener.wrap(response -> {
        windowDelayRecommendation(latestTime);
    }, exception -> {
        listener.onFailure(new ADValidationException(exception.getMessage(), DetectorValidationIssueType.FEATURE_ATTRIBUTES, ValidationAspect.MODEL));
    });
    MultiResponsesDelegateActionListener<MergeableList<double[]>> multiFeatureQueriesResponseListener = new MultiResponsesDelegateActionListener<>(validateFeatureQueriesListener, anomalyDetector.getFeatureAttributes().size(), CommonErrorMessages.FEATURE_QUERY_TOO_SPARSE, false);
    for (Feature feature : anomalyDetector.getFeatureAttributes()) {
        AggregationBuilder aggregation = getBucketAggregation(latestTime, (IntervalTimeConfiguration) anomalyDetector.getDetectionInterval());
        BoolQueryBuilder query = QueryBuilders.boolQuery().filter(anomalyDetector.getFilterQuery());
        List<String> featureFields = ParseUtils.getFieldNamesForFeature(feature, xContentRegistry);
        for (String featureField : featureFields) {
            query.filter(QueryBuilders.existsQuery(featureField));
        }
        SearchSourceBuilder searchSourceBuilder = getSearchSourceBuilder(query, aggregation);
        SearchRequest searchRequest = new SearchRequest(anomalyDetector.getIndices().toArray(new String[0])).source(searchSourceBuilder);
        client.search(searchRequest, ActionListener.wrap(response -> {
            Histogram aggregate = checkBucketResultErrors(response);
            if (aggregate == null) {
                return;
            }
            double fullBucketRate = processBucketAggregationResults(aggregate);
            if (fullBucketRate < CONFIG_BUCKET_MINIMUM_SUCCESS_RATE) {
                multiFeatureQueriesResponseListener.onFailure(new ADValidationException(CommonErrorMessages.FEATURE_QUERY_TOO_SPARSE, DetectorValidationIssueType.FEATURE_ATTRIBUTES, ValidationAspect.MODEL));
            } else {
                multiFeatureQueriesResponseListener.onResponse(new MergeableList<>(new ArrayList<>(Collections.singletonList(new double[] { fullBucketRate }))));
            }
        }, e -> {
            logger.error(e);
            multiFeatureQueriesResponseListener.onFailure(new OpenSearchStatusException(CommonErrorMessages.FEATURE_QUERY_TOO_SPARSE, RestStatus.BAD_REQUEST, e));
        }));
    }
}
Also used : TOP_VALIDATE_TIMEOUT_IN_MILLIS(org.opensearch.ad.settings.AnomalyDetectorSettings.TOP_VALIDATE_TIMEOUT_IN_MILLIS) INTERVAL_RECOMMENDATION_DECREASING_MULTIPLIER(org.opensearch.ad.settings.AnomalyDetectorSettings.INTERVAL_RECOMMENDATION_DECREASING_MULTIPLIER) OpenSearchStatusException(org.opensearch.OpenSearchStatusException) TimeConfiguration(org.opensearch.ad.model.TimeConfiguration) MAX_INTERVAL_REC_LENGTH_IN_MINUTES(org.opensearch.ad.settings.AnomalyDetectorSettings.MAX_INTERVAL_REC_LENGTH_IN_MINUTES) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) FieldSortBuilder(org.opensearch.search.sort.FieldSortBuilder) Locale(java.util.Locale) Duration(java.time.Duration) Map(java.util.Map) ActionListener(org.opensearch.action.ActionListener) Client(org.opensearch.client.Client) TimeValue(org.opensearch.common.unit.TimeValue) Feature(org.opensearch.ad.model.Feature) MultiBucketsAggregation(org.opensearch.search.aggregations.bucket.MultiBucketsAggregation) CONFIG_BUCKET_MINIMUM_SUCCESS_RATE(org.opensearch.ad.settings.AnomalyDetectorSettings.CONFIG_BUCKET_MINIMUM_SUCCESS_RATE) Instant(java.time.Instant) RestStatus(org.opensearch.rest.RestStatus) Terms(org.opensearch.search.aggregations.bucket.terms.Terms) Collectors(java.util.stream.Collectors) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) List(java.util.List) Logger(org.apache.logging.log4j.Logger) QueryBuilder(org.opensearch.index.query.QueryBuilder) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) SearchFeatureDao(org.opensearch.ad.feature.SearchFeatureDao) Optional(java.util.Optional) TermsValuesSourceBuilder(org.opensearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) MAX_TIMES_DECREASING_INTERVAL(org.opensearch.ad.settings.AnomalyDetectorSettings.MAX_TIMES_DECREASING_INTERVAL) BucketOrder(org.opensearch.search.aggregations.BucketOrder) HashMap(java.util.HashMap) Aggregations(org.opensearch.search.aggregations.Aggregations) DateHistogramInterval(org.opensearch.search.aggregations.bucket.histogram.DateHistogramInterval) AnomalyDetectorSettings(org.opensearch.ad.settings.AnomalyDetectorSettings) INTERVAL_RECOMMENDATION_INCREASING_MULTIPLIER(org.opensearch.ad.settings.AnomalyDetectorSettings.INTERVAL_RECOMMENDATION_INCREASING_MULTIPLIER) INTERVAL_BUCKET_MINIMUM_SUCCESS_RATE(org.opensearch.ad.settings.AnomalyDetectorSettings.INTERVAL_BUCKET_MINIMUM_SUCCESS_RATE) ArrayList(java.util.ArrayList) LongBounds(org.opensearch.search.aggregations.bucket.histogram.LongBounds) SortOrder(org.opensearch.search.sort.SortOrder) AnomalyDetector(org.opensearch.ad.model.AnomalyDetector) SearchRequest(org.opensearch.action.search.SearchRequest) SearchResponse(org.opensearch.action.search.SearchResponse) MergeableList(org.opensearch.ad.model.MergeableList) EndRunException(org.opensearch.ad.common.exception.EndRunException) ValidationAspect(org.opensearch.ad.model.ValidationAspect) ValidateAnomalyDetectorResponse(org.opensearch.ad.transport.ValidateAnomalyDetectorResponse) QueryBuilders(org.opensearch.index.query.QueryBuilders) RangeQueryBuilder(org.opensearch.index.query.RangeQueryBuilder) ADValidationException(org.opensearch.ad.common.exception.ADValidationException) IOException(java.io.IOException) PipelineAggregatorBuilders(org.opensearch.search.aggregations.PipelineAggregatorBuilders) CompositeAggregation(org.opensearch.search.aggregations.bucket.composite.CompositeAggregation) AggregationBuilders(org.opensearch.search.aggregations.AggregationBuilders) CommonErrorMessages(org.opensearch.ad.constant.CommonErrorMessages) ChronoUnit(java.time.temporal.ChronoUnit) DetectorValidationIssueType(org.opensearch.ad.model.DetectorValidationIssueType) NamedXContentRegistry(org.opensearch.common.xcontent.NamedXContentRegistry) ClusterService(org.opensearch.cluster.service.ClusterService) Clock(java.time.Clock) Comparator(java.util.Comparator) IntervalTimeConfiguration(org.opensearch.ad.model.IntervalTimeConfiguration) Collections(java.util.Collections) LogManager(org.apache.logging.log4j.LogManager) Histogram(org.opensearch.search.aggregations.bucket.histogram.Histogram) ParseUtils(org.opensearch.ad.util.ParseUtils) SearchRequest(org.opensearch.action.search.SearchRequest) Histogram(org.opensearch.search.aggregations.bucket.histogram.Histogram) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) MergeableList(org.opensearch.ad.model.MergeableList) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) Feature(org.opensearch.ad.model.Feature) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) ADValidationException(org.opensearch.ad.common.exception.ADValidationException) OpenSearchStatusException(org.opensearch.OpenSearchStatusException)

Example 4 with MultiResponsesDelegateActionListener

use of org.opensearch.ad.util.MultiResponsesDelegateActionListener in project anomaly-detection by opensearch-project.

the class AnomalyDetectorProfileRunner method profileEntityStats.

private void profileEntityStats(MultiResponsesDelegateActionListener<DetectorProfile> listener, AnomalyDetector detector) {
    List<String> categoryField = detector.getCategoryField();
    if (!detector.isMultientityDetector() || categoryField.size() > NumericSetting.maxCategoricalFields()) {
        listener.onResponse(new DetectorProfile.Builder().build());
    } else {
        if (categoryField.size() == 1) {
            // Run a cardinality aggregation to count the cardinality of single category fields
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            CardinalityAggregationBuilder aggBuilder = new CardinalityAggregationBuilder(CommonName.TOTAL_ENTITIES);
            aggBuilder.field(categoryField.get(0));
            searchSourceBuilder.aggregation(aggBuilder);
            SearchRequest request = new SearchRequest(detector.getIndices().toArray(new String[0]), searchSourceBuilder);
            client.search(request, ActionListener.wrap(searchResponse -> {
                Map<String, Aggregation> aggMap = searchResponse.getAggregations().asMap();
                InternalCardinality totalEntities = (InternalCardinality) aggMap.get(CommonName.TOTAL_ENTITIES);
                long value = totalEntities.getValue();
                DetectorProfile.Builder profileBuilder = new DetectorProfile.Builder();
                DetectorProfile profile = profileBuilder.totalEntities(value).build();
                listener.onResponse(profile);
            }, searchException -> {
                logger.warn(CommonErrorMessages.FAIL_TO_GET_TOTAL_ENTITIES + detector.getDetectorId());
                listener.onFailure(searchException);
            }));
        } else {
            // Run a composite query and count the number of buckets to decide cardinality of multiple category fields
            AggregationBuilder bucketAggs = AggregationBuilders.composite(CommonName.TOTAL_ENTITIES, detector.getCategoryField().stream().map(f -> new TermsValuesSourceBuilder(f).field(f)).collect(Collectors.toList())).size(maxTotalEntitiesToTrack);
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().aggregation(bucketAggs).trackTotalHits(false).size(0);
            SearchRequest searchRequest = new SearchRequest().indices(detector.getIndices().toArray(new String[0])).source(searchSourceBuilder);
            client.search(searchRequest, ActionListener.wrap(searchResponse -> {
                DetectorProfile.Builder profileBuilder = new DetectorProfile.Builder();
                Aggregations aggs = searchResponse.getAggregations();
                if (aggs == null) {
                    // This would indicate some bug or some opensearch core changes that we are not aware of (we don't keep up-to-date
                    // with
                    // the large amounts of changes there). For example, they may change to if there are results return it; otherwise
                    // return
                    // null instead of an empty Aggregations as they currently do.
                    logger.warn("Unexpected null aggregation.");
                    listener.onResponse(profileBuilder.totalEntities(0L).build());
                    return;
                }
                Aggregation aggrResult = aggs.get(CommonName.TOTAL_ENTITIES);
                if (aggrResult == null) {
                    listener.onFailure(new IllegalArgumentException("Fail to find valid aggregation result"));
                    return;
                }
                CompositeAggregation compositeAgg = (CompositeAggregation) aggrResult;
                DetectorProfile profile = profileBuilder.totalEntities(Long.valueOf(compositeAgg.getBuckets().size())).build();
                listener.onResponse(profile);
            }, searchException -> {
                logger.warn(CommonErrorMessages.FAIL_TO_GET_TOTAL_ENTITIES + detector.getDetectorId());
                listener.onFailure(searchException);
            }));
        }
    }
}
Also used : Aggregation(org.opensearch.search.aggregations.Aggregation) ResourceNotFoundException(org.opensearch.ad.common.exception.ResourceNotFoundException) OpenSearchStatusException(org.opensearch.OpenSearchStatusException) FAIL_TO_FIND_DETECTOR_MSG(org.opensearch.ad.constant.CommonErrorMessages.FAIL_TO_FIND_DETECTOR_MSG) XContentParser(org.opensearch.common.xcontent.XContentParser) DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) Throwables(org.apache.logging.log4j.core.util.Throwables) ANOMALY_DETECTOR_JOB_INDEX(org.opensearch.ad.model.AnomalyDetectorJob.ANOMALY_DETECTOR_JOB_INDEX) Map(java.util.Map) RCFPollingAction(org.opensearch.ad.transport.RCFPollingAction) ActionListener(org.opensearch.action.ActionListener) DetectorProfile(org.opensearch.ad.model.DetectorProfile) Client(org.opensearch.client.Client) NumericSetting(org.opensearch.ad.settings.NumericSetting) LoggingDeprecationHandler(org.opensearch.common.xcontent.LoggingDeprecationHandler) Set(java.util.Set) ADTaskType(org.opensearch.ad.model.ADTaskType) XContentParserUtils.ensureExpectedToken(org.opensearch.common.xcontent.XContentParserUtils.ensureExpectedToken) ADTaskManager(org.opensearch.ad.task.ADTaskManager) Collectors(java.util.stream.Collectors) TransportService(org.opensearch.transport.TransportService) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) List(java.util.List) Logger(org.apache.logging.log4j.Logger) AnomalyResult(org.opensearch.ad.model.AnomalyResult) ExceptionUtil(org.opensearch.ad.util.ExceptionUtil) CardinalityAggregationBuilder(org.opensearch.search.aggregations.metrics.CardinalityAggregationBuilder) DetectorState(org.opensearch.ad.model.DetectorState) INTERNAL_SERVER_ERROR(org.opensearch.rest.RestStatus.INTERNAL_SERVER_ERROR) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) XContentType(org.opensearch.common.xcontent.XContentType) TermsValuesSourceBuilder(org.opensearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) DiscoveryNodeFilterer(org.opensearch.ad.util.DiscoveryNodeFilterer) Aggregations(org.opensearch.search.aggregations.Aggregations) SearchHits(org.opensearch.search.SearchHits) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) AnomalyDetectorSettings(org.opensearch.ad.settings.AnomalyDetectorSettings) ProfileRequest(org.opensearch.ad.transport.ProfileRequest) AnomalyDetector(org.opensearch.ad.model.AnomalyDetector) SearchRequest(org.opensearch.action.search.SearchRequest) SearchResponse(org.opensearch.action.search.SearchResponse) InternalCardinality(org.opensearch.search.aggregations.metrics.InternalCardinality) ProfileResponse(org.opensearch.ad.transport.ProfileResponse) QueryBuilders(org.opensearch.index.query.QueryBuilders) CommonName(org.opensearch.ad.constant.CommonName) InitProgressProfile(org.opensearch.ad.model.InitProgressProfile) ANOMALY_DETECTORS_INDEX(org.opensearch.ad.model.AnomalyDetector.ANOMALY_DETECTORS_INDEX) GetRequest(org.opensearch.action.get.GetRequest) NotSerializedADExceptionName(org.opensearch.ad.common.exception.NotSerializedADExceptionName) DetectorProfileName(org.opensearch.ad.model.DetectorProfileName) CompositeAggregation(org.opensearch.search.aggregations.bucket.composite.CompositeAggregation) RCFPollingResponse(org.opensearch.ad.transport.RCFPollingResponse) AggregationBuilders(org.opensearch.search.aggregations.AggregationBuilders) FAIL_TO_PARSE_DETECTOR_MSG(org.opensearch.ad.constant.CommonErrorMessages.FAIL_TO_PARSE_DETECTOR_MSG) CommonErrorMessages(org.opensearch.ad.constant.CommonErrorMessages) RCFPollingRequest(org.opensearch.ad.transport.RCFPollingRequest) AnomalyDetectorJob(org.opensearch.ad.model.AnomalyDetectorJob) NamedXContentRegistry(org.opensearch.common.xcontent.NamedXContentRegistry) IntervalTimeConfiguration(org.opensearch.ad.model.IntervalTimeConfiguration) LogManager(org.apache.logging.log4j.LogManager) BAD_REQUEST(org.opensearch.rest.RestStatus.BAD_REQUEST) ProfileAction(org.opensearch.ad.transport.ProfileAction) SearchRequest(org.opensearch.action.search.SearchRequest) CompositeAggregation(org.opensearch.search.aggregations.bucket.composite.CompositeAggregation) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) CardinalityAggregationBuilder(org.opensearch.search.aggregations.metrics.CardinalityAggregationBuilder) Aggregations(org.opensearch.search.aggregations.Aggregations) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) CardinalityAggregationBuilder(org.opensearch.search.aggregations.metrics.CardinalityAggregationBuilder) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) TermsValuesSourceBuilder(org.opensearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) DetectorProfile(org.opensearch.ad.model.DetectorProfile) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) Aggregation(org.opensearch.search.aggregations.Aggregation) CompositeAggregation(org.opensearch.search.aggregations.bucket.composite.CompositeAggregation) TermsValuesSourceBuilder(org.opensearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder) CardinalityAggregationBuilder(org.opensearch.search.aggregations.metrics.CardinalityAggregationBuilder) InternalCardinality(org.opensearch.search.aggregations.metrics.InternalCardinality) Map(java.util.Map)

Example 5 with MultiResponsesDelegateActionListener

use of org.opensearch.ad.util.MultiResponsesDelegateActionListener in project anomaly-detection by opensearch-project.

the class AnomalyDetectorProfileRunner method prepareProfile.

private void prepareProfile(AnomalyDetector detector, ActionListener<DetectorProfile> listener, Set<DetectorProfileName> profilesToCollect) {
    String detectorId = detector.getDetectorId();
    GetRequest getRequest = new GetRequest(ANOMALY_DETECTOR_JOB_INDEX, detectorId);
    client.get(getRequest, ActionListener.wrap(getResponse -> {
        if (getResponse != null && getResponse.isExists()) {
            try (XContentParser parser = XContentType.JSON.xContent().createParser(xContentRegistry, LoggingDeprecationHandler.INSTANCE, getResponse.getSourceAsString())) {
                ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.nextToken(), parser);
                AnomalyDetectorJob job = AnomalyDetectorJob.parse(parser);
                long enabledTimeMs = job.getEnabledTime().toEpochMilli();
                boolean isMultiEntityDetector = detector.isMultientityDetector();
                int totalResponsesToWait = 0;
                if (profilesToCollect.contains(DetectorProfileName.ERROR)) {
                    totalResponsesToWait++;
                }
                // when to consolidate results and return to users
                if (isMultiEntityDetector) {
                    if (profilesToCollect.contains(DetectorProfileName.TOTAL_ENTITIES)) {
                        totalResponsesToWait++;
                    }
                    if (profilesToCollect.contains(DetectorProfileName.COORDINATING_NODE) || profilesToCollect.contains(DetectorProfileName.SHINGLE_SIZE) || profilesToCollect.contains(DetectorProfileName.TOTAL_SIZE_IN_BYTES) || profilesToCollect.contains(DetectorProfileName.MODELS) || profilesToCollect.contains(DetectorProfileName.ACTIVE_ENTITIES) || profilesToCollect.contains(DetectorProfileName.INIT_PROGRESS) || profilesToCollect.contains(DetectorProfileName.STATE)) {
                        totalResponsesToWait++;
                    }
                    if (profilesToCollect.contains(DetectorProfileName.AD_TASK)) {
                        totalResponsesToWait++;
                    }
                } else {
                    if (profilesToCollect.contains(DetectorProfileName.STATE) || profilesToCollect.contains(DetectorProfileName.INIT_PROGRESS)) {
                        totalResponsesToWait++;
                    }
                    if (profilesToCollect.contains(DetectorProfileName.COORDINATING_NODE) || profilesToCollect.contains(DetectorProfileName.SHINGLE_SIZE) || profilesToCollect.contains(DetectorProfileName.TOTAL_SIZE_IN_BYTES) || profilesToCollect.contains(DetectorProfileName.MODELS)) {
                        totalResponsesToWait++;
                    }
                    if (profilesToCollect.contains(DetectorProfileName.AD_TASK)) {
                        totalResponsesToWait++;
                    }
                }
                MultiResponsesDelegateActionListener<DetectorProfile> delegateListener = new MultiResponsesDelegateActionListener<DetectorProfile>(listener, totalResponsesToWait, CommonErrorMessages.FAIL_FETCH_ERR_MSG + detectorId, false);
                if (profilesToCollect.contains(DetectorProfileName.ERROR)) {
                    adTaskManager.getAndExecuteOnLatestDetectorLevelTask(detectorId, ADTaskType.REALTIME_TASK_TYPES, adTask -> {
                        DetectorProfile.Builder profileBuilder = new DetectorProfile.Builder();
                        if (adTask.isPresent()) {
                            long lastUpdateTimeMs = adTask.get().getLastUpdateTime().toEpochMilli();
                            // is enabled.
                            if (lastUpdateTimeMs > enabledTimeMs && adTask.get().getError() != null) {
                                profileBuilder.error(adTask.get().getError());
                            }
                            delegateListener.onResponse(profileBuilder.build());
                        } else {
                            // detector state for this detector does not exist
                            delegateListener.onResponse(profileBuilder.build());
                        }
                    }, transportService, false, delegateListener);
                }
                // when to consolidate results and return to users
                if (isMultiEntityDetector) {
                    if (profilesToCollect.contains(DetectorProfileName.TOTAL_ENTITIES)) {
                        profileEntityStats(delegateListener, detector);
                    }
                    if (profilesToCollect.contains(DetectorProfileName.COORDINATING_NODE) || profilesToCollect.contains(DetectorProfileName.SHINGLE_SIZE) || profilesToCollect.contains(DetectorProfileName.TOTAL_SIZE_IN_BYTES) || profilesToCollect.contains(DetectorProfileName.MODELS) || profilesToCollect.contains(DetectorProfileName.ACTIVE_ENTITIES) || profilesToCollect.contains(DetectorProfileName.INIT_PROGRESS) || profilesToCollect.contains(DetectorProfileName.STATE)) {
                        profileModels(detector, profilesToCollect, job, true, delegateListener);
                    }
                    if (profilesToCollect.contains(DetectorProfileName.AD_TASK)) {
                        adTaskManager.getLatestHistoricalTaskProfile(detectorId, transportService, null, delegateListener);
                    }
                } else {
                    if (profilesToCollect.contains(DetectorProfileName.STATE) || profilesToCollect.contains(DetectorProfileName.INIT_PROGRESS)) {
                        profileStateRelated(detector, delegateListener, job.isEnabled(), profilesToCollect);
                    }
                    if (profilesToCollect.contains(DetectorProfileName.COORDINATING_NODE) || profilesToCollect.contains(DetectorProfileName.SHINGLE_SIZE) || profilesToCollect.contains(DetectorProfileName.TOTAL_SIZE_IN_BYTES) || profilesToCollect.contains(DetectorProfileName.MODELS)) {
                        profileModels(detector, profilesToCollect, job, false, delegateListener);
                    }
                    if (profilesToCollect.contains(DetectorProfileName.AD_TASK)) {
                        adTaskManager.getLatestHistoricalTaskProfile(detectorId, transportService, null, delegateListener);
                    }
                }
            } catch (Exception e) {
                logger.error(CommonErrorMessages.FAIL_TO_GET_PROFILE_MSG, e);
                listener.onFailure(e);
            }
        } else {
            onGetDetectorForPrepare(detectorId, listener, profilesToCollect);
        }
    }, exception -> {
        if (ExceptionUtil.isIndexNotAvailable(exception)) {
            logger.info(exception.getMessage());
            onGetDetectorForPrepare(detectorId, listener, profilesToCollect);
        } else {
            logger.error(CommonErrorMessages.FAIL_TO_GET_PROFILE_MSG + detectorId);
            listener.onFailure(exception);
        }
    }));
}
Also used : Aggregation(org.opensearch.search.aggregations.Aggregation) ResourceNotFoundException(org.opensearch.ad.common.exception.ResourceNotFoundException) OpenSearchStatusException(org.opensearch.OpenSearchStatusException) FAIL_TO_FIND_DETECTOR_MSG(org.opensearch.ad.constant.CommonErrorMessages.FAIL_TO_FIND_DETECTOR_MSG) XContentParser(org.opensearch.common.xcontent.XContentParser) DiscoveryNode(org.opensearch.cluster.node.DiscoveryNode) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) Throwables(org.apache.logging.log4j.core.util.Throwables) ANOMALY_DETECTOR_JOB_INDEX(org.opensearch.ad.model.AnomalyDetectorJob.ANOMALY_DETECTOR_JOB_INDEX) Map(java.util.Map) RCFPollingAction(org.opensearch.ad.transport.RCFPollingAction) ActionListener(org.opensearch.action.ActionListener) DetectorProfile(org.opensearch.ad.model.DetectorProfile) Client(org.opensearch.client.Client) NumericSetting(org.opensearch.ad.settings.NumericSetting) LoggingDeprecationHandler(org.opensearch.common.xcontent.LoggingDeprecationHandler) Set(java.util.Set) ADTaskType(org.opensearch.ad.model.ADTaskType) XContentParserUtils.ensureExpectedToken(org.opensearch.common.xcontent.XContentParserUtils.ensureExpectedToken) ADTaskManager(org.opensearch.ad.task.ADTaskManager) Collectors(java.util.stream.Collectors) TransportService(org.opensearch.transport.TransportService) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) List(java.util.List) Logger(org.apache.logging.log4j.Logger) AnomalyResult(org.opensearch.ad.model.AnomalyResult) ExceptionUtil(org.opensearch.ad.util.ExceptionUtil) CardinalityAggregationBuilder(org.opensearch.search.aggregations.metrics.CardinalityAggregationBuilder) DetectorState(org.opensearch.ad.model.DetectorState) INTERNAL_SERVER_ERROR(org.opensearch.rest.RestStatus.INTERNAL_SERVER_ERROR) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) XContentType(org.opensearch.common.xcontent.XContentType) TermsValuesSourceBuilder(org.opensearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) DiscoveryNodeFilterer(org.opensearch.ad.util.DiscoveryNodeFilterer) Aggregations(org.opensearch.search.aggregations.Aggregations) SearchHits(org.opensearch.search.SearchHits) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) AnomalyDetectorSettings(org.opensearch.ad.settings.AnomalyDetectorSettings) ProfileRequest(org.opensearch.ad.transport.ProfileRequest) AnomalyDetector(org.opensearch.ad.model.AnomalyDetector) SearchRequest(org.opensearch.action.search.SearchRequest) SearchResponse(org.opensearch.action.search.SearchResponse) InternalCardinality(org.opensearch.search.aggregations.metrics.InternalCardinality) ProfileResponse(org.opensearch.ad.transport.ProfileResponse) QueryBuilders(org.opensearch.index.query.QueryBuilders) CommonName(org.opensearch.ad.constant.CommonName) InitProgressProfile(org.opensearch.ad.model.InitProgressProfile) ANOMALY_DETECTORS_INDEX(org.opensearch.ad.model.AnomalyDetector.ANOMALY_DETECTORS_INDEX) GetRequest(org.opensearch.action.get.GetRequest) NotSerializedADExceptionName(org.opensearch.ad.common.exception.NotSerializedADExceptionName) DetectorProfileName(org.opensearch.ad.model.DetectorProfileName) CompositeAggregation(org.opensearch.search.aggregations.bucket.composite.CompositeAggregation) RCFPollingResponse(org.opensearch.ad.transport.RCFPollingResponse) AggregationBuilders(org.opensearch.search.aggregations.AggregationBuilders) FAIL_TO_PARSE_DETECTOR_MSG(org.opensearch.ad.constant.CommonErrorMessages.FAIL_TO_PARSE_DETECTOR_MSG) CommonErrorMessages(org.opensearch.ad.constant.CommonErrorMessages) RCFPollingRequest(org.opensearch.ad.transport.RCFPollingRequest) AnomalyDetectorJob(org.opensearch.ad.model.AnomalyDetectorJob) NamedXContentRegistry(org.opensearch.common.xcontent.NamedXContentRegistry) IntervalTimeConfiguration(org.opensearch.ad.model.IntervalTimeConfiguration) LogManager(org.apache.logging.log4j.LogManager) BAD_REQUEST(org.opensearch.rest.RestStatus.BAD_REQUEST) ProfileAction(org.opensearch.ad.transport.ProfileAction) GetRequest(org.opensearch.action.get.GetRequest) AggregationBuilder(org.opensearch.search.aggregations.AggregationBuilder) CardinalityAggregationBuilder(org.opensearch.search.aggregations.metrics.CardinalityAggregationBuilder) SearchSourceBuilder(org.opensearch.search.builder.SearchSourceBuilder) TermsValuesSourceBuilder(org.opensearch.search.aggregations.bucket.composite.TermsValuesSourceBuilder) BoolQueryBuilder(org.opensearch.index.query.BoolQueryBuilder) MultiResponsesDelegateActionListener(org.opensearch.ad.util.MultiResponsesDelegateActionListener) AnomalyDetectorJob(org.opensearch.ad.model.AnomalyDetectorJob) DetectorProfile(org.opensearch.ad.model.DetectorProfile) XContentParser(org.opensearch.common.xcontent.XContentParser) ResourceNotFoundException(org.opensearch.ad.common.exception.ResourceNotFoundException) OpenSearchStatusException(org.opensearch.OpenSearchStatusException)

Aggregations

List (java.util.List)7 Map (java.util.Map)7 LogManager (org.apache.logging.log4j.LogManager)7 Logger (org.apache.logging.log4j.Logger)7 ActionListener (org.opensearch.action.ActionListener)7 AnomalyDetector (org.opensearch.ad.model.AnomalyDetector)7 MultiResponsesDelegateActionListener (org.opensearch.ad.util.MultiResponsesDelegateActionListener)7 SearchRequest (org.opensearch.action.search.SearchRequest)6 Client (org.opensearch.client.Client)6 SearchSourceBuilder (org.opensearch.search.builder.SearchSourceBuilder)6 Set (java.util.Set)5 Collectors (java.util.stream.Collectors)5 OpenSearchStatusException (org.opensearch.OpenSearchStatusException)5 CommonErrorMessages (org.opensearch.ad.constant.CommonErrorMessages)5 NamedXContentRegistry (org.opensearch.common.xcontent.NamedXContentRegistry)5 BoolQueryBuilder (org.opensearch.index.query.BoolQueryBuilder)5 QueryBuilders (org.opensearch.index.query.QueryBuilders)5 AggregationBuilders (org.opensearch.search.aggregations.AggregationBuilders)5 SearchResponse (org.opensearch.action.search.SearchResponse)4 AnomalyResult (org.opensearch.ad.model.AnomalyResult)4