-
Notifications
You must be signed in to change notification settings - Fork 347
Expand file tree
/
Copy pathStatsMetricsTest.java
More file actions
122 lines (98 loc) · 4.82 KB
/
Copy pathStatsMetricsTest.java
File metadata and controls
122 lines (98 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package datadog.trace.api.metrics;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
/**
* Unit tests for {@link StatsMetrics}. The instance is a process-wide singleton, so each test uses
* its own uniquely-named collapse reasons to stay isolated from other tests' counters.
*/
class StatsMetricsTest {
private static Map<String, StatsMetrics.TaggedCounter> countersByTag() {
return StatsMetrics.getInstance().getTaggedCounters().stream()
.collect(Collectors.toMap(StatsMetrics.TaggedCounter::getTag, Function.identity()));
}
@AfterEach
void drainDeltas() {
// StatsMetrics is a process-wide singleton; these tests leave per-reason deltas behind. Drain
// every counter so they do not leak into another collector's expectations when tests share a
// Gradle worker (e.g. CoreMetricCollectorTest asserting an exact span-metric count).
for (StatsMetrics.TaggedCounter counter : StatsMetrics.getInstance().getTaggedCounters()) {
counter.getValueAndReset();
}
}
@Test
void accumulatesPerReasonAndEmitsResetDeltas() {
StatsMetrics metrics = StatsMetrics.getInstance();
String reason = "collapsed:test_accumulate";
metrics.onCollapsedSpans(reason, 3);
metrics.onCollapsedSpans(reason, 4);
StatsMetrics.TaggedCounter counter = countersByTag().get(reason);
assertEquals(StatsMetrics.COLLAPSED_SPANS, counter.getName());
assertEquals(reason, counter.getTag());
assertEquals(7, counter.getValue(), "getValue reports the running total");
// First drain returns the whole accumulated delta; a second drain with no activity returns 0.
assertEquals(7, counter.getValueAndReset(), "first drain returns the accumulated delta");
assertEquals(0, counter.getValueAndReset(), "no new activity -> zero delta");
metrics.onCollapsedSpans(reason, 5);
assertEquals(5, counter.getValueAndReset(), "only the post-drain increment is returned");
}
@Test
void separateReasonsGetSeparateCounters() {
StatsMetrics metrics = StatsMetrics.getInstance();
String collapsed = "collapsed:test_separate";
String oversized = "oversized:test_separate";
metrics.onCollapsedSpans(collapsed, 2);
metrics.onCollapsedSpans(oversized, 9);
Map<String, StatsMetrics.TaggedCounter> counters = countersByTag();
assertEquals(2, counters.get(collapsed).getValue());
assertEquals(9, counters.get(oversized).getValue());
}
@Test
void nonPositiveCountsAreIgnored() {
StatsMetrics metrics = StatsMetrics.getInstance();
String reason = "collapsed:test_nonpositive";
metrics.onCollapsedSpans(reason, 0);
metrics.onCollapsedSpans(reason, -5);
// No counter is created for a reason that never saw a positive count.
assertNull(countersByTag().get(reason), "no counter created for non-positive counts");
metrics.onCollapsedSpans(reason, 4);
assertEquals(4, countersByTag().get(reason).getValue());
// A later non-positive count leaves the running total untouched.
metrics.onCollapsedSpans(reason, -1);
assertEquals(4, countersByTag().get(reason).getValue());
}
@Test
void wholeKeyCollapseIncrementsPreCreatedCounter() {
StatsMetrics metrics = StatsMetrics.getInstance();
// The whole_key counter is pre-created at construction, so it is always present in the drain.
StatsMetrics.TaggedCounter counter = countersByTag().get(StatsMetrics.COLLAPSED_WHOLE_KEY);
assertEquals(StatsMetrics.COLLAPSED_SPANS, counter.getName());
assertEquals(StatsMetrics.COLLAPSED_WHOLE_KEY, counter.getTag());
long before = counter.getValue();
metrics.onWholeKeyCollapse();
metrics.onWholeKeyCollapse();
assertEquals(before + 2, counter.getValue(), "each call increments the counter by one");
// Routing the same tag through onCollapsedSpans hits the same pre-created counter instance.
assertTrue(
countersByTag().get(StatsMetrics.COLLAPSED_WHOLE_KEY) == counter,
"whole_key resolves to a single stable counter");
metrics.onCollapsedSpans(StatsMetrics.COLLAPSED_WHOLE_KEY, 3);
assertEquals(before + 5, counter.getValue());
}
@Test
void reasonCounterIsStableAcrossLookups() {
StatsMetrics metrics = StatsMetrics.getInstance();
String reason = "collapsed:test_stable";
metrics.onCollapsedSpans(reason, 1);
StatsMetrics.TaggedCounter first = countersByTag().get(reason);
metrics.onCollapsedSpans(reason, 1);
StatsMetrics.TaggedCounter second = countersByTag().get(reason);
assertTrue(first == second, "same reason maps to the same counter instance");
assertEquals(2, first.getValue());
}
}