io.camunda.operate.webapp.api.v1.dao.elasticsearch.ElasticsearchFlowNodeStatisticsDao 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.api.v1.dao.elasticsearch;
import static io.camunda.operate.entities.FlowNodeState.ACTIVE;
import static io.camunda.operate.entities.FlowNodeState.COMPLETED;
import static io.camunda.operate.entities.FlowNodeState.TERMINATED;
import static io.camunda.operate.schema.templates.FlowNodeInstanceTemplate.FLOW_NODE_ID;
import static io.camunda.operate.schema.templates.FlowNodeInstanceTemplate.INCIDENT;
import static io.camunda.operate.schema.templates.FlowNodeInstanceTemplate.STATE;
import static io.camunda.operate.schema.templates.FlowNodeInstanceTemplate.TYPE;
import static io.camunda.operate.util.ElasticsearchUtil.TERMS_AGG_SIZE;
import static io.camunda.operate.util.ElasticsearchUtil.joinWithAnd;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.constantScoreQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.search.aggregations.AggregationBuilders.filter;
import static org.elasticsearch.search.aggregations.AggregationBuilders.terms;
import io.camunda.operate.conditions.ElasticsearchCondition;
import io.camunda.operate.entities.FlowNodeType;
import io.camunda.operate.exceptions.OperateRuntimeException;
import io.camunda.operate.schema.templates.FlowNodeInstanceTemplate;
import io.camunda.operate.util.ElasticsearchUtil;
import io.camunda.operate.webapp.api.v1.dao.FlowNodeStatisticsDao;
import io.camunda.operate.webapp.api.v1.entities.FlowNodeStatistics;
import io.camunda.operate.webapp.api.v1.entities.Query;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.filter.Filter;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Conditional(ElasticsearchCondition.class)
@Component("ElasticsearchFlowNodeStatisticsDaoV1")
public class ElasticsearchFlowNodeStatisticsDao extends ElasticsearchDao
implements FlowNodeStatisticsDao {
@Autowired private FlowNodeInstanceTemplate flowNodeInstanceTemplate;
@Override
protected void buildFiltering(
Query query, SearchSourceBuilder searchSourceBuilder) {
final FlowNodeStatistics filter = query.getFilter();
final List queryBuilders = new ArrayList<>();
if (filter != null) {
queryBuilders.add(buildTermQuery(FlowNodeStatistics.ACTIVITY_ID, filter.getActivityId()));
}
searchSourceBuilder.query(joinWithAnd(queryBuilders.toArray(new QueryBuilder[] {})));
}
@Override
public List getFlowNodeStatisticsForProcessInstance(Long processInstanceKey) {
try {
final SearchRequest request =
ElasticsearchUtil.createSearchRequest(flowNodeInstanceTemplate)
.source(
new SearchSourceBuilder()
.query(
constantScoreQuery(
termQuery(
FlowNodeInstanceTemplate.PROCESS_INSTANCE_KEY,
processInstanceKey)))
.aggregation(
terms(FLOW_NODE_ID_AGG)
.field(FLOW_NODE_ID)
.size(TERMS_AGG_SIZE)
.subAggregation(
filter(
COUNT_INCIDENT,
boolQuery()
// Need to count when MULTI_INSTANCE_BODY itself has an
// incident
// .mustNot(termQuery(TYPE,
// FlowNodeType.MULTI_INSTANCE_BODY))
.must(termQuery(INCIDENT, true))))
.subAggregation(
filter(
COUNT_CANCELED,
boolQuery()
.mustNot(
termQuery(TYPE, FlowNodeType.MULTI_INSTANCE_BODY))
.must(termQuery(STATE, TERMINATED))))
.subAggregation(
filter(
COUNT_COMPLETED,
boolQuery()
.mustNot(
termQuery(TYPE, FlowNodeType.MULTI_INSTANCE_BODY))
.must(termQuery(STATE, COMPLETED))))
.subAggregation(
filter(
COUNT_ACTIVE,
boolQuery()
.mustNot(
termQuery(TYPE, FlowNodeType.MULTI_INSTANCE_BODY))
.must(termQuery(STATE, ACTIVE))
.must(termQuery(INCIDENT, false)))))
.size(0));
final SearchResponse response = tenantAwareClient.search(request);
final Aggregations aggregations = response.getAggregations();
final Terms flowNodeAgg = aggregations.get(FLOW_NODE_ID_AGG);
return flowNodeAgg.getBuckets().stream()
.map(
bucket ->
new FlowNodeStatistics()
.setActivityId(bucket.getKeyAsString())
.setCanceled(
((Filter) bucket.getAggregations().get(COUNT_CANCELED)).getDocCount())
.setIncidents(
((Filter) bucket.getAggregations().get(COUNT_INCIDENT)).getDocCount())
.setCompleted(
((Filter) bucket.getAggregations().get(COUNT_COMPLETED)).getDocCount())
.setActive(
((Filter) bucket.getAggregations().get(COUNT_ACTIVE)).getDocCount()))
.collect(Collectors.toList());
} catch (IOException e) {
final String message =
String.format(
"Exception occurred, while obtaining statistics for process instance flow nodes: %s",
e.getMessage());
throw new OperateRuntimeException(message, e);
}
}
}