26
26
import com .arpnetworking .metrics .incubator .PeriodicMetrics ;
27
27
import com .arpnetworking .metrics .proxy .models .messages .Command ;
28
28
import com .arpnetworking .metrics .proxy .models .messages .Connect ;
29
+ import com .arpnetworking .metrics .proxy .models .messages .MetricReport ;
29
30
import com .arpnetworking .metrics .proxy .models .protocol .MessageProcessorsFactory ;
30
31
import com .arpnetworking .metrics .proxy .models .protocol .MessagesProcessor ;
31
32
import com .arpnetworking .steno .LogValueMapFactory ;
32
33
import com .arpnetworking .steno .Logger ;
33
34
import com .arpnetworking .steno .LoggerFactory ;
35
+ import com .arpnetworking .tsdcore .model .AggregatedData ;
36
+ import com .arpnetworking .tsdcore .model .Key ;
37
+ import com .arpnetworking .tsdcore .model .PeriodicData ;
34
38
import com .fasterxml .jackson .core .JsonProcessingException ;
35
39
import com .fasterxml .jackson .databind .ObjectMapper ;
36
40
import com .fasterxml .jackson .databind .node .JsonNodeFactory ;
37
41
import com .fasterxml .jackson .databind .node .ObjectNode ;
42
+ import com .google .common .collect .Maps ;
43
+ import com .google .common .collect .Sets ;
38
44
39
45
import java .util .List ;
46
+ import java .util .Map ;
47
+ import java .util .Set ;
40
48
41
49
/**
42
50
* Actor class to hold the state for a single connection.
@@ -96,6 +104,9 @@ public Receive createReceive() {
96
104
.log ();
97
105
getSelf ().tell (PoisonPill .getInstance (), getSelf ());
98
106
})
107
+ .match (PeriodicData .class , message -> {
108
+ processPeriodicData (message );
109
+ })
99
110
.matchAny (message -> {
100
111
if (_channel == null ) {
101
112
LOGGER .warn ()
@@ -179,6 +190,52 @@ public void sendCommand(final String command, final ObjectNode data) {
179
190
send (message );
180
191
}
181
192
193
+ /**
194
+ * Subscribe the connection to a stream.
195
+ *
196
+ * @param service The service to subscribe to.
197
+ * @param metric The metric to subscribe to.
198
+ * @param statistic The statistic to subscribe to.
199
+ */
200
+ public void subscribe (final String service , final String metric , final String statistic ) {
201
+ if (!_subscriptions .containsKey (service )) {
202
+ _subscriptions .put (service , Maps .newHashMap ());
203
+ }
204
+
205
+ final Map <String , Set <String >> metrics = _subscriptions .get (service );
206
+ if (!metrics .containsKey (metric )) {
207
+ metrics .put (metric , Sets .newHashSet ());
208
+ }
209
+
210
+ final Set <String > statistics = metrics .get (metric );
211
+ if (!statistics .contains (statistic )) {
212
+ statistics .add (statistic );
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Unsubscribe the connection from a stream.
218
+ *
219
+ * @param service The service to unsubscribe from.
220
+ * @param metric The metric to unsubscribe from.
221
+ * @param statistic The statistic to unsubscribe from.
222
+ */
223
+ public void unsubscribe (final String service , final String metric , final String statistic ) {
224
+ if (!_subscriptions .containsKey (service )) {
225
+ return ;
226
+ }
227
+
228
+ final Map <String , Set <String >> metrics = _subscriptions .get (service );
229
+ if (!metrics .containsKey (metric )) {
230
+ return ;
231
+ }
232
+
233
+ final Set <String > statistics = metrics .get (metric );
234
+ if (statistics .contains (statistic )) {
235
+ statistics .remove (statistic );
236
+ }
237
+ }
238
+
182
239
/**
183
240
* Accessor to this Connection's Telemetry actor.
184
241
*
@@ -198,6 +255,7 @@ public Object toLogValue() {
198
255
return LogValueMapFactory .builder (this )
199
256
.put ("connection" , _channel )
200
257
.put ("messageProcessors" , _messageProcessors )
258
+ .put ("subscriptions" , _subscriptions )
201
259
.build ();
202
260
}
203
261
@@ -206,11 +264,66 @@ public String toString() {
206
264
return toLogValue ().toString ();
207
265
}
208
266
267
+ private void processPeriodicData (final PeriodicData message ) {
268
+ final Key dimensions = message .getDimensions ();
269
+ final String host = dimensions .getHost ();
270
+ final String service = dimensions .getService ();
271
+ final Map <String , Set <String >> metrics = _subscriptions .get (service );
272
+ if (metrics == null ) {
273
+ LOGGER .trace ()
274
+ .setMessage ("Not sending MetricReport" )
275
+ .addData ("reason" , "service not found in subscriptions" )
276
+ .addData ("service" , service )
277
+ .log ();
278
+ return ;
279
+ }
280
+
281
+ for (final Map .Entry <String , AggregatedData > entry : message .getData ().entries ()) {
282
+ final String metric = entry .getKey ();
283
+ final AggregatedData datum = entry .getValue ();
284
+
285
+ final Set <String > stats = metrics .get (metric );
286
+ if (stats == null ) {
287
+ LOGGER .trace ()
288
+ .setMessage ("Not sending MetricReport" )
289
+ .addData ("reason" , "metric not found in subscriptions" )
290
+ .addData ("metric" , metric )
291
+ .log ();
292
+ continue ;
293
+ }
294
+
295
+ final String statisticName = datum .getStatistic ().getName ();
296
+ if (!stats .contains (statisticName )) {
297
+ LOGGER .trace ()
298
+ .setMessage ("Not sending MetricReport" )
299
+ .addData ("reason" , "statistic not found in subscriptions" )
300
+ .addData ("statistic" , statisticName )
301
+ .log ();
302
+ continue ;
303
+ }
304
+
305
+ final MetricReport metricReport = new MetricReport (
306
+ service ,
307
+ host ,
308
+ statisticName ,
309
+ metric ,
310
+ datum .getValue ().getValue (),
311
+ datum .getValue ().getUnit (),
312
+ message .getStart ());
313
+ for (final MessagesProcessor messagesProcessor : _messageProcessors ) {
314
+ if (messagesProcessor .handleMessage (metricReport )) {
315
+ break ;
316
+ }
317
+ }
318
+ }
319
+ }
320
+
209
321
private ActorRef _telemetry ;
210
322
private ActorRef _channel ;
211
323
212
324
private final PeriodicMetrics _metrics ;
213
325
private final List <MessagesProcessor > _messageProcessors ;
326
+ private final Map <String , Map <String , Set <String >>> _subscriptions = Maps .newHashMap ();
214
327
215
328
private static final String METRICS_PREFIX = "actors/connection/" ;
216
329
private static final String UNKNOWN_COMMAND_COUNTER = METRICS_PREFIX + "command/UNKNOWN" ;
0 commit comments