15
15
*/
16
16
package com .arpnetworking .metrics .mad ;
17
17
18
+ import akka .actor .ActorRef ;
19
+ import akka .actor .ActorSystem ;
20
+ import akka .actor .PoisonPill ;
21
+ import akka .actor .Props ;
18
22
import com .arpnetworking .commons .builder .OvalBuilder ;
19
23
import com .arpnetworking .commons .observer .Observable ;
20
24
import com .arpnetworking .commons .observer .Observer ;
35
39
import com .google .common .collect .ImmutableSet ;
36
40
import com .google .common .collect .Lists ;
37
41
import com .google .common .collect .Maps ;
38
- import edu .umd .cs .findbugs .annotations .SuppressFBWarnings ;
39
42
import net .sf .oval .constraint .NotNull ;
40
43
41
44
import java .time .Duration ;
44
47
import java .util .Map ;
45
48
import java .util .Optional ;
46
49
import java .util .Set ;
47
- import java .util .concurrent .ExecutorService ;
48
- import java .util .concurrent .Executors ;
49
- import java .util .concurrent .TimeUnit ;
50
50
import java .util .regex .Pattern ;
51
51
52
52
/**
56
56
* @author Ville Koskela (ville dot koskela at inscopemetrics dot io)
57
57
* @author Ryan Ascheman (rascheman at groupon dot com)
58
58
*/
59
- // NOTE: The _periodWorkerExecutor is accessed both in synchronized lifecycle methods like launch() and shutdown() but
60
- // also non-synchronized methods like notify(). Access to _periodWorkerExecutor does not need to be synchronized.
61
- @ SuppressFBWarnings ("IS2_INCONSISTENT_SYNC" )
62
59
public final class Aggregator implements Observer , Launchable {
63
60
64
61
@ Override
@@ -67,11 +64,6 @@ public synchronized void launch() {
67
64
.setMessage ("Launching aggregator" )
68
65
.addData ("aggregator" , this )
69
66
.log ();
70
-
71
- _periodWorkers .clear ();
72
- if (!_periods .isEmpty ()) {
73
- _periodWorkerExecutor = Executors .newCachedThreadPool (r -> new Thread (r , "PeriodWorker" ));
74
- }
75
67
}
76
68
77
69
@ Override
@@ -81,18 +73,10 @@ public synchronized void shutdown() {
81
73
.addData ("aggregator" , this )
82
74
.log ();
83
75
84
- for (final List <PeriodWorker > periodCloserList : _periodWorkers .values ()) {
85
- periodCloserList .forEach (com .arpnetworking .metrics .mad .PeriodWorker ::shutdown );
86
- }
87
- _periodWorkers .clear ();
88
- if (_periodWorkerExecutor != null ) {
89
- _periodWorkerExecutor .shutdown ();
90
- try {
91
- _periodWorkerExecutor .awaitTermination (10 , TimeUnit .SECONDS );
92
- } catch (final InterruptedException e ) {
93
- LOGGER .warn ("Unable to shutdown period worker executor" , e );
76
+ for (final List <ActorRef > actorRefList : _periodWorkerActors .values ()) {
77
+ for (final ActorRef actorRef : actorRefList ) {
78
+ actorRef .tell (PoisonPill .getInstance (), ActorRef .noSender ());
94
79
}
95
- _periodWorkerExecutor = null ;
96
80
}
97
81
}
98
82
@@ -109,12 +93,13 @@ public void notify(final Observable observable, final Object event) {
109
93
final Record record = (Record ) event ;
110
94
final Key key = new DefaultKey (record .getDimensions ());
111
95
LOGGER .trace ()
112
- .setMessage ("Processing record" )
96
+ .setMessage ("Sending record to aggregation actor " )
113
97
.addData ("record" , record )
114
98
.addData ("key" , key )
115
99
.log ();
116
- for (final PeriodWorker periodWorker : _periodWorkers .computeIfAbsent (key , this ::createPeriodWorkers )) {
117
- periodWorker .record (record );
100
+
101
+ for (final ActorRef periodWorkerActor : _periodWorkerActors .computeIfAbsent (key , this ::createActors )) {
102
+ periodWorkerActor .tell (record , ActorRef .noSender ());
118
103
}
119
104
}
120
105
@@ -130,7 +115,6 @@ public Object toLogValue() {
130
115
.put ("timerStatistics" , _specifiedTimerStatistics )
131
116
.put ("counterStatistics" , _specifiedCounterStatistics )
132
117
.put ("gaugeStatistics" , _specifiedGaugeStatistics )
133
- .put ("periodWorkers" , _periodWorkers )
134
118
.build ();
135
119
}
136
120
@@ -139,30 +123,25 @@ public String toString() {
139
123
return toLogValue ().toString ();
140
124
}
141
125
142
- private List <PeriodWorker > createPeriodWorkers (final Key key ) {
143
- final List <PeriodWorker > periodWorkerList = Lists .newArrayListWithExpectedSize (_periods .size ());
126
+ private List <ActorRef > createActors (final Key key ) {
127
+ final List <ActorRef > periodWorkerList = Lists .newArrayListWithExpectedSize (_periods .size ());
144
128
for (final Duration period : _periods ) {
145
- final PeriodWorker periodWorker = new PeriodWorker .Builder ()
129
+ final Bucket .Builder bucketBuilder = new Bucket .Builder ()
130
+ .setKey (key )
131
+ .setSpecifiedCounterStatistics (_specifiedCounterStatistics )
132
+ .setSpecifiedGaugeStatistics (_specifiedGaugeStatistics )
133
+ .setSpecifiedTimerStatistics (_specifiedTimerStatistics )
134
+ .setDependentCounterStatistics (_dependentCounterStatistics )
135
+ .setDependentGaugeStatistics (_dependentGaugeStatistics )
136
+ .setDependentTimerStatistics (_dependentTimerStatistics )
137
+ .setSpecifiedStatistics (_cachedSpecifiedStatistics )
138
+ .setDependentStatistics (_cachedDependentStatistics )
146
139
.setPeriod (period )
147
- .setBucketBuilder (
148
- new Bucket .Builder ()
149
- .setKey (key )
150
- .setSpecifiedCounterStatistics (_specifiedCounterStatistics )
151
- .setSpecifiedGaugeStatistics (_specifiedGaugeStatistics )
152
- .setSpecifiedTimerStatistics (_specifiedTimerStatistics )
153
- .setDependentCounterStatistics (_dependentCounterStatistics )
154
- .setDependentGaugeStatistics (_dependentGaugeStatistics )
155
- .setDependentTimerStatistics (_dependentTimerStatistics )
156
- .setSpecifiedStatistics (_cachedSpecifiedStatistics )
157
- .setDependentStatistics (_cachedDependentStatistics )
158
- .setPeriod (period )
159
- .setSink (_sink ))
160
- .build ();
161
- periodWorkerList .add (periodWorker );
162
- _periodWorkerExecutor .execute (periodWorker );
140
+ .setSink (_sink );
141
+ periodWorkerList .add (_actorSystem .actorOf (Props .create (PeriodWorker .class , period , bucketBuilder )));
163
142
}
164
143
LOGGER .debug ()
165
- .setMessage ("Created period workers " )
144
+ .setMessage ("Created period worker actors " )
166
145
.addData ("key" , key )
167
146
.addData ("periodWorkersSize" , periodWorkerList .size ())
168
147
.log ();
@@ -178,6 +157,7 @@ private ImmutableSet<Statistic> computeDependentStatistics(final ImmutableSet<St
178
157
}
179
158
180
159
private Aggregator (final Builder builder ) {
160
+ _actorSystem = builder ._actorSystem ;
181
161
_periods = ImmutableSet .copyOf (builder ._periods );
182
162
_sink = builder ._sink ;
183
163
_specifiedCounterStatistics = ImmutableSet .copyOf (builder ._counterStatistics );
@@ -223,8 +203,9 @@ public Optional<ImmutableSet<Statistic>> load(final String metric) throws Except
223
203
return statistics .map (statisticImmutableSet -> computeDependentStatistics (statisticImmutableSet ));
224
204
}
225
205
});
226
- }
206
+ }
227
207
208
+ private final ActorSystem _actorSystem ;
228
209
private final ImmutableSet <Duration > _periods ;
229
210
private final Sink _sink ;
230
211
private final ImmutableSet <Statistic > _specifiedTimerStatistics ;
@@ -236,9 +217,7 @@ public Optional<ImmutableSet<Statistic>> load(final String metric) throws Except
236
217
private final ImmutableMap <Pattern , ImmutableSet <Statistic >> _statistics ;
237
218
private final LoadingCache <String , Optional <ImmutableSet <Statistic >>> _cachedSpecifiedStatistics ;
238
219
private final LoadingCache <String , Optional <ImmutableSet <Statistic >>> _cachedDependentStatistics ;
239
- private final Map <Key , List <PeriodWorker >> _periodWorkers = Maps .newConcurrentMap ();
240
-
241
- private ExecutorService _periodWorkerExecutor = null ;
220
+ private final Map <Key , List <ActorRef >> _periodWorkerActors = Maps .newConcurrentMap ();
242
221
243
222
private static final Logger LOGGER = LoggerFactory .getLogger (Aggregator .class );
244
223
@@ -254,6 +233,17 @@ public Builder() {
254
233
super (Aggregator ::new );
255
234
}
256
235
236
+ /**
237
+ * Set the Akka {@link ActorSystem}. Cannot be null.
238
+ *
239
+ * @param value The Akka {@link ActorSystem}.
240
+ * @return This <code>Builder</code> instance.
241
+ */
242
+ public Builder setActorSystem (final ActorSystem value ) {
243
+ _actorSystem = value ;
244
+ return this ;
245
+ }
246
+
257
247
/**
258
248
* Set the sink. Cannot be null or empty.
259
249
*
@@ -321,6 +311,8 @@ public Builder setStatistics(final Map<String, Set<Statistic>> value) {
321
311
return this ;
322
312
}
323
313
314
+ @ NotNull
315
+ private ActorSystem _actorSystem ;
324
316
@ NotNull
325
317
private Sink _sink ;
326
318
@ NotNull
0 commit comments