From fddd56e9bac85d5dafaa6c3e0fb2f406979f4af2 Mon Sep 17 00:00:00 2001 From: Peter Alfonsi Date: Thu, 11 Apr 2024 11:59:13 -0700 Subject: [PATCH] Moved aggregation logic to API PR Signed-off-by: Peter Alfonsi --- .../cache/stats/MultiDimensionCacheStats.java | 68 ---------------- .../stats/MultiDimensionCacheStatsTests.java | 77 ------------------- 2 files changed, 145 deletions(-) diff --git a/server/src/main/java/org/opensearch/common/cache/stats/MultiDimensionCacheStats.java b/server/src/main/java/org/opensearch/common/cache/stats/MultiDimensionCacheStats.java index 7c9bb2209a1e0..1cb604b80e530 100644 --- a/server/src/main/java/org/opensearch/common/cache/stats/MultiDimensionCacheStats.java +++ b/server/src/main/java/org/opensearch/common/cache/stats/MultiDimensionCacheStats.java @@ -131,74 +131,6 @@ public long getTotalEntries() { return getTotalStats().getEntries(); } - /** - * Returns a new tree containing the stats aggregated by the levels passed in. The root node is a dummy node, - * whose name and value are null. The new tree only has dimensions matching the levels passed in. - */ - MDCSDimensionNode aggregateByLevels(List levels) { - List filteredLevels = filterLevels(levels); - MDCSDimensionNode newRoot = new MDCSDimensionNode("", true, statsRoot.getStats()); - for (MDCSDimensionNode child : statsRoot.children.values()) { - aggregateByLevelsHelper(newRoot, child, filteredLevels, 0); - } - return newRoot; - } - - void aggregateByLevelsHelper( - MDCSDimensionNode parentInNewTree, - MDCSDimensionNode currentInOriginalTree, - List levels, - int depth - ) { - if (levels.contains(dimensionNames.get(depth))) { - // If this node is in a level we want to aggregate, create a new dimension node with the same value and stats, and connect it to - // the last parent node in the new tree. If it already exists, increment it instead. - String dimensionValue = currentInOriginalTree.getDimensionValue(); - MDCSDimensionNode nodeInNewTree = parentInNewTree.children.get(dimensionValue); - if (nodeInNewTree == null) { - // Create new node with stats matching the node from the original tree - int indexOfLastLevel = dimensionNames.indexOf(levels.get(levels.size() - 1)); - boolean isLeafNode = depth == indexOfLastLevel; // If this is the last level we aggregate, the new node should be a leaf - // node - nodeInNewTree = new MDCSDimensionNode(dimensionValue, !isLeafNode, currentInOriginalTree.getStats()); - parentInNewTree.children.put(dimensionValue, nodeInNewTree); - } else { - // Otherwise increment existing stats - CacheStatsCounterSnapshot newStats = CacheStatsCounterSnapshot.addSnapshots( - nodeInNewTree.getStats(), - currentInOriginalTree.getStats() - ); - nodeInNewTree.setStats(newStats); - } - // Finally set the parent node to be this node for the next callers of this function - parentInNewTree = nodeInNewTree; - } - - if (!currentInOriginalTree.children.isEmpty()) { - // Not a leaf node - for (Map.Entry childEntry : currentInOriginalTree.children.entrySet()) { - MDCSDimensionNode child = childEntry.getValue(); - aggregateByLevelsHelper(parentInNewTree, child, levels, depth + 1); - } - } - } - - /** - * Filters out levels that aren't in dimensionNames. Unrecognized levels are ignored. - */ - private List filterLevels(List levels) { - List filtered = new ArrayList<>(); - for (String level : levels) { - if (dimensionNames.contains(level)) { - filtered.add(level); - } - } - if (filtered.isEmpty()) { - throw new IllegalArgumentException("Levels cannot have size 0"); - } - return filtered; - } - public CacheStatsCounterSnapshot getStatsForDimensionValues(List dimensionValues) { MDCSDimensionNode current = statsRoot; for (String dimensionValue : dimensionValues) { diff --git a/server/src/test/java/org/opensearch/common/cache/stats/MultiDimensionCacheStatsTests.java b/server/src/test/java/org/opensearch/common/cache/stats/MultiDimensionCacheStatsTests.java index e7cc7f23f2747..3be79876cf148 100644 --- a/server/src/test/java/org/opensearch/common/cache/stats/MultiDimensionCacheStatsTests.java +++ b/server/src/test/java/org/opensearch/common/cache/stats/MultiDimensionCacheStatsTests.java @@ -95,83 +95,6 @@ public void testEmptyDimsList() throws Exception { assertEquals(stats.getTotalStats(), statsRoot.getStats()); } - public void testAggregateByAllDimensions() throws Exception { - // Aggregating with all dimensions as levels should just give us the same values that were in the original map - List dimensionNames = List.of("dim1", "dim2", "dim3", "dim4"); - StatsHolder statsHolder = new StatsHolder(dimensionNames); - Map> usedDimensionValues = getUsedDimensionValues(statsHolder, 10); - Map, CacheStatsCounter> expected = populateStats(statsHolder, usedDimensionValues, 1000, 10); - MultiDimensionCacheStats stats = (MultiDimensionCacheStats) statsHolder.getCacheStats(); - - MultiDimensionCacheStats.MDCSDimensionNode aggregated = stats.aggregateByLevels(dimensionNames); - for (Map.Entry, CacheStatsCounter> expectedEntry : expected.entrySet()) { - List dimensionValues = new ArrayList<>(); - for (String dimValue : expectedEntry.getKey()) { - dimensionValues.add(dimValue); - } - assertEquals(expectedEntry.getValue().snapshot(), getNode(dimensionValues, aggregated).getStats()); - } - assertSumOfChildrenStats(aggregated); - } - - public void testAggregateBySomeDimensions() throws Exception { - List dimensionNames = List.of("dim1", "dim2", "dim3", "dim4"); - StatsHolder statsHolder = new StatsHolder(dimensionNames); - Map> usedDimensionValues = getUsedDimensionValues(statsHolder, 10); - Map, CacheStatsCounter> expected = populateStats(statsHolder, usedDimensionValues, 1000, 10); - MultiDimensionCacheStats stats = (MultiDimensionCacheStats) statsHolder.getCacheStats(); - - for (int i = 0; i < (1 << dimensionNames.size()); i++) { - // Test each combination of possible levels - List levels = new ArrayList<>(); - for (int nameIndex = 0; nameIndex < dimensionNames.size(); nameIndex++) { - if ((i & (1 << nameIndex)) != 0) { - levels.add(dimensionNames.get(nameIndex)); - } - } - if (levels.size() == 0) { - assertThrows(IllegalArgumentException.class, () -> stats.aggregateByLevels(levels)); - } else { - MultiDimensionCacheStats.MDCSDimensionNode aggregated = stats.aggregateByLevels(levels); - Map, MultiDimensionCacheStats.MDCSDimensionNode> aggregatedLeafNodes = getAllLeafNodes(aggregated); - - for (Map.Entry, MultiDimensionCacheStats.MDCSDimensionNode> aggEntry : aggregatedLeafNodes.entrySet()) { - CacheStatsCounter expectedCounter = new CacheStatsCounter(); - for (List expectedDims : expected.keySet()) { - if (expectedDims.containsAll(aggEntry.getKey())) { - expectedCounter.add(expected.get(expectedDims)); - } - } - assertEquals(expectedCounter.snapshot(), aggEntry.getValue().getStats()); - } - assertSumOfChildrenStats(aggregated); - } - } - } - - // Get a map from the list of dimension values to the corresponding leaf node. - private Map, MultiDimensionCacheStats.MDCSDimensionNode> getAllLeafNodes(MultiDimensionCacheStats.MDCSDimensionNode root) { - Map, MultiDimensionCacheStats.MDCSDimensionNode> result = new HashMap<>(); - getAllLeafNodesHelper(result, root, new ArrayList<>()); - return result; - } - - private void getAllLeafNodesHelper( - Map, MultiDimensionCacheStats.MDCSDimensionNode> result, - MultiDimensionCacheStats.MDCSDimensionNode current, - List pathToCurrent - ) { - if (current.children.isEmpty()) { - result.put(pathToCurrent, current); - } else { - for (Map.Entry entry : current.children.entrySet()) { - List newPath = new ArrayList<>(pathToCurrent); - newPath.add(entry.getKey()); - getAllLeafNodesHelper(result, entry.getValue(), newPath); - } - } - } - private void assertSumOfChildrenStats(MultiDimensionCacheStats.MDCSDimensionNode current) { if (!current.children.isEmpty()) { CacheStatsCounter expectedTotal = new CacheStatsCounter();