Yuta HIGUCHI

metrics command to dump all the Metric in the system.

- Add probe to measure the time spent querying for Mastership.

Change-Id: I48fe37568a3261ee5b6229a3884e42a3a741b407
1 +/*
2 + * Copyright 2014 Open Networking Laboratory
3 + *
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 + */
16 +
17 +package org.onlab.onos.cli;
18 +
19 +import static java.lang.String.format;
20 +
21 +import java.util.Comparator;
22 +import java.util.Map;
23 +import java.util.Map.Entry;
24 +
25 +import org.apache.karaf.shell.commands.Command;
26 +import org.joda.time.LocalDateTime;
27 +import org.onlab.metrics.MetricsService;
28 +
29 +import com.codahale.metrics.Counter;
30 +import com.codahale.metrics.Gauge;
31 +import com.codahale.metrics.Histogram;
32 +import com.codahale.metrics.Meter;
33 +import com.codahale.metrics.Metric;
34 +import com.codahale.metrics.MetricFilter;
35 +import com.codahale.metrics.Snapshot;
36 +import com.codahale.metrics.Timer;
37 +import com.google.common.base.Strings;
38 +import com.google.common.collect.Ordering;
39 +import com.google.common.collect.TreeMultimap;
40 +
41 +/**
42 + * Prints metrics in the system.
43 + */
44 +@Command(scope = "onos", name = "metrics",
45 + description = "Prints metrics in the system")
46 +public class MetricsListCommand extends AbstractShellCommand {
47 +
48 + @Override
49 + protected void execute() {
50 + MetricsService metricsService = get(MetricsService.class);
51 +
52 + // TODO support filter condition
53 + MetricFilter filter = MetricFilter.ALL;
54 +
55 + TreeMultimap<String, Metric> matched = listMetrics(metricsService, filter);
56 + matched.asMap().forEach((name, metrics) -> {
57 + for (Metric metric : metrics) {
58 + // TODO JSON version
59 + printMetric(name, metric);
60 + }
61 + });
62 + }
63 +
64 + /**
65 + * Print metric object.
66 + *
67 + * @param name metric name
68 + * @param metric metric object
69 + */
70 + private void printMetric(String name, Metric metric) {
71 + final String heading;
72 +
73 + if (metric instanceof Counter) {
74 + heading = format("-- %s : [%s] --", name, "Counter");
75 + print(heading);
76 + Counter counter = (Counter) metric;
77 + print(" count = %d", counter.getCount());
78 +
79 + } else if (metric instanceof Gauge) {
80 + heading = format("-- %s : [%s] --", name, "Gauge");
81 + print(heading);
82 + @SuppressWarnings("rawtypes")
83 + Gauge gauge = (Gauge) metric;
84 + final Object value = gauge.getValue();
85 + if (name.endsWith("EpochMs") && value instanceof Long) {
86 + print(" value = %s (%s)", value, new LocalDateTime(value));
87 + } else {
88 + print(" value = %s", value);
89 + }
90 +
91 + } else if (metric instanceof Histogram) {
92 + heading = format("-- %s : [%s] --", name, "Histogram");
93 + print(heading);
94 + final Histogram histogram = (Histogram) metric;
95 + final Snapshot snapshot = histogram.getSnapshot();
96 + print(" count = %d", histogram.getCount());
97 + print(" min = %d", snapshot.getMin());
98 + print(" max = %d", snapshot.getMax());
99 + print(" mean = %f", snapshot.getMean());
100 + print(" stddev = %f", snapshot.getStdDev());
101 +
102 + } else if (metric instanceof Meter) {
103 + heading = format("-- %s : [%s] --", name, "Meter");
104 + print(heading);
105 + final Meter meter = (Meter) metric;
106 + print(" count = %d", meter.getCount());
107 + print(" mean rate = %f", meter.getMeanRate());
108 + print(" 1-minute rate = %f", meter.getOneMinuteRate());
109 + print(" 5-minute rate = %f", meter.getFiveMinuteRate());
110 + print(" 15-minute rate = %f", meter.getFifteenMinuteRate());
111 +
112 + } else if (metric instanceof Timer) {
113 + heading = format("-- %s : [%s] --", name, "Timer");
114 + print(heading);
115 + final Timer timer = (Timer) metric;
116 + final Snapshot snapshot = timer.getSnapshot();
117 + print(" count = %d", timer.getCount());
118 + print(" mean rate = %f", timer.getMeanRate());
119 + print(" 1-minute rate = %f", timer.getOneMinuteRate());
120 + print(" 5-minute rate = %f", timer.getFiveMinuteRate());
121 + print(" 15-minute rate = %f", timer.getFifteenMinuteRate());
122 + print(" min = %f ms", nanoToMs(snapshot.getMin()));
123 + print(" max = %f ms", nanoToMs(snapshot.getMax()));
124 + print(" mean = %f ms", nanoToMs(snapshot.getMean()));
125 + print(" stddev = %f ms", nanoToMs(snapshot.getStdDev()));
126 + } else {
127 + heading = format("-- %s : [%s] --", name, metric.getClass().getCanonicalName());
128 + print(heading);
129 + print("Unknown Metric type:{}", metric.getClass().getCanonicalName());
130 + }
131 + print(Strings.repeat("-", heading.length()));
132 + }
133 +
134 + @SuppressWarnings("rawtypes")
135 + private TreeMultimap<String, Metric> listMetrics(MetricsService metricsService, MetricFilter filter) {
136 + TreeMultimap<String, Metric> metrics = TreeMultimap.create(Comparator.naturalOrder(), Ordering.arbitrary());
137 +
138 + Map<String, Counter> counters = metricsService.getCounters(filter);
139 + for (Entry<String, Counter> entry : counters.entrySet()) {
140 + metrics.put(entry.getKey(), entry.getValue());
141 + }
142 + Map<String, Gauge> gauges = metricsService.getGauges(filter);
143 + for (Entry<String, Gauge> entry : gauges.entrySet()) {
144 + metrics.put(entry.getKey(), entry.getValue());
145 + }
146 + Map<String, Histogram> histograms = metricsService.getHistograms(filter);
147 + for (Entry<String, Histogram> entry : histograms.entrySet()) {
148 + metrics.put(entry.getKey(), entry.getValue());
149 + }
150 + Map<String, Meter> meters = metricsService.getMeters(filter);
151 + for (Entry<String, Meter> entry : meters.entrySet()) {
152 + metrics.put(entry.getKey(), entry.getValue());
153 + }
154 + Map<String, Timer> timers = metricsService.getTimers(filter);
155 + for (Entry<String, Timer> entry : timers.entrySet()) {
156 + metrics.put(entry.getKey(), entry.getValue());
157 + }
158 +
159 + return metrics;
160 + }
161 +
162 + private double nanoToMs(double nano) {
163 + return nano / 1_000_000D;
164 + }
165 +}
...@@ -19,6 +19,11 @@ ...@@ -19,6 +19,11 @@
19 <command> 19 <command>
20 <action class="org.onlab.onos.cli.SummaryCommand"/> 20 <action class="org.onlab.onos.cli.SummaryCommand"/>
21 </command> 21 </command>
22 +
23 + <command>
24 + <action class="org.onlab.onos.cli.MetricsListCommand"/>
25 + </command>
26 +
22 <command> 27 <command>
23 <action class="org.onlab.onos.cli.TabletMemberCommand"/> 28 <action class="org.onlab.onos.cli.TabletMemberCommand"/>
24 </command> 29 </command>
......
...@@ -27,6 +27,9 @@ import org.apache.felix.scr.annotations.Deactivate; ...@@ -27,6 +27,9 @@ import org.apache.felix.scr.annotations.Deactivate;
27 import org.apache.felix.scr.annotations.Reference; 27 import org.apache.felix.scr.annotations.Reference;
28 import org.apache.felix.scr.annotations.ReferenceCardinality; 28 import org.apache.felix.scr.annotations.ReferenceCardinality;
29 import org.apache.felix.scr.annotations.Service; 29 import org.apache.felix.scr.annotations.Service;
30 +import org.onlab.metrics.MetricsComponent;
31 +import org.onlab.metrics.MetricsFeature;
32 +import org.onlab.metrics.MetricsService;
30 import org.onlab.onos.cluster.ClusterEvent; 33 import org.onlab.onos.cluster.ClusterEvent;
31 import org.onlab.onos.cluster.ClusterEventListener; 34 import org.onlab.onos.cluster.ClusterEventListener;
32 import org.onlab.onos.cluster.ClusterService; 35 import org.onlab.onos.cluster.ClusterService;
...@@ -47,6 +50,9 @@ import org.onlab.onos.net.DeviceId; ...@@ -47,6 +50,9 @@ import org.onlab.onos.net.DeviceId;
47 import org.onlab.onos.net.MastershipRole; 50 import org.onlab.onos.net.MastershipRole;
48 import org.slf4j.Logger; 51 import org.slf4j.Logger;
49 52
53 +import com.codahale.metrics.Timer;
54 +import com.codahale.metrics.Timer.Context;
55 +
50 @Component(immediate = true) 56 @Component(immediate = true)
51 @Service 57 @Service
52 public class MastershipManager 58 public class MastershipManager
...@@ -72,10 +78,16 @@ public class MastershipManager ...@@ -72,10 +78,16 @@ public class MastershipManager
72 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) 78 @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
73 protected ClusterService clusterService; 79 protected ClusterService clusterService;
74 80
81 + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
82 + protected MetricsService metricsService;
83 +
75 private ClusterEventListener clusterListener = new InternalClusterEventListener(); 84 private ClusterEventListener clusterListener = new InternalClusterEventListener();
85 + private Timer requestRoleTimer;
76 86
77 @Activate 87 @Activate
78 public void activate() { 88 public void activate() {
89 + requestRoleTimer = createTimer("Mastership", "requestRole", "responseTime");
90 +
79 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry); 91 eventDispatcher.addSink(MastershipEvent.class, listenerRegistry);
80 clusterService.addListener(clusterListener); 92 clusterService.addListener(clusterListener);
81 store.setDelegate(delegate); 93 store.setDelegate(delegate);
...@@ -137,7 +149,12 @@ public class MastershipManager ...@@ -137,7 +149,12 @@ public class MastershipManager
137 @Override 149 @Override
138 public MastershipRole requestRoleFor(DeviceId deviceId) { 150 public MastershipRole requestRoleFor(DeviceId deviceId) {
139 checkNotNull(deviceId, DEVICE_ID_NULL); 151 checkNotNull(deviceId, DEVICE_ID_NULL);
140 - return store.requestRole(deviceId); 152 + final Context timer = startTimer(requestRoleTimer);
153 + try {
154 + return store.requestRole(deviceId);
155 + } finally {
156 + stopTimer(timer);
157 + }
141 } 158 }
142 159
143 @Override 160 @Override
...@@ -186,6 +203,28 @@ public class MastershipManager ...@@ -186,6 +203,28 @@ public class MastershipManager
186 203
187 204
188 205
206 + private Timer createTimer(String component, String feature, String name) {
207 + if (metricsService != null) {
208 + MetricsComponent c = metricsService.registerComponent(component);
209 + MetricsFeature f = c.registerFeature(feature);
210 + return metricsService.createTimer(c, f, name);
211 + }
212 + return null;
213 + }
214 +
215 + private static final Context startTimer(Timer timer) {
216 + if (timer != null) {
217 + return timer.time();
218 + }
219 + return null;
220 + }
221 +
222 + private static final void stopTimer(Context context) {
223 + if (context != null) {
224 + context.stop();
225 + }
226 + }
227 +
189 //callback for reacting to cluster events 228 //callback for reacting to cluster events
190 private class InternalClusterEventListener implements ClusterEventListener { 229 private class InternalClusterEventListener implements ClusterEventListener {
191 230
......
...@@ -154,7 +154,7 @@ public class MetricsManager implements MetricsService { ...@@ -154,7 +154,7 @@ public class MetricsManager implements MetricsService {
154 * Creates a Timer metric. 154 * Creates a Timer metric.
155 * 155 *
156 * @param component component the Timer is defined in 156 * @param component component the Timer is defined in
157 - * @param feature feature the Timeer is defined in 157 + * @param feature feature the Timer is defined in
158 * @param metricName local name of the metric 158 * @param metricName local name of the metric
159 * @return the created Timer Metric 159 * @return the created Timer Metric
160 */ 160 */
......