Line data Source code
1 : // Copyright (C) 2015 The Android Open Source Project
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : package com.google.gerrit.metrics.dropwizard;
16 :
17 : import com.codahale.metrics.Counter;
18 : import com.codahale.metrics.Gauge;
19 : import com.codahale.metrics.Histogram;
20 : import com.codahale.metrics.Meter;
21 : import com.codahale.metrics.Metric;
22 : import com.codahale.metrics.Snapshot;
23 : import com.codahale.metrics.Timer;
24 : import com.google.common.collect.ImmutableList;
25 : import com.google.common.collect.ImmutableMap;
26 : import com.google.gerrit.common.Nullable;
27 : import com.google.gerrit.metrics.Description;
28 : import com.google.gerrit.metrics.Field;
29 : import java.util.ArrayList;
30 : import java.util.List;
31 : import java.util.Map;
32 : import java.util.TreeMap;
33 : import java.util.function.Function;
34 :
35 : class MetricJson {
36 : String description;
37 : String unit;
38 : Boolean constant;
39 : Boolean rate;
40 : Boolean gauge;
41 : Boolean cumulative;
42 :
43 : Long count;
44 : Object value;
45 :
46 : Double rate_1m;
47 : Double rate_5m;
48 : Double rate_15m;
49 : Double rate_mean;
50 :
51 : Double p50;
52 : Double p75;
53 : Double p95;
54 : Double p98;
55 : Double p99;
56 : Double p99_9;
57 :
58 : Double min;
59 : Double avg;
60 : Double max;
61 : Double sum;
62 : Double std_dev;
63 :
64 : List<FieldJson> fields;
65 : Map<String, Object> buckets;
66 :
67 0 : MetricJson(Metric metric, ImmutableMap<String, String> atts, boolean dataOnly) {
68 0 : if (!dataOnly) {
69 0 : description = atts.get(Description.DESCRIPTION);
70 0 : unit = atts.get(Description.UNIT);
71 0 : constant = toBool(atts, Description.CONSTANT);
72 0 : rate = toBool(atts, Description.RATE);
73 0 : gauge = toBool(atts, Description.GAUGE);
74 0 : cumulative = toBool(atts, Description.CUMULATIVE);
75 : }
76 0 : init(metric, atts);
77 0 : }
78 :
79 : private void init(Metric metric, ImmutableMap<String, String> atts) {
80 0 : if (metric instanceof BucketedMetric) {
81 0 : BucketedMetric m = (BucketedMetric) metric;
82 0 : if (m.getTotal() != null) {
83 0 : init(m.getTotal(), atts);
84 : }
85 :
86 0 : Field<?>[] fieldList = m.getFields();
87 0 : fields = new ArrayList<>(fieldList.length);
88 0 : for (Field<?> f : fieldList) {
89 0 : fields.add(new FieldJson(f));
90 : }
91 0 : buckets = makeBuckets(fieldList, m.getCells(), atts);
92 :
93 0 : } else if (metric instanceof Counter) {
94 0 : Counter c = (Counter) metric;
95 0 : count = c.getCount();
96 :
97 0 : } else if (metric instanceof Gauge) {
98 0 : Gauge<?> g = (Gauge<?>) metric;
99 0 : value = g.getValue();
100 :
101 0 : } else if (metric instanceof Meter) {
102 0 : Meter m = (Meter) metric;
103 0 : count = m.getCount();
104 0 : rate_1m = m.getOneMinuteRate();
105 0 : rate_5m = m.getFiveMinuteRate();
106 0 : rate_15m = m.getFifteenMinuteRate();
107 :
108 0 : } else if (metric instanceof Timer) {
109 0 : Timer m = (Timer) metric;
110 0 : Snapshot s = m.getSnapshot();
111 0 : count = m.getCount();
112 0 : rate_1m = m.getOneMinuteRate();
113 0 : rate_5m = m.getFiveMinuteRate();
114 0 : rate_15m = m.getFifteenMinuteRate();
115 :
116 0 : double div = Description.getTimeUnit(atts.get(Description.UNIT)).toNanos(1);
117 0 : p50 = s.getMedian() / div;
118 0 : p75 = s.get75thPercentile() / div;
119 0 : p95 = s.get95thPercentile() / div;
120 0 : p98 = s.get98thPercentile() / div;
121 0 : p99 = s.get99thPercentile() / div;
122 0 : p99_9 = s.get999thPercentile() / div;
123 :
124 0 : min = s.getMin() / div;
125 0 : max = s.getMax() / div;
126 0 : std_dev = s.getStdDev() / div;
127 :
128 0 : } else if (metric instanceof Histogram) {
129 0 : Histogram m = (Histogram) metric;
130 0 : Snapshot s = m.getSnapshot();
131 0 : count = m.getCount();
132 :
133 0 : p50 = s.getMedian();
134 0 : p75 = s.get75thPercentile();
135 0 : p95 = s.get95thPercentile();
136 0 : p98 = s.get98thPercentile();
137 0 : p99 = s.get99thPercentile();
138 0 : p99_9 = s.get999thPercentile();
139 :
140 0 : min = (double) s.getMin();
141 0 : avg = s.getMean();
142 0 : max = (double) s.getMax();
143 0 : sum = s.getMean() * m.getCount();
144 0 : std_dev = s.getStdDev();
145 : }
146 0 : }
147 :
148 : @Nullable
149 : private static Boolean toBool(ImmutableMap<String, String> atts, String key) {
150 0 : return Description.TRUE_VALUE.equals(atts.get(key)) ? true : null;
151 : }
152 :
153 : @SuppressWarnings("unchecked")
154 : private static Map<String, Object> makeBuckets(
155 : Field<?>[] fields, Map<?, Metric> metrics, ImmutableMap<String, String> atts) {
156 0 : if (fields.length == 1) {
157 0 : Function<Object, String> fmt = (Function<Object, String>) fields[0].formatter();
158 0 : Map<String, Object> out = new TreeMap<>();
159 0 : for (Map.Entry<?, Metric> e : metrics.entrySet()) {
160 0 : out.put(fmt.apply(e.getKey()), new MetricJson(e.getValue(), atts, true));
161 0 : }
162 0 : return out;
163 : }
164 :
165 0 : Map<String, Object> out = new TreeMap<>();
166 0 : for (Map.Entry<?, Metric> e : metrics.entrySet()) {
167 0 : ImmutableList<Object> keys = (ImmutableList<Object>) e.getKey();
168 0 : Map<String, Object> dst = out;
169 :
170 0 : for (int i = 0; i < fields.length - 1; i++) {
171 0 : Function<Object, String> fmt = (Function<Object, String>) fields[i].formatter();
172 0 : String key = fmt.apply(keys.get(i));
173 0 : Map<String, Object> t = (Map<String, Object>) dst.get(key);
174 0 : if (t == null) {
175 0 : t = new TreeMap<>();
176 0 : dst.put(key, t);
177 : }
178 0 : dst = t;
179 : }
180 :
181 0 : Function<Object, String> fmt =
182 0 : (Function<Object, String>) fields[fields.length - 1].formatter();
183 0 : dst.put(fmt.apply(keys.get(fields.length - 1)), new MetricJson(e.getValue(), atts, true));
184 0 : }
185 0 : return out;
186 : }
187 :
188 : static class FieldJson {
189 : String name;
190 : String type;
191 : String description;
192 :
193 0 : FieldJson(Field<?> field) {
194 0 : this.name = field.name();
195 0 : this.description = field.description().orElse(null);
196 0 : this.type =
197 0 : Enum.class.isAssignableFrom(field.valueType()) ? field.valueType().getSimpleName() : null;
198 0 : }
199 : }
200 : }
|