• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018, OpenCensus Authors
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 io.opencensus.contrib.dropwizard;
18 
19 import com.codahale.metrics.Counter;
20 import com.codahale.metrics.Gauge;
21 import com.codahale.metrics.Histogram;
22 import com.codahale.metrics.Meter;
23 import com.codahale.metrics.Timer;
24 import io.opencensus.common.Clock;
25 import io.opencensus.common.Timestamp;
26 import io.opencensus.implcore.common.MillisClock;
27 import io.opencensus.internal.DefaultVisibilityForTesting;
28 import io.opencensus.internal.Utils;
29 import io.opencensus.metrics.LabelKey;
30 import io.opencensus.metrics.LabelValue;
31 import io.opencensus.metrics.export.Metric;
32 import io.opencensus.metrics.export.MetricDescriptor;
33 import io.opencensus.metrics.export.MetricDescriptor.Type;
34 import io.opencensus.metrics.export.MetricProducer;
35 import io.opencensus.metrics.export.Point;
36 import io.opencensus.metrics.export.Summary;
37 import io.opencensus.metrics.export.Summary.Snapshot;
38 import io.opencensus.metrics.export.Summary.Snapshot.ValueAtPercentile;
39 import io.opencensus.metrics.export.TimeSeries;
40 import io.opencensus.metrics.export.Value;
41 import java.util.ArrayList;
42 import java.util.Arrays;
43 import java.util.Collection;
44 import java.util.Collections;
45 import java.util.List;
46 import java.util.Map.Entry;
47 import javax.annotation.Nullable;
48 
49 /**
50  * Collects DropWizard metrics from a list {@link com.codahale.metrics.MetricRegistry}s.
51  *
52  * <p>A {@link io.opencensus.metrics.export.MetricProducer} that wraps a DropWizardMetrics.
53  *
54  * @since 0.17
55  */
56 public class DropWizardMetrics extends MetricProducer {
57   @DefaultVisibilityForTesting static final String DEFAULT_UNIT = "1";
58   private final List<com.codahale.metrics.MetricRegistry> metricRegistryList;
59   private final Clock clock;
60   private final Timestamp cumulativeStartTimestamp;
61 
62   /**
63    * Hook the Dropwizard registry into the OpenCensus registry.
64    *
65    * @param metricRegistryList a list of {@link com.codahale.metrics.MetricRegistry}s.
66    * @since 0.17
67    */
DropWizardMetrics(List<com.codahale.metrics.MetricRegistry> metricRegistryList)68   public DropWizardMetrics(List<com.codahale.metrics.MetricRegistry> metricRegistryList) {
69     Utils.checkNotNull(metricRegistryList, "metricRegistryList");
70     Utils.checkListElementNotNull(metricRegistryList, "metricRegistryList");
71     this.metricRegistryList = metricRegistryList;
72     clock = MillisClock.getInstance();
73     cumulativeStartTimestamp = clock.now();
74   }
75 
76   /**
77    * Returns a {@code Metric} collected from {@link Gauge}.
78    *
79    * @param dropwizardName the metric name.
80    * @param gauge the gauge object to collect.
81    * @return a {@code Metric}.
82    */
83   @SuppressWarnings("rawtypes")
collectGauge(String dropwizardName, Gauge gauge)84   private @Nullable Metric collectGauge(String dropwizardName, Gauge gauge) {
85     String metricName = DropWizardUtils.generateFullMetricName(dropwizardName, "gauge");
86     String metricDescription = DropWizardUtils.generateFullMetricDescription(dropwizardName, gauge);
87 
88     // Figure out which gauge instance and call the right method to get value
89     Type type;
90     Value value;
91 
92     Object obj = gauge.getValue();
93     if (obj instanceof Number) {
94       type = Type.GAUGE_DOUBLE;
95       value = Value.doubleValue(((Number) obj).doubleValue());
96     } else if (obj instanceof Boolean) {
97       type = Type.GAUGE_INT64;
98       value = Value.longValue(((Boolean) obj) ? 1 : 0);
99     } else {
100       // Ignoring Gauge (gauge.getKey()) with unhandled type.
101       return null;
102     }
103 
104     MetricDescriptor metricDescriptor =
105         MetricDescriptor.create(
106             metricName, metricDescription, DEFAULT_UNIT, type, Collections.<LabelKey>emptyList());
107     TimeSeries timeSeries =
108         TimeSeries.createWithOnePoint(
109             Collections.<LabelValue>emptyList(), Point.create(value, clock.now()), null);
110     return Metric.createWithOneTimeSeries(metricDescriptor, timeSeries);
111   }
112 
113   /**
114    * Returns a {@code Metric} collected from {@link Counter}.
115    *
116    * @param dropwizardName the metric name.
117    * @param counter the counter object to collect.
118    * @return a {@code Metric}.
119    */
collectCounter(String dropwizardName, Counter counter)120   private Metric collectCounter(String dropwizardName, Counter counter) {
121     String metricName = DropWizardUtils.generateFullMetricName(dropwizardName, "counter");
122     String metricDescription =
123         DropWizardUtils.generateFullMetricDescription(dropwizardName, counter);
124 
125     MetricDescriptor metricDescriptor =
126         MetricDescriptor.create(
127             metricName,
128             metricDescription,
129             DEFAULT_UNIT,
130             Type.GAUGE_INT64,
131             Collections.<LabelKey>emptyList());
132     TimeSeries timeSeries =
133         TimeSeries.createWithOnePoint(
134             Collections.<LabelValue>emptyList(),
135             Point.create(Value.longValue(counter.getCount()), clock.now()),
136             null);
137     return Metric.createWithOneTimeSeries(metricDescriptor, timeSeries);
138   }
139 
140   /**
141    * Returns a {@code Metric} collected from {@link Meter}.
142    *
143    * @param dropwizardName the metric name.
144    * @param meter the meter object to collect
145    * @return a {@code Metric}.
146    */
collectMeter(String dropwizardName, Meter meter)147   private Metric collectMeter(String dropwizardName, Meter meter) {
148     String metricName = DropWizardUtils.generateFullMetricName(dropwizardName, "meter");
149     String metricDescription = DropWizardUtils.generateFullMetricDescription(dropwizardName, meter);
150 
151     MetricDescriptor metricDescriptor =
152         MetricDescriptor.create(
153             metricName,
154             metricDescription,
155             DEFAULT_UNIT,
156             Type.CUMULATIVE_INT64,
157             Collections.<LabelKey>emptyList());
158     TimeSeries timeSeries =
159         TimeSeries.createWithOnePoint(
160             Collections.<LabelValue>emptyList(),
161             Point.create(Value.longValue(meter.getCount()), clock.now()),
162             null);
163 
164     return Metric.createWithOneTimeSeries(metricDescriptor, timeSeries);
165   }
166 
167   /**
168    * Returns a {@code Metric} collected from {@link Histogram}.
169    *
170    * @param dropwizardName the metric name.
171    * @param histogram the histogram object to collect
172    * @return a {@code Metric}.
173    */
collectHistogram(String dropwizardName, Histogram histogram)174   private Metric collectHistogram(String dropwizardName, Histogram histogram) {
175     String metricName = DropWizardUtils.generateFullMetricName(dropwizardName, "histogram");
176     String metricDescription =
177         DropWizardUtils.generateFullMetricDescription(dropwizardName, histogram);
178     return collectSnapshotAndCount(
179         metricName, metricDescription, histogram.getSnapshot(), histogram.getCount());
180   }
181 
182   /**
183    * Returns a {@code Metric} collected from {@link Timer}.
184    *
185    * @param dropwizardName the metric name.
186    * @param timer the timer object to collect
187    * @return a {@code Metric}.
188    */
collectTimer(String dropwizardName, Timer timer)189   private Metric collectTimer(String dropwizardName, Timer timer) {
190     String metricName = DropWizardUtils.generateFullMetricName(dropwizardName, "timer");
191     String metricDescription = DropWizardUtils.generateFullMetricDescription(dropwizardName, timer);
192     return collectSnapshotAndCount(
193         metricName, metricDescription, timer.getSnapshot(), timer.getCount());
194   }
195 
196   /**
197    * Returns a {@code Metric} collected from {@link Snapshot}.
198    *
199    * @param metricName the metric name.
200    * @param metricDescription the metric description.
201    * @param codahaleSnapshot the snapshot object to collect
202    * @param count the value or count
203    * @return a {@code Metric}.
204    */
collectSnapshotAndCount( String metricName, String metricDescription, com.codahale.metrics.Snapshot codahaleSnapshot, long count)205   private Metric collectSnapshotAndCount(
206       String metricName,
207       String metricDescription,
208       com.codahale.metrics.Snapshot codahaleSnapshot,
209       long count) {
210     List<ValueAtPercentile> valueAtPercentiles =
211         Arrays.asList(
212             ValueAtPercentile.create(50.0, codahaleSnapshot.getMedian()),
213             ValueAtPercentile.create(75.0, codahaleSnapshot.get75thPercentile()),
214             ValueAtPercentile.create(98.0, codahaleSnapshot.get98thPercentile()),
215             ValueAtPercentile.create(99.0, codahaleSnapshot.get99thPercentile()),
216             ValueAtPercentile.create(99.9, codahaleSnapshot.get999thPercentile()));
217 
218     Snapshot snapshot = Snapshot.create((long) codahaleSnapshot.size(), 0.0, valueAtPercentiles);
219     Point point =
220         Point.create(Value.summaryValue(Summary.create(count, 0.0, snapshot)), clock.now());
221 
222     // TODO(mayurkale): OPTIMIZATION: Cache the MetricDescriptor objects.
223     MetricDescriptor metricDescriptor =
224         MetricDescriptor.create(
225             metricName,
226             metricDescription,
227             DEFAULT_UNIT,
228             Type.SUMMARY,
229             Collections.<LabelKey>emptyList());
230     TimeSeries timeSeries =
231         TimeSeries.createWithOnePoint(
232             Collections.<LabelValue>emptyList(), point, cumulativeStartTimestamp);
233 
234     return Metric.createWithOneTimeSeries(metricDescriptor, timeSeries);
235   }
236 
237   @Override
238   @SuppressWarnings("rawtypes")
getMetrics()239   public Collection<Metric> getMetrics() {
240     ArrayList<Metric> metrics = new ArrayList<Metric>();
241 
242     for (com.codahale.metrics.MetricRegistry metricRegistry : metricRegistryList) {
243       for (Entry<String, Counter> counterEntry : metricRegistry.getCounters().entrySet()) {
244         metrics.add(collectCounter(counterEntry.getKey(), counterEntry.getValue()));
245       }
246 
247       for (Entry<String, Gauge> gaugeEntry : metricRegistry.getGauges().entrySet()) {
248         Metric metric = collectGauge(gaugeEntry.getKey(), gaugeEntry.getValue());
249         if (metric != null) {
250           metrics.add(metric);
251         }
252       }
253 
254       for (Entry<String, Meter> counterEntry : metricRegistry.getMeters().entrySet()) {
255         metrics.add(collectMeter(counterEntry.getKey(), counterEntry.getValue()));
256       }
257 
258       for (Entry<String, Histogram> counterEntry : metricRegistry.getHistograms().entrySet()) {
259         metrics.add(collectHistogram(counterEntry.getKey(), counterEntry.getValue()));
260       }
261 
262       for (Entry<String, Timer> counterEntry : metricRegistry.getTimers().entrySet()) {
263         metrics.add(collectTimer(counterEntry.getKey(), counterEntry.getValue()));
264       }
265     }
266 
267     return metrics;
268   }
269 }
270