Class AgentOverviewDashboardService
The actual ES aggregation logic lives in the _flowable_AgentInvocation*Query.query
resource files (see modules/flowable-platform-service/.../query/default/). This
service does not encode any new query logic — it just calls the existing queries by key
via QueryService.executeQuery(String, String, Map) and merges the results into a denormalized AgentOverviewDashboardService.Response.
Evaluator quality is pass-rate only (evaluations + passed); paired aggregations share group/size/order to keep buckets consistent.
Performance note: getDashboard(Instant, Instant, List, String, String) issues ~22 sequential ES round-trips per call. Two
faster alternatives were evaluated (but intentionally not yet implemented):
- Elasticsearch
_msearch— one HTTP round-trip with an NDJSON body of all sub-queries. Big latency win, but needs new methods onElasticsearchClient/SearchService/QueryService CompletableFutureparallelism — keeps N round-trips but runs them concurrently. Requires a dedicated I/O thread pool sized to match the Rest5Client connection pool (the defaultForkJoinPool.commonPool()is sized for CPU work, would starve unrelated JVM work, and would queue threads on connection acquisition).
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classstatic classGeneric key/value bucket used for "X by Y" breakdowns.protected static interfaceprotected static interfacestatic classPer-agent overview row.static classstatic classprotected static final recordstatic classQuality of one evaluator (by bareevaluatorKey).static classEvaluator KPI counts.static classstatic classstatic classstatic classstatic classstatic classstatic class -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final tools.jackson.databind.ObjectMapperprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected static final Stringprotected final QueryServiceprotected static final Stringprotected static final Stringprotected static final String -
Constructor Summary
ConstructorsConstructorDescriptionAgentOverviewDashboardService(QueryService queryService, tools.jackson.databind.ObjectMapper objectMapper) -
Method Summary
Modifier and TypeMethodDescriptionprotected static voidaccumulateDateVersionPassedAndTotal(tools.jackson.databind.JsonNode aggs, String aggName, Map<String, Map<String, long[]>> acc) Reads adate_histogram > terms(version) > sumaggregation intolong[2]per (time, version): slot 0 = evaluations (doc_count), slot 1 = passed (sum).protected static longasDocCount(tools.jackson.databind.JsonNode aggs, String name) Reads the matching-document count of a single-bucket filter aggregation (the shape thatcountCompleted/countActiveproduce).protected static doubleprotected static longprotected static doubleasNestedFilteredAvg(tools.jackson.databind.JsonNode aggs, String name) Reads the value of anavgNestedFieldFilteredaggregation.buildByDefinition(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected List<AgentOverviewDashboardService.ByLlmRow> buildByLlm(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected AgentOverviewDashboardService.CacheHitbuildCacheHitRate(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected List<AgentOverviewDashboardService.EvaluatorRow> buildEvaluatorRows(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Per-evaluator quality table grouped byevaluatorKey: bucket doc_count = evaluations,passedNumericsum = passed.protected AgentOverviewDashboardService.EvaluatorsbuildEvaluators(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator KPI counts.protected List<AgentOverviewDashboardService.TimeBucket> buildEvaluatorTrend(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator pass-rate over time: doc_count per bucket = evaluations,passedNumericsum = passed.protected List<AgentOverviewDashboardService.TimeBucket> buildEvaluatorTrendByVersion(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator pass-rate over time, per agent-definition version (value = pass-rate %),nullwhen a version had no verdicts in the bucket so the chart renders a gap, not a 0%.buildFilterValuesByType(Instant from, Instant to, Collection<String> agentDefinitionKeys, String interval) protected AgentOverviewDashboardService.GuardrailsbuildGuardrails(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected List<AgentOverviewDashboardService.TimeBucket> buildInvocationsOverTime(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected AgentOverviewDashboardService.Kpisprotected List<AgentOverviewDashboardService.Bucket> buildOperationDistribution(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected List<AgentOverviewDashboardService.OperationStat> buildQualityByOperation(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Quality by operation key (already filtered to the drilled-down agent; operation keys are agent-scoped).protected List<AgentOverviewDashboardService.VersionStat> buildQualityByVersion(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Quality by the PARENT agent'sagentDefinitionVersion— evaluators version independently and are identified by bare key.protected List<AgentOverviewDashboardService.TimeBucket> buildTokensByTypeOverTime(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) protected AgentOverviewDashboardService.ToolsbuildTools(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) getAgentDrillDown(Instant from, Instant to, String agentDefinitionKey, String interval, String tenantId) Per-agent drill-down: per-evaluator quality, a pass-rate trend, and quality by parent version and by operation.getDashboard(Instant from, Instant to, List<String> agentDefinitionKeys, String interval, String tenantId) protected static voidmergeDateDocCount(Map<String, AgentOverviewDashboardService.TimeBucket> byTime, tools.jackson.databind.JsonNode aggs, String aggName, String seriesName) Merges a date agg's per-bucketdoc_countas a series, ignoring any sub-aggregation.protected static voidmergeDateSeries(Map<String, AgentOverviewDashboardService.TimeBucket> byTime, tools.jackson.databind.JsonNode aggs, String aggName, String seriesName) protected static tools.jackson.databind.JsonNodenestedBuckets(tools.jackson.databind.JsonNode aggs, String aggName) Bucket list of agroupByNestedFieldFiltered-style aggregation, or a missing node when the path is absent.protected static voidreadBuckets(tools.jackson.databind.JsonNode aggs, String aggName, AgentOverviewDashboardService.BucketHandler handler) protected static List<AgentOverviewDashboardService.Bucket> readBucketsWithSum(tools.jackson.databind.JsonNode aggs, String aggName) Reads buckets from agroupByFieldWithSumFieldaggregation, returning only the sub-aggregation sum value.protected static voidreadBucketsWithSumOrCount(tools.jackson.databind.JsonNode aggs, String aggName, AgentOverviewDashboardService.BucketWithValueHandler handler) protected static List<AgentOverviewDashboardService.TimeBucket> readDateBuckets(tools.jackson.databind.JsonNode aggs, String aggName, String seriesName) readEvaluatorCounts(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator pass/fail counts from oneQUERY_EVALUATOR_PASS_RATEaggregation; failed is the remainder after passed.protected static voidreadNestedFilteredBuckets(tools.jackson.databind.JsonNode aggs, String aggName, AgentOverviewDashboardService.BucketHandler handler) Reads buckets from agroupByNestedFieldFiltered-style aggregation.protected static voidreadNestedFilteredBucketsWithSub(tools.jackson.databind.JsonNode aggs, String aggName, String subAggSuffix, AgentOverviewDashboardService.BucketWithValueHandler handler) MirrorsgroupByNestedFieldFilteredWith[Sum|Avg]Field.protected tools.jackson.databind.JsonNoderun(String queryKey, String tenantId, Map<String, tools.jackson.databind.JsonNode> filterValuesByType) Calls the deployed query by key.translateFilterValues(QueryDefinitionModel model, Map<String, tools.jackson.databind.JsonNode> filterValuesByType) Walks the query's declared input parameters and builds a payload using each parameter's actualname, looking up its value bytypefrom the dashboard's filter values.
-
Field Details
-
TYPE_AGENT_DEFINITIONS
- See Also:
-
TYPE_START_TIME
- See Also:
-
TYPE_END_TIME
- See Also:
-
OPTION_INTERVAL
- See Also:
-
QUERY_TOTAL_TOKENS
- See Also:
-
QUERY_INVOCATION_COUNT
- See Also:
-
QUERY_AVG_DURATION
- See Also:
-
QUERY_TOTAL_TOOLS
- See Also:
-
QUERY_AVG_TOOL_DURATION
- See Also:
-
QUERY_TOTAL_GUARDRAIL_EVALS
- See Also:
-
QUERY_GUARDRAIL_PASS_RATE
- See Also:
-
QUERY_GUARDRAILS_BY_DEFINITION
- See Also:
-
QUERY_EVALUATOR_PASS_RATE
- See Also:
-
QUERY_ACTIVE_DEFINITIONS
- See Also:
-
QUERY_INSTANCES_COUNT
- See Also:
-
QUERY_INVOCATIONS_BY_TIME
- See Also:
-
QUERY_TOKENS_BY_TYPE_BY_TIME
- See Also:
-
QUERY_TOKENS_BY_DEFINITION
- See Also:
-
QUERY_AVG_TOKENS_BY_DEFINITION
- See Also:
-
QUERY_AVG_DURATION_BY_DEFINITION
- See Also:
-
QUERY_TOTAL_TOKENS_BY_MODEL
- See Also:
-
QUERY_AVG_TOKENS_PER_CALL_BY_MODEL
- See Also:
-
QUERY_MODEL_DISTRIBUTION
- See Also:
-
QUERY_TOOLS_BY_NAME
- See Also:
-
QUERY_OPERATION_DISTRIBUTION
- See Also:
-
QUERY_EVALUATOR_BY_OPERATION
- See Also:
-
QUERY_EVALUATOR_BY_TIME
- See Also:
-
QUERY_EVALUATOR_BY_TIME_AND_VERSION
- See Also:
-
QUERY_EVALUATOR_BY_VERSION
- See Also:
-
QUERY_EVALUATOR_BY_EVALUATOR
- See Also:
-
queryService
-
objectMapper
protected final tools.jackson.databind.ObjectMapper objectMapper
-
-
Constructor Details
-
AgentOverviewDashboardService
public AgentOverviewDashboardService(QueryService queryService, tools.jackson.databind.ObjectMapper objectMapper)
-
-
Method Details
-
getDashboard
-
getAgentDrillDown
-
buildKpis
protected AgentOverviewDashboardService.Kpis buildKpis(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildInvocationsOverTime
protected List<AgentOverviewDashboardService.TimeBucket> buildInvocationsOverTime(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildTokensByTypeOverTime
protected List<AgentOverviewDashboardService.TimeBucket> buildTokensByTypeOverTime(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildByDefinition
protected List<AgentOverviewDashboardService.ByDefinitionRow> buildByDefinition(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildByLlm
protected List<AgentOverviewDashboardService.ByLlmRow> buildByLlm(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildGuardrails
protected AgentOverviewDashboardService.Guardrails buildGuardrails(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildEvaluators
protected AgentOverviewDashboardService.Evaluators buildEvaluators(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator KPI counts. Only completed evaluations are indexed, soevaluations = passed + failed. -
readEvaluatorCounts
protected AgentOverviewDashboardService.EvaluatorCounts readEvaluatorCounts(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator pass/fail counts from oneQUERY_EVALUATOR_PASS_RATEaggregation; failed is the remainder after passed. -
buildTools
protected AgentOverviewDashboardService.Tools buildTools(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildCacheHitRate
protected AgentOverviewDashboardService.CacheHit buildCacheHitRate(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildOperationDistribution
protected List<AgentOverviewDashboardService.Bucket> buildOperationDistribution(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) -
buildEvaluatorRows
protected List<AgentOverviewDashboardService.EvaluatorRow> buildEvaluatorRows(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Per-evaluator quality table grouped byevaluatorKey: bucket doc_count = evaluations,passedNumericsum = passed. -
buildEvaluatorTrend
protected List<AgentOverviewDashboardService.TimeBucket> buildEvaluatorTrend(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator pass-rate over time: doc_count per bucket = evaluations,passedNumericsum = passed. -
buildEvaluatorTrendByVersion
protected List<AgentOverviewDashboardService.TimeBucket> buildEvaluatorTrendByVersion(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Evaluator pass-rate over time, per agent-definition version (value = pass-rate %),nullwhen a version had no verdicts in the bucket so the chart renders a gap, not a 0%. -
buildQualityByVersion
protected List<AgentOverviewDashboardService.VersionStat> buildQualityByVersion(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Quality by the PARENT agent'sagentDefinitionVersion— evaluators version independently and are identified by bare key. -
buildQualityByOperation
protected List<AgentOverviewDashboardService.OperationStat> buildQualityByOperation(Map<String, tools.jackson.databind.JsonNode> filters, String tenantId) Quality by operation key (already filtered to the drilled-down agent; operation keys are agent-scoped). -
run
protected tools.jackson.databind.JsonNode run(String queryKey, String tenantId, Map<String, tools.jackson.databind.JsonNode> filterValuesByType) Calls the deployed query by key. Returns the raw "aggregations" subtree (or null on failure).Translates the type-keyed filter values into the actual payload keys the query expects by reading the query model's input parameters. This works for both old-style (implicit
__flowable_internal_input_param_*names) and new-style (explicitinputParametersblock) query JSONs. -
translateFilterValues
protected Map<String, tools.jackson.databind.JsonNode> translateFilterValues(QueryDefinitionModel model, Map<String, tools.jackson.databind.JsonNode> filterValuesByType) Walks the query's declared input parameters and builds a payload using each parameter's actualname, looking up its value bytypefrom the dashboard's filter values. Decouples this service from how the platform deployer happens to name parameters internally. -
buildFilterValuesByType
-
asLong
-
asDocCount
Reads the matching-document count of a single-bucket filter aggregation (the shape thatcountCompleted/countActiveproduce). Filter aggregations respond withdoc_count— they have novaluefield like the metric aggregations (sum/avg/cardinality) thatasLong(JsonNode, String)reads. -
asNestedFilteredAvg
Reads the value of anavgNestedFieldFilteredaggregation. The metric lives several levels deep:/{aggName}/{aggName}_filtered/{aggName}_avg/value. -
asDouble
-
readBuckets
protected static void readBuckets(tools.jackson.databind.JsonNode aggs, String aggName, AgentOverviewDashboardService.BucketHandler handler) -
readBucketsWithSumOrCount
protected static void readBucketsWithSumOrCount(tools.jackson.databind.JsonNode aggs, String aggName, AgentOverviewDashboardService.BucketWithValueHandler handler) -
readBucketsWithSum
protected static List<AgentOverviewDashboardService.Bucket> readBucketsWithSum(tools.jackson.databind.JsonNode aggs, String aggName) Reads buckets from agroupByFieldWithSumFieldaggregation, returning only the sub-aggregation sum value. We deliberately do NOT fall back todoc_count: for metrics like "violations per definition", a zero sum is a meaningful answer (no violations for that agent), and bucketed agents with zero are filtered out so the chart shows only agents that actually contributed to the metric. -
nestedBuckets
protected static tools.jackson.databind.JsonNode nestedBuckets(tools.jackson.databind.JsonNode aggs, String aggName) Bucket list of agroupByNestedFieldFiltered-style aggregation, or a missing node when the path is absent. -
readNestedFilteredBuckets
protected static void readNestedFilteredBuckets(tools.jackson.databind.JsonNode aggs, String aggName, AgentOverviewDashboardService.BucketHandler handler) Reads buckets from agroupByNestedFieldFiltered-style aggregation. The bucket list lives several levels deep:/aggregations/{aggName}/{aggName}_filtered/{aggName}_inner/buckets. -
readNestedFilteredBucketsWithSub
protected static void readNestedFilteredBucketsWithSub(tools.jackson.databind.JsonNode aggs, String aggName, String subAggSuffix, AgentOverviewDashboardService.BucketWithValueHandler handler) MirrorsgroupByNestedFieldFilteredWith[Sum|Avg]Field. Unlike the flat group-by builders (which name their metric sub-aggregationaggName + "_sub"), the nested filtered builders name itaggName + "_sum"oraggName + "_avg"depending on the metric — the caller passes the matching suffix. -
readDateBuckets
protected static List<AgentOverviewDashboardService.TimeBucket> readDateBuckets(tools.jackson.databind.JsonNode aggs, String aggName, String seriesName) -
mergeDateSeries
protected static void mergeDateSeries(Map<String, AgentOverviewDashboardService.TimeBucket> byTime, tools.jackson.databind.JsonNode aggs, String aggName, String seriesName) -
mergeDateDocCount
protected static void mergeDateDocCount(Map<String, AgentOverviewDashboardService.TimeBucket> byTime, tools.jackson.databind.JsonNode aggs, String aggName, String seriesName) Merges a date agg's per-bucketdoc_countas a series, ignoring any sub-aggregation. -
accumulateDateVersionPassedAndTotal
-