Skip to content

Commit 0c3e6e2

Browse files
authored
Merge pull request #25 from avast/group-monitor
Remove MultiMonitor, add Summary and Group monitors
2 parents 48e7987 + 2bf7d8a commit 0c3e6e2

File tree

7 files changed

+384
-185
lines changed

7 files changed

+384
-185
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
package com.avast.metrics.core.multi;
2+
3+
import com.avast.metrics.TimerPairImpl;
4+
import com.avast.metrics.api.*;
5+
6+
import java.util.Arrays;
7+
import java.util.List;
8+
import java.util.function.Supplier;
9+
import java.util.stream.Collectors;
10+
11+
/**
12+
* Wrapper around a group of monitors.
13+
*/
14+
public class GroupMonitor implements Monitor {
15+
16+
private final List<Monitor> monitors;
17+
private final Naming naming;
18+
19+
/**
20+
* Factory method.
21+
*
22+
* @param monitors list of monitors
23+
* @return multiple monitor containing all passed monitors
24+
*/
25+
public static Monitor of(Monitor... monitors) {
26+
return new GroupMonitor(Arrays.asList(monitors), Naming.defaultNaming());
27+
}
28+
29+
/**
30+
* Factory method.
31+
*
32+
* @param monitors list of monitors
33+
* @param naming naming conventions for TimerPairs
34+
* @return multiple monitor containing all passed monitors
35+
*/
36+
public static Monitor of(Naming naming, Monitor... monitors) {
37+
return new GroupMonitor(Arrays.asList(monitors), naming);
38+
}
39+
40+
private GroupMonitor(List<Monitor> monitors, Naming naming) {
41+
if (monitors.size() < 2) {
42+
throw new IllegalArgumentException("Group monitor from less than 2 counters makes no sense");
43+
}
44+
this.monitors = monitors;
45+
this.naming = naming;
46+
}
47+
48+
/**
49+
* {@inheritDoc}
50+
*
51+
* @param name name of the next sub-level
52+
* @return new group monitor with name applied to all instances
53+
*/
54+
@Override
55+
public Monitor named(String name) {
56+
List<Monitor> newMonitors = monitors.stream()
57+
.map(monitor -> monitor.named(name))
58+
.collect(Collectors.toList());
59+
return new GroupMonitor(newMonitors, naming);
60+
}
61+
62+
/**
63+
* {@inheritDoc}
64+
*
65+
* @param name1 name of the next sub-level
66+
* @param name2 name of the next sub-level
67+
* @param restOfNames name of the next sub-level
68+
* @return new group monitor with name applied to all instances
69+
*/
70+
@Override
71+
public Monitor named(String name1, String name2, String... restOfNames) {
72+
List<Monitor> newMonitors = monitors.stream()
73+
.map(monitor -> monitor.named(name1, name2, restOfNames))
74+
.collect(Collectors.toList());
75+
return new GroupMonitor(newMonitors, naming);
76+
}
77+
78+
@Override
79+
public String getName() {
80+
return monitors.get(0).getName();
81+
}
82+
83+
@Override
84+
public Meter newMeter(String name) {
85+
List<Meter> meters = monitors.stream()
86+
.map(m -> m.newMeter(name))
87+
.collect(Collectors.toList());
88+
89+
return new MultiMeter(meters);
90+
}
91+
92+
@Override
93+
public Counter newCounter(String name) {
94+
List<Counter> counters = monitors.stream()
95+
.map(m -> m.newCounter(name))
96+
.collect(Collectors.toList());
97+
98+
return new MultiCounter(counters);
99+
}
100+
101+
@Override
102+
public Timer newTimer(String name) {
103+
List<Timer> timers = monitors.stream()
104+
.map(m -> m.newTimer(name))
105+
.collect(Collectors.toList());
106+
107+
return new MultiTimer(timers);
108+
}
109+
110+
@Override
111+
public TimerPair newTimerPair(String name) {
112+
return new TimerPairImpl(
113+
newTimer(naming.successTimerName(name)),
114+
newTimer(naming.failureTimerName(name))
115+
);
116+
}
117+
118+
@Override
119+
public <T> Gauge<T> newGauge(String name, Supplier<T> gauge) {
120+
return newGauge(name, false, gauge);
121+
}
122+
123+
@Override
124+
public <T> Gauge<T> newGauge(String name, boolean replaceExisting, Supplier<T> gauge) {
125+
List<Gauge<T>> gauges = monitors.stream()
126+
.map(monitor -> monitor.newGauge(name, replaceExisting, gauge))
127+
.collect(Collectors.toList());
128+
return gauges.get(0);
129+
}
130+
131+
@Override
132+
public Histogram newHistogram(String name) {
133+
List<Histogram> histograms = monitors.stream()
134+
.map(m -> m.newHistogram(name))
135+
.collect(Collectors.toList());
136+
137+
return new MultiHistogram(histograms);
138+
}
139+
140+
@Override
141+
public void remove(Metric metric) {
142+
monitors.forEach(monitor -> monitor.remove(metric));
143+
}
144+
145+
@Override
146+
public void close() {
147+
monitors.forEach(Monitor::close);
148+
}
149+
150+
}

core/src/main/java/com/avast/metrics/core/multi/MultiCounter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.List;
66

77
/**
8-
* Counter used by {@link MultiMonitor}.
8+
* Counter used by {@link GroupMonitor} and {@link SummaryMonitor}.
99
*/
1010
class MultiCounter implements Counter {
1111
private final List<Counter> counters;

core/src/main/java/com/avast/metrics/core/multi/MultiHistogram.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.List;
66

77
/**
8-
* Histogram used by {@link MultiMonitor}.
8+
* Histogram used by {@link GroupMonitor} and {@link SummaryMonitor}.
99
*/
1010
class MultiHistogram implements Histogram {
1111
private final List<Histogram> histograms;

core/src/main/java/com/avast/metrics/core/multi/MultiMeter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.List;
66

77
/**
8-
* Meter used by {@link MultiMonitor}.
8+
* Meter used by {@link GroupMonitor} and {@link SummaryMonitor}.
99
*/
1010
class MultiMeter implements Meter {
1111
private final List<Meter> meters;
Lines changed: 8 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,22 @@
11
package com.avast.metrics.core.multi;
22

3-
import com.avast.metrics.TimerPairImpl;
4-
import com.avast.metrics.api.*;
3+
import com.avast.metrics.api.Monitor;
4+
import com.avast.metrics.api.Naming;
55

66
import java.util.ArrayList;
77
import java.util.List;
8-
import java.util.function.Supplier;
9-
import java.util.stream.Collectors;
108

119
/**
12-
* Wrapper around multiple monitors that adds possibility of per instance and summary metrics stored in a single object
13-
* and updated by a single call instead of two separate ones.
14-
* <p>
15-
* The first of the wrapped monitors is the main monitor instance, it should be the most concrete one. The second
16-
* is typically a summary per all instances. Only two wrapped monitors are expected at the moment but the internal
17-
* implementation is generic.
18-
* <p>
19-
* <h3>Limitations</h3>
20-
* <p>
21-
* The updates are applied to all wrapped monitors the same way, but queries for names and values will always operate only
22-
* on the first one which represents the monitored instance. Note it is impossible to return two ints at place of one int,
23-
* adding them together would typically produce a value that doesn't make any sense at all.
24-
* <p>
25-
* {@link #named(String)} creates a new multi monitor with the name applied only to the instance monitor, the summary
26-
* one is untouched and only copied. This allows to dynamically create new sub-monitors while summary is preserved.
27-
* <p>
28-
* {@link #remove(Metric)} removes the metric only from the first wrapped monitor. The summary monitor is shared by
29-
* multiple instances so the remove might cause some unexpected problems in such case.
30-
* <p>
31-
* {@link #newGauge(String, Supplier)} is also registered only to the first wrapped monitor. There would be JMX conflicts
32-
* with the summary monitor shared by multiple instances.
33-
* <p>
34-
* <h3>Typical usage</h3>
35-
* <p>
36-
* <pre><code>
37-
* Monitor summaryMonitor = monitor.named("path");
38-
* Monitor instanceMonitor = summaryMonitor.named("instance");
39-
*
40-
* Monitor monitor = MultiMonitor.of(instanceMonitor, summaryMonitor);
41-
*
42-
* this.errors = monitor.newMeter("errors");
43-
* this.requests = monitor.newMeter("requests");
44-
* </code></pre>
45-
* <p>
46-
* <pre><code>
47-
* Monitor summaryMonitor = monitor.named("path");
48-
* Monitor monitor = MultiMonitor.of(summaryMonitor, summaryMonitor);
49-
* ConcurrentMap&lt;String, Meter&gt; requests = new ConcurrentHashMap&lt;&gt;()
50-
*
51-
* // Dynamically create a new meter if not present in the cache and increment its value
52-
* requests.computeIfAbsent(topic, t -&gt; monitor.named(t).newMeter("requests")).mark();
53-
* </code></pre>
10+
* Use SummaryMonitor instead.
5411
*/
55-
public class MultiMonitor implements Monitor {
56-
57-
private final List<Monitor> monitors;
58-
private final Naming naming;
59-
12+
@Deprecated()
13+
public class MultiMonitor extends SummaryMonitor {
6014
/**
6115
* Factory method. Read {@link MultiMonitor} limitations!
6216
*
6317
* @param instanceMonitor non-shared main monitor for data from a single instance
6418
* @param summaryMonitor shared summary monitor counting sums per all instances
65-
* @return multi monitor containing all passed monitors
19+
* @return summary monitor containing all passed monitors
6620
*/
6721
public static Monitor of(Monitor instanceMonitor, Monitor summaryMonitor) {
6822
List<Monitor> allMonitors = new ArrayList<>(2);
@@ -78,7 +32,7 @@ public static Monitor of(Monitor instanceMonitor, Monitor summaryMonitor) {
7832
* @param instanceMonitor non-shared main monitor for data from a single instance
7933
* @param summaryMonitor shared summary monitor counting sums per all instances
8034
* @param naming naming conventions for TimerPair
81-
* @return multi monitor containing all passed monitors
35+
* @return summary monitor containing all passed monitors
8236
*/
8337

8438
public static Monitor of(Monitor instanceMonitor, Monitor summaryMonitor, Naming naming) {
@@ -90,133 +44,6 @@ public static Monitor of(Monitor instanceMonitor, Monitor summaryMonitor, Naming
9044
}
9145

9246
private MultiMonitor(List<Monitor> monitors, Naming naming) {
93-
if (monitors.size() < 2) {
94-
throw new IllegalArgumentException("Multi monitor from less than 2 monitors makes no sense");
95-
}
96-
97-
this.monitors = monitors;
98-
this.naming = naming;
99-
}
100-
101-
/**
102-
* {@inheritDoc}
103-
*
104-
* @param name name of the next sub-level
105-
* @return new multi monitor with name applied only on the instance one, the summary one is left untouched
106-
*/
107-
@Override
108-
public Monitor named(String name) {
109-
return MultiMonitor.of(monitors.get(0).named(name), monitors.get(1));
110-
}
111-
112-
/**
113-
* {@inheritDoc}
114-
*
115-
* @param name1 name of the next sub-level
116-
* @param name2 name of the next sub-level
117-
* @param restOfNames name of the next sub-level
118-
* @return new multi monitor with names applied only on the instance one, the summary one is left untouched
119-
*/
120-
@Override
121-
public Monitor named(String name1, String name2, String... restOfNames) {
122-
return MultiMonitor.of(monitors.get(0).named(name1, name2, restOfNames), monitors.get(1));
123-
}
124-
125-
@Override
126-
public String getName() {
127-
return monitors.get(0).getName();
128-
}
129-
130-
@Override
131-
public Meter newMeter(String name) {
132-
List<Meter> meters = monitors.stream()
133-
.map(m -> m.newMeter(name))
134-
.collect(Collectors.toList());
135-
136-
return new MultiMeter(meters);
137-
}
138-
139-
@Override
140-
public Counter newCounter(String name) {
141-
List<Counter> counters = monitors.stream()
142-
.map(m -> m.newCounter(name))
143-
.collect(Collectors.toList());
144-
145-
return new MultiCounter(counters);
146-
}
147-
148-
@Override
149-
public Timer newTimer(String name) {
150-
return newMultiTimer(name);
151-
}
152-
153-
private MultiTimer newMultiTimer(String name) {
154-
List<Timer> timers = monitors.stream()
155-
.map(m -> m.newTimer(name))
156-
.collect(Collectors.toList());
157-
158-
return new MultiTimer(timers);
159-
}
160-
161-
162-
/**
163-
* TimerPair multi monitor. Uses instanceMonitor (first parameter of the factory method) to create failure timer.
164-
*
165-
*/
166-
@Override
167-
public TimerPair newTimerPair(String name) {
168-
return new TimerPairImpl(
169-
newMultiTimer(name),
170-
monitors.get(0).newTimer(naming.successTimerName(name))
171-
);
47+
super(monitors, naming);
17248
}
173-
174-
/**
175-
* {@inheritDoc}
176-
* <p>
177-
* Register the gauge only to the instance monitor. There would be JMX conflicts with the summary monitor
178-
* which is typically shared by multiple instances.
179-
*
180-
* @param name gauge name
181-
* @param gauge method to compute the gauge value
182-
* @param <T> type of computed value
183-
* @return new gauge
184-
*/
185-
@Override
186-
public <T> Gauge<T> newGauge(String name, Supplier<T> gauge) {
187-
return newGauge(name, false, gauge);
188-
}
189-
190-
@Override
191-
public <T> Gauge<T> newGauge(String name, boolean replaceExisting, Supplier<T> gauge) {
192-
return monitors.get(0).newGauge(name, replaceExisting, gauge);
193-
}
194-
195-
@Override
196-
public Histogram newHistogram(String name) {
197-
List<Histogram> histograms = monitors.stream()
198-
.map(m -> m.newHistogram(name))
199-
.collect(Collectors.toList());
200-
201-
return new MultiHistogram(histograms);
202-
}
203-
204-
/**
205-
* {@inheritDoc}
206-
* <p>
207-
* Remove the metric only from the instance monitor. There would be JMX conflicts with the summary monitor
208-
* which is typically shared by multiple instances.
209-
*
210-
* @param metric metric to unregister
211-
*/
212-
@Override
213-
public void remove(Metric metric) {
214-
monitors.get(0).remove(metric);
215-
}
216-
217-
@Override
218-
public void close() {
219-
monitors.forEach(Monitor::close);
220-
}
221-
22249
}

0 commit comments

Comments
 (0)