blob: e3877e83502210c7b4320ce12d4ab2782fa83fb1 [file] [log] [blame]
Flavio Castro41b1f3a2015-07-31 13:51:32 -07001/*
Aaron Kruglikov1110b2c2016-02-02 16:24:37 -08002 * Copyright 2016 Open Networking Laboratory
Flavio Castro41b1f3a2015-07-31 13:51:32 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Aaron Kruglikov1110b2c2016-02-02 16:24:37 -080016package org.onosproject.utils;
Flavio Castro41b1f3a2015-07-31 13:51:32 -070017
Flavio Castro6e044612015-08-13 14:13:58 -070018import com.codahale.metrics.Counter;
Flavio Castro41b1f3a2015-07-31 13:51:32 -070019import com.codahale.metrics.Timer;
20import com.google.common.collect.Maps;
21import org.onlab.metrics.MetricsComponent;
22import org.onlab.metrics.MetricsFeature;
23import org.onlab.metrics.MetricsService;
24import org.onlab.osgi.DefaultServiceDirectory;
25
26import java.util.Map;
27import java.util.concurrent.TimeUnit;
28
29import static com.google.common.base.Preconditions.checkNotNull;
30
31/**
32 * Agent that implements usage and performance monitoring via the metrics service.
33 */
34public class MeteringAgent {
35
Flavio Castro6e044612015-08-13 14:13:58 -070036 private Counter exceptionCounter;
37 private Counter perObjExceptionCounter;
Flavio Castro41b1f3a2015-07-31 13:51:32 -070038 private MetricsService metricsService;
39 private MetricsComponent metricsComponent;
40 private MetricsFeature metricsFeature;
41 private final Map<String, Timer> perObjOpTimers = Maps.newConcurrentMap();
42 private final Map<String, Timer> perOpTimers = Maps.newConcurrentMap();
43 private Timer perPrimitiveTimer;
44 private Timer perObjTimer;
45 private MetricsFeature wildcard;
46 private final boolean activated;
47 private Context nullTimer;
48
49 /**
50 * Constructs a new MeteringAgent for a given distributed primitive.
51 * Instantiates the metrics service
52 * Initializes all the general metrics for that object
53 *
54 * @param primitiveName Type of primitive to be metered
55 * @param objName Global name of the primitive
Madan Jampanif97edc12015-08-31 14:41:01 -070056 * @param activated boolean flag for whether metering is enabled or not
Flavio Castro41b1f3a2015-07-31 13:51:32 -070057 */
58 public MeteringAgent(String primitiveName, String objName, boolean activated) {
59 checkNotNull(objName, "Object name cannot be null");
60 this.activated = activated;
61 nullTimer = new Context(null, "");
62 if (this.activated) {
63 this.metricsService = DefaultServiceDirectory.getService(MetricsService.class);
64 this.metricsComponent = metricsService.registerComponent(primitiveName);
65 this.metricsFeature = metricsComponent.registerFeature(objName);
66 this.wildcard = metricsComponent.registerFeature("*");
67 this.perObjTimer = metricsService.createTimer(metricsComponent, metricsFeature, "*");
68 this.perPrimitiveTimer = metricsService.createTimer(metricsComponent, wildcard, "*");
Flavio Castro6e044612015-08-13 14:13:58 -070069 this.perObjExceptionCounter = metricsService.createCounter(metricsComponent, metricsFeature, "exceptions");
70 this.exceptionCounter = metricsService.createCounter(metricsComponent, wildcard, "exceptions");
Flavio Castro41b1f3a2015-07-31 13:51:32 -070071 }
72 }
73
74 /**
75 * Initializes a specific timer for a given operation.
76 *
77 * @param op Specific operation being metered
Madan Jampanif97edc12015-08-31 14:41:01 -070078 * @return timer context
Flavio Castro41b1f3a2015-07-31 13:51:32 -070079 */
80 public Context startTimer(String op) {
81 if (!activated) {
82 return nullTimer;
83 }
84 // Check if timer exists, if it doesn't creates it
85 final Timer currTimer = perObjOpTimers.computeIfAbsent(op, timer ->
86 metricsService.createTimer(metricsComponent, metricsFeature, op));
87 perOpTimers.computeIfAbsent(op, timer -> metricsService.createTimer(metricsComponent, wildcard, op));
88 // Starts timer
89 return new Context(currTimer.time(), op);
90 }
91
92 /**
93 * Timer.Context with a specific operation.
94 */
95 public class Context {
96 private final Timer.Context context;
97 private final String operation;
98
99 /**
100 * Constructs Context.
101 *
Madan Jampanif97edc12015-08-31 14:41:01 -0700102 * @param context context
103 * @param operation operation name
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700104 */
105 public Context(Timer.Context context, String operation) {
106 this.context = context;
107 this.operation = operation;
108 }
109
110 /**
111 * Stops timer given a specific context and updates all related metrics.
Madan Jampanif97edc12015-08-31 14:41:01 -0700112 * @param e throwable
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700113 */
Flavio Castro6e044612015-08-13 14:13:58 -0700114 public void stop(Throwable e) {
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700115 if (!activated) {
116 return;
117 }
Flavio Castro6e044612015-08-13 14:13:58 -0700118 if (e == null) {
119 //Stop and updates timer with specific measurements per map, per operation
120 final long time = context.stop();
121 //updates timer with aggregated measurements per map
122 perOpTimers.get(operation).update(time, TimeUnit.NANOSECONDS);
123 //updates timer with aggregated measurements per map
124 perObjTimer.update(time, TimeUnit.NANOSECONDS);
125 //updates timer with aggregated measurements per all Consistent Maps
126 perPrimitiveTimer.update(time, TimeUnit.NANOSECONDS);
127 } else {
128 exceptionCounter.inc();
129 perObjExceptionCounter.inc();
130 }
Flavio Castro41b1f3a2015-07-31 13:51:32 -0700131 }
132 }
133
134}