io.camunda.operate.webapp.opensearch.reader.OpensearchFlowNodeStatisticsReader Maven / Gradle / Ivy
The newest version!
/*
* Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH under
* one or more contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright ownership.
* Licensed under the Camunda License 1.0. You may not use this file
* except in compliance with the Camunda License 1.0.
*/
package io.camunda.operate.webapp.opensearch.reader;
import static io.camunda.operate.schema.templates.ListViewTemplate.ACTIVITIES_JOIN_RELATION;
import static io.camunda.operate.schema.templates.ListViewTemplate.ACTIVITY_ID;
import static io.camunda.operate.schema.templates.ListViewTemplate.ACTIVITY_STATE;
import static io.camunda.operate.schema.templates.ListViewTemplate.ACTIVITY_TYPE;
import static io.camunda.operate.schema.templates.ListViewTemplate.INCIDENT;
import static io.camunda.operate.store.opensearch.client.sync.OpenSearchDocumentOperations.TERMS_AGG_SIZE;
import static io.camunda.operate.store.opensearch.dsl.AggregationDSL.children;
import static io.camunda.operate.store.opensearch.dsl.AggregationDSL.parent;
import static io.camunda.operate.store.opensearch.dsl.AggregationDSL.termAggregation;
import static io.camunda.operate.store.opensearch.dsl.AggregationDSL.withSubaggregations;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.and;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.constantScore;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.term;
import static io.camunda.operate.store.opensearch.dsl.QueryDSL.withTenantCheck;
import static io.camunda.operate.store.opensearch.dsl.RequestDSL.searchRequestBuilder;
import io.camunda.operate.conditions.OpensearchCondition;
import io.camunda.operate.entities.FlowNodeState;
import io.camunda.operate.entities.FlowNodeType;
import io.camunda.operate.schema.templates.ListViewTemplate;
import io.camunda.operate.store.opensearch.client.sync.RichOpenSearchClient;
import io.camunda.operate.store.opensearch.dsl.RequestDSL;
import io.camunda.operate.util.CollectionUtil;
import io.camunda.operate.util.Convertable;
import io.camunda.operate.util.MapPath;
import io.camunda.operate.webapp.opensearch.OpenSearchQueryHelper;
import io.camunda.operate.webapp.reader.FlowNodeStatisticsReader;
import io.camunda.operate.webapp.rest.dto.FlowNodeStatisticsDto;
import io.camunda.operate.webapp.rest.dto.listview.ListViewQueryDto;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.opensearch.client.opensearch._types.aggregations.Aggregation;
import org.opensearch.client.opensearch.core.SearchRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Conditional(OpensearchCondition.class)
@Component
public class OpensearchFlowNodeStatisticsReader implements FlowNodeStatisticsReader {
@Autowired private ListViewTemplate listViewTemplate;
@Autowired private OpenSearchQueryHelper openSearchQueryHelper;
@Autowired private RichOpenSearchClient richOpenSearchClient;
@Override
public Collection getFlowNodeStatistics(ListViewQueryDto query) {
final SearchRequest.Builder searchRequest;
if (!query.isFinished()) {
searchRequest = createQuery(query, RequestDSL.QueryType.ONLY_RUNTIME);
} else {
searchRequest = createQuery(query, RequestDSL.QueryType.ALL);
}
final Map statisticsMap = runQueryAndCollectStats(searchRequest);
return statisticsMap.values();
}
private SearchRequest.Builder createQuery(
ListViewQueryDto query, RequestDSL.QueryType queryType) {
final Map subAggregations = new HashMap<>();
if (query.isActive()) {
subAggregations.put(AGG_ACTIVE_ACTIVITIES, getActiveFlowNodesAggregation());
}
if (query.isCanceled()) {
subAggregations.put(AGG_TERMINATED_ACTIVITIES, getTerminatedActivitiesAggregation());
}
if (query.isIncidents()) {
subAggregations.put(AGG_INCIDENT_ACTIVITIES, getIncidentActivitiesAggregation());
}
subAggregations.put(AGG_FINISHED_ACTIVITIES, getFinishedActivitiesAggregation());
return searchRequestBuilder(listViewTemplate, queryType)
.query(
withTenantCheck(
constantScore(openSearchQueryHelper.createQueryFragment(query, queryType))))
.size(0)
.aggregations(
AGG_ACTIVITIES,
withSubaggregations(children(ACTIVITIES_JOIN_RELATION), subAggregations));
}
private Aggregation getTerminatedActivitiesAggregation() {
return withSubaggregations(
term(ACTIVITY_STATE, FlowNodeState.TERMINATED.name()), uniqueActivitiesAggregation());
}
private Aggregation getActiveFlowNodesAggregation() {
return withSubaggregations(
and(term(INCIDENT, false), term(ACTIVITY_STATE, FlowNodeState.ACTIVE.toString())),
uniqueActivitiesAggregation());
}
private Aggregation getIncidentActivitiesAggregation() {
return withSubaggregations(
and(term(INCIDENT, true), term(ACTIVITY_STATE, FlowNodeState.ACTIVE.toString())),
uniqueActivitiesAggregation());
}
private Aggregation getFinishedActivitiesAggregation() {
return withSubaggregations(
and(
term(ACTIVITY_TYPE, FlowNodeType.END_EVENT.toString()),
term(ACTIVITY_STATE, FlowNodeState.COMPLETED.toString())),
uniqueActivitiesAggregation());
}
private Map uniqueActivitiesAggregation() {
return Map.of(
AGG_UNIQUE_ACTIVITIES,
withSubaggregations(
termAggregation(ACTIVITY_ID, TERMS_AGG_SIZE),
Map.of(AGG_ACTIVITY_TO_PROCESS, parent(ACTIVITIES_JOIN_RELATION)._toAggregation())));
}
private Map runQueryAndCollectStats(
SearchRequest.Builder searchRequest) {
final Map statisticsMap = new HashMap<>();
final Map result = richOpenSearchClient.doc().searchAsMap(searchRequest);
final Optional