metrics command to dump all the Metric in the system.
- Add probe to measure the time spent querying for Mastership. Change-Id: I48fe37568a3261ee5b6229a3884e42a3a741b407
Showing
4 changed files
with
210 additions
and
1 deletions
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); |
152 | + final Context timer = startTimer(requestRoleTimer); | ||
153 | + try { | ||
140 | return store.requestRole(deviceId); | 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 | */ | ... | ... |
-
Please register or login to post a comment