OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/android/record_histogram.h" | 5 #include "base/android/record_histogram.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <map> | 9 #include <map> |
| 10 #include <string> |
10 | 11 |
11 #include "base/android/jni_android.h" | 12 #include "base/android/jni_android.h" |
12 #include "base/android/jni_string.h" | 13 #include "base/android/jni_string.h" |
13 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
14 #include "base/macros.h" | 15 #include "base/macros.h" |
15 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
16 #include "base/metrics/sparse_histogram.h" | 17 #include "base/metrics/sparse_histogram.h" |
17 #include "base/metrics/statistics_recorder.h" | 18 #include "base/metrics/statistics_recorder.h" |
18 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
19 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 HistogramBase* histogram) { | 57 HistogramBase* histogram) { |
57 DCHECK(histogram->HasConstructionArguments(expected_min, expected_max, | 58 DCHECK(histogram->HasConstructionArguments(expected_min, expected_max, |
58 expected_bucket_count)) | 59 expected_bucket_count)) |
59 << ConvertJavaStringToUTF8(env, j_histogram_name) << "/" << expected_min | 60 << ConvertJavaStringToUTF8(env, j_histogram_name) << "/" << expected_min |
60 << "/" << expected_max << "/" << expected_bucket_count << " vs. " | 61 << "/" << expected_max << "/" << expected_bucket_count << " vs. " |
61 << HistogramConstructionParamsToString(histogram); | 62 << HistogramConstructionParamsToString(histogram); |
62 } | 63 } |
63 | 64 |
64 HistogramBase* BooleanHistogram(JNIEnv* env, | 65 HistogramBase* BooleanHistogram(JNIEnv* env, |
65 jstring j_histogram_name, | 66 jstring j_histogram_name, |
66 jint j_histogram_key) { | 67 jlong j_histogram_key) { |
67 DCHECK(j_histogram_name); | 68 DCHECK(j_histogram_name); |
68 DCHECK(j_histogram_key); | 69 HistogramBase* histogram = HistogramFromKey(j_histogram_key); |
69 HistogramBase* histogram = FindLocked(j_histogram_key); | |
70 if (histogram) | 70 if (histogram) |
71 return histogram; | 71 return histogram; |
72 | 72 |
73 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 73 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
74 histogram = BooleanHistogram::FactoryGet( | 74 histogram = BooleanHistogram::FactoryGet( |
75 histogram_name, HistogramBase::kUmaTargetedHistogramFlag); | 75 histogram_name, HistogramBase::kUmaTargetedHistogramFlag); |
76 return InsertLocked(j_histogram_key, histogram); | 76 return histogram; |
77 } | 77 } |
78 | 78 |
79 HistogramBase* EnumeratedHistogram(JNIEnv* env, | 79 HistogramBase* EnumeratedHistogram(JNIEnv* env, |
80 jstring j_histogram_name, | 80 jstring j_histogram_name, |
81 jint j_histogram_key, | 81 jlong j_histogram_key, |
82 jint j_boundary) { | 82 jint j_boundary) { |
83 DCHECK(j_histogram_name); | 83 DCHECK(j_histogram_name); |
84 DCHECK(j_histogram_key); | 84 HistogramBase* histogram = HistogramFromKey(j_histogram_key); |
85 HistogramBase* histogram = FindLocked(j_histogram_key); | |
86 int32_t boundary = static_cast<int32_t>(j_boundary); | 85 int32_t boundary = static_cast<int32_t>(j_boundary); |
87 if (histogram) { | 86 if (histogram) { |
88 CheckHistogramArgs(env, j_histogram_name, 1, boundary, boundary + 1, | 87 CheckHistogramArgs(env, j_histogram_name, 1, boundary, boundary + 1, |
89 histogram); | 88 histogram); |
90 return histogram; | 89 return histogram; |
91 } | 90 } |
92 | 91 |
93 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 92 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
94 histogram = | 93 histogram = |
95 LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1, | 94 LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1, |
96 HistogramBase::kUmaTargetedHistogramFlag); | 95 HistogramBase::kUmaTargetedHistogramFlag); |
97 return InsertLocked(j_histogram_key, histogram); | 96 return histogram; |
98 } | 97 } |
99 | 98 |
100 HistogramBase* CustomCountHistogram(JNIEnv* env, | 99 HistogramBase* CustomCountHistogram(JNIEnv* env, |
101 jstring j_histogram_name, | 100 jstring j_histogram_name, |
102 jint j_histogram_key, | 101 jlong j_histogram_key, |
103 jint j_min, | 102 jint j_min, |
104 jint j_max, | 103 jint j_max, |
105 jint j_num_buckets) { | 104 jint j_num_buckets) { |
106 DCHECK(j_histogram_name); | 105 DCHECK(j_histogram_name); |
107 DCHECK(j_histogram_key); | |
108 int32_t min = static_cast<int32_t>(j_min); | 106 int32_t min = static_cast<int32_t>(j_min); |
109 int32_t max = static_cast<int32_t>(j_max); | 107 int32_t max = static_cast<int32_t>(j_max); |
110 int32_t num_buckets = static_cast<int32_t>(j_num_buckets); | 108 int32_t num_buckets = static_cast<int32_t>(j_num_buckets); |
111 HistogramBase* histogram = FindLocked(j_histogram_key); | 109 HistogramBase* histogram = HistogramFromKey(j_histogram_key); |
112 if (histogram) { | 110 if (histogram) { |
113 CheckHistogramArgs(env, j_histogram_name, min, max, num_buckets, | 111 CheckHistogramArgs(env, j_histogram_name, min, max, num_buckets, |
114 histogram); | 112 histogram); |
115 return histogram; | 113 return histogram; |
116 } | 114 } |
117 | 115 |
118 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 116 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
119 histogram = | 117 histogram = |
120 Histogram::FactoryGet(histogram_name, min, max, num_buckets, | 118 Histogram::FactoryGet(histogram_name, min, max, num_buckets, |
121 HistogramBase::kUmaTargetedHistogramFlag); | 119 HistogramBase::kUmaTargetedHistogramFlag); |
122 return InsertLocked(j_histogram_key, histogram); | 120 return histogram; |
123 } | 121 } |
124 | 122 |
125 HistogramBase* LinearCountHistogram(JNIEnv* env, | 123 HistogramBase* LinearCountHistogram(JNIEnv* env, |
126 jstring j_histogram_name, | 124 jstring j_histogram_name, |
127 jint j_histogram_key, | 125 jlong j_histogram_key, |
128 jint j_min, | 126 jint j_min, |
129 jint j_max, | 127 jint j_max, |
130 jint j_num_buckets) { | 128 jint j_num_buckets) { |
131 DCHECK(j_histogram_name); | 129 DCHECK(j_histogram_name); |
132 DCHECK(j_histogram_key); | |
133 int32_t min = static_cast<int32_t>(j_min); | 130 int32_t min = static_cast<int32_t>(j_min); |
134 int32_t max = static_cast<int32_t>(j_max); | 131 int32_t max = static_cast<int32_t>(j_max); |
135 int32_t num_buckets = static_cast<int32_t>(j_num_buckets); | 132 int32_t num_buckets = static_cast<int32_t>(j_num_buckets); |
136 HistogramBase* histogram = FindLocked(j_histogram_key); | 133 HistogramBase* histogram = HistogramFromKey(j_histogram_key); |
137 if (histogram) { | 134 if (histogram) { |
138 CheckHistogramArgs(env, j_histogram_name, min, max, num_buckets, | 135 CheckHistogramArgs(env, j_histogram_name, min, max, num_buckets, |
139 histogram); | 136 histogram); |
140 return histogram; | 137 return histogram; |
141 } | 138 } |
142 | 139 |
143 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 140 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
144 histogram = | 141 histogram = |
145 LinearHistogram::FactoryGet(histogram_name, min, max, num_buckets, | 142 LinearHistogram::FactoryGet(histogram_name, min, max, num_buckets, |
146 HistogramBase::kUmaTargetedHistogramFlag); | 143 HistogramBase::kUmaTargetedHistogramFlag); |
147 return InsertLocked(j_histogram_key, histogram); | 144 return histogram; |
148 } | 145 } |
149 | 146 |
150 HistogramBase* SparseHistogram(JNIEnv* env, | 147 HistogramBase* SparseHistogram(JNIEnv* env, |
151 jstring j_histogram_name, | 148 jstring j_histogram_name, |
152 jint j_histogram_key) { | 149 jlong j_histogram_key) { |
153 DCHECK(j_histogram_name); | 150 DCHECK(j_histogram_name); |
154 DCHECK(j_histogram_key); | 151 HistogramBase* histogram = HistogramFromKey(j_histogram_key); |
155 HistogramBase* histogram = FindLocked(j_histogram_key); | |
156 if (histogram) | 152 if (histogram) |
157 return histogram; | 153 return histogram; |
158 | 154 |
159 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 155 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
160 histogram = SparseHistogram::FactoryGet( | 156 histogram = SparseHistogram::FactoryGet( |
161 histogram_name, HistogramBase::kUmaTargetedHistogramFlag); | 157 histogram_name, HistogramBase::kUmaTargetedHistogramFlag); |
162 return InsertLocked(j_histogram_key, histogram); | 158 return histogram; |
163 } | 159 } |
164 | 160 |
165 HistogramBase* CustomTimesHistogram(JNIEnv* env, | 161 HistogramBase* CustomTimesHistogram(JNIEnv* env, |
166 jstring j_histogram_name, | 162 jstring j_histogram_name, |
167 jint j_histogram_key, | 163 jlong j_histogram_key, |
168 jint j_min, | 164 jint j_min, |
169 jint j_max, | 165 jint j_max, |
170 jint j_bucket_count) { | 166 jint j_bucket_count) { |
171 DCHECK(j_histogram_name); | 167 DCHECK(j_histogram_name); |
172 DCHECK(j_histogram_key); | 168 HistogramBase* histogram = HistogramFromKey(j_histogram_key); |
173 HistogramBase* histogram = FindLocked(j_histogram_key); | |
174 int32_t min = static_cast<int32_t>(j_min); | 169 int32_t min = static_cast<int32_t>(j_min); |
175 int32_t max = static_cast<int32_t>(j_max); | 170 int32_t max = static_cast<int32_t>(j_max); |
176 int32_t bucket_count = static_cast<int32_t>(j_bucket_count); | 171 int32_t bucket_count = static_cast<int32_t>(j_bucket_count); |
177 if (histogram) { | 172 if (histogram) { |
178 CheckHistogramArgs(env, j_histogram_name, min, max, bucket_count, | 173 CheckHistogramArgs(env, j_histogram_name, min, max, bucket_count, |
179 histogram); | 174 histogram); |
180 return histogram; | 175 return histogram; |
181 } | 176 } |
182 | 177 |
183 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 178 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
184 // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet | 179 // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet |
185 // is just a convenience for constructing the underlying Histogram with | 180 // is just a convenience for constructing the underlying Histogram with |
186 // TimeDelta arguments. | 181 // TimeDelta arguments. |
187 histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count, | 182 histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count, |
188 HistogramBase::kUmaTargetedHistogramFlag); | 183 HistogramBase::kUmaTargetedHistogramFlag); |
189 return InsertLocked(j_histogram_key, histogram); | 184 return histogram; |
190 } | 185 } |
191 | 186 |
192 private: | 187 private: |
193 HistogramBase* FindLocked(jint j_histogram_key) { | 188 // Convert a jlong |histogram_key| from Java to a HistogramBase* via a cast. |
194 AutoLock locked(lock_); | 189 // The Java side caches these in a map (see RecordHistogram.java), which is |
195 auto histogram_it = histograms_.find(j_histogram_key); | 190 // safe to do since C++ Histogram objects are never freed. |
196 return histogram_it != histograms_.end() ? histogram_it->second : nullptr; | 191 static HistogramBase* HistogramFromKey(jlong j_histogram_key) { |
| 192 return reinterpret_cast<HistogramBase*>(j_histogram_key); |
197 } | 193 } |
198 | 194 |
199 HistogramBase* InsertLocked(jint j_histogram_key, HistogramBase* histogram) { | |
200 AutoLock locked(lock_); | |
201 histograms_.insert(std::make_pair(j_histogram_key, histogram)); | |
202 return histogram; | |
203 } | |
204 | |
205 Lock lock_; | |
206 std::map<jint, HistogramBase*> histograms_; | |
207 | |
208 DISALLOW_COPY_AND_ASSIGN(HistogramCache); | 195 DISALLOW_COPY_AND_ASSIGN(HistogramCache); |
209 }; | 196 }; |
210 | 197 |
211 LazyInstance<HistogramCache>::Leaky g_histograms; | 198 LazyInstance<HistogramCache>::Leaky g_histograms; |
212 | 199 |
213 } // namespace | 200 } // namespace |
214 | 201 |
215 void RecordBooleanHistogram(JNIEnv* env, | 202 jlong RecordBooleanHistogram(JNIEnv* env, |
| 203 const JavaParamRef<jclass>& clazz, |
| 204 const JavaParamRef<jstring>& j_histogram_name, |
| 205 jlong j_histogram_key, |
| 206 jboolean j_sample) { |
| 207 bool sample = static_cast<bool>(j_sample); |
| 208 HistogramBase* histogram = g_histograms.Get().BooleanHistogram( |
| 209 env, j_histogram_name, j_histogram_key); |
| 210 histogram->AddBoolean(sample); |
| 211 return reinterpret_cast<jlong>(histogram); |
| 212 } |
| 213 |
| 214 jlong RecordEnumeratedHistogram(JNIEnv* env, |
| 215 const JavaParamRef<jclass>& clazz, |
| 216 const JavaParamRef<jstring>& j_histogram_name, |
| 217 jlong j_histogram_key, |
| 218 jint j_sample, |
| 219 jint j_boundary) { |
| 220 int sample = static_cast<int>(j_sample); |
| 221 |
| 222 HistogramBase* histogram = g_histograms.Get().EnumeratedHistogram( |
| 223 env, j_histogram_name, j_histogram_key, j_boundary); |
| 224 histogram->Add(sample); |
| 225 return reinterpret_cast<jlong>(histogram); |
| 226 } |
| 227 |
| 228 jlong RecordCustomCountHistogram(JNIEnv* env, |
| 229 const JavaParamRef<jclass>& clazz, |
| 230 const JavaParamRef<jstring>& j_histogram_name, |
| 231 jlong j_histogram_key, |
| 232 jint j_sample, |
| 233 jint j_min, |
| 234 jint j_max, |
| 235 jint j_num_buckets) { |
| 236 int sample = static_cast<int>(j_sample); |
| 237 |
| 238 HistogramBase* histogram = g_histograms.Get().CustomCountHistogram( |
| 239 env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets); |
| 240 histogram->Add(sample); |
| 241 return reinterpret_cast<jlong>(histogram); |
| 242 } |
| 243 |
| 244 jlong RecordLinearCountHistogram(JNIEnv* env, |
| 245 const JavaParamRef<jclass>& clazz, |
| 246 const JavaParamRef<jstring>& j_histogram_name, |
| 247 jlong j_histogram_key, |
| 248 jint j_sample, |
| 249 jint j_min, |
| 250 jint j_max, |
| 251 jint j_num_buckets) { |
| 252 int sample = static_cast<int>(j_sample); |
| 253 |
| 254 HistogramBase* histogram = g_histograms.Get().LinearCountHistogram( |
| 255 env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets); |
| 256 histogram->Add(sample); |
| 257 return reinterpret_cast<jlong>(histogram); |
| 258 } |
| 259 |
| 260 jlong RecordSparseHistogram(JNIEnv* env, |
216 const JavaParamRef<jclass>& clazz, | 261 const JavaParamRef<jclass>& clazz, |
217 const JavaParamRef<jstring>& j_histogram_name, | 262 const JavaParamRef<jstring>& j_histogram_name, |
218 jint j_histogram_key, | 263 jlong j_histogram_key, |
219 jboolean j_sample) { | 264 jint j_sample) { |
220 bool sample = static_cast<bool>(j_sample); | 265 int sample = static_cast<int>(j_sample); |
221 g_histograms.Get() | 266 HistogramBase* histogram = g_histograms.Get().SparseHistogram( |
222 .BooleanHistogram(env, j_histogram_name, j_histogram_key) | 267 env, j_histogram_name, j_histogram_key); |
223 ->AddBoolean(sample); | 268 histogram->Add(sample); |
| 269 return reinterpret_cast<jlong>(histogram); |
224 } | 270 } |
225 | 271 |
226 void RecordEnumeratedHistogram(JNIEnv* env, | 272 jlong RecordCustomTimesHistogramMilliseconds( |
227 const JavaParamRef<jclass>& clazz, | |
228 const JavaParamRef<jstring>& j_histogram_name, | |
229 jint j_histogram_key, | |
230 jint j_sample, | |
231 jint j_boundary) { | |
232 int sample = static_cast<int>(j_sample); | |
233 | |
234 g_histograms.Get() | |
235 .EnumeratedHistogram(env, j_histogram_name, j_histogram_key, j_boundary) | |
236 ->Add(sample); | |
237 } | |
238 | |
239 void RecordCustomCountHistogram(JNIEnv* env, | |
240 const JavaParamRef<jclass>& clazz, | |
241 const JavaParamRef<jstring>& j_histogram_name, | |
242 jint j_histogram_key, | |
243 jint j_sample, | |
244 jint j_min, | |
245 jint j_max, | |
246 jint j_num_buckets) { | |
247 int sample = static_cast<int>(j_sample); | |
248 | |
249 g_histograms.Get() | |
250 .CustomCountHistogram(env, j_histogram_name, j_histogram_key, j_min, | |
251 j_max, j_num_buckets) | |
252 ->Add(sample); | |
253 } | |
254 | |
255 void RecordLinearCountHistogram(JNIEnv* env, | |
256 const JavaParamRef<jclass>& clazz, | |
257 const JavaParamRef<jstring>& j_histogram_name, | |
258 jint j_histogram_key, | |
259 jint j_sample, | |
260 jint j_min, | |
261 jint j_max, | |
262 jint j_num_buckets) { | |
263 int sample = static_cast<int>(j_sample); | |
264 | |
265 g_histograms.Get() | |
266 .LinearCountHistogram(env, j_histogram_name, j_histogram_key, j_min, | |
267 j_max, j_num_buckets) | |
268 ->Add(sample); | |
269 } | |
270 | |
271 void RecordSparseHistogram(JNIEnv* env, | |
272 const JavaParamRef<jclass>& clazz, | |
273 const JavaParamRef<jstring>& j_histogram_name, | |
274 jint j_histogram_key, | |
275 jint j_sample) { | |
276 int sample = static_cast<int>(j_sample); | |
277 g_histograms.Get() | |
278 .SparseHistogram(env, j_histogram_name, j_histogram_key) | |
279 ->Add(sample); | |
280 } | |
281 | |
282 void RecordCustomTimesHistogramMilliseconds( | |
283 JNIEnv* env, | 273 JNIEnv* env, |
284 const JavaParamRef<jclass>& clazz, | 274 const JavaParamRef<jclass>& clazz, |
285 const JavaParamRef<jstring>& j_histogram_name, | 275 const JavaParamRef<jstring>& j_histogram_name, |
286 jint j_histogram_key, | 276 jlong j_histogram_key, |
287 jint j_duration, | 277 jint j_duration, |
288 jint j_min, | 278 jint j_min, |
289 jint j_max, | 279 jint j_max, |
290 jint j_num_buckets) { | 280 jint j_num_buckets) { |
291 g_histograms.Get() | 281 HistogramBase* histogram = g_histograms.Get().CustomTimesHistogram( |
292 .CustomTimesHistogram(env, j_histogram_name, j_histogram_key, j_min, | 282 env, j_histogram_name, j_histogram_key, j_min, j_max, j_num_buckets); |
293 j_max, j_num_buckets) | 283 histogram->AddTime( |
294 ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64_t>(j_duration))); | 284 TimeDelta::FromMilliseconds(static_cast<int64_t>(j_duration))); |
| 285 return reinterpret_cast<jlong>(histogram); |
295 } | 286 } |
296 | 287 |
297 void Initialize(JNIEnv* env, const JavaParamRef<jclass>&) { | 288 void Initialize(JNIEnv* env, const JavaParamRef<jclass>&) { |
298 StatisticsRecorder::Initialize(); | 289 StatisticsRecorder::Initialize(); |
299 } | 290 } |
300 | 291 |
301 // This backs a Java test util for testing histograms - | 292 // This backs a Java test util for testing histograms - |
302 // MetricsUtils.HistogramDelta. It should live in a test-specific file, but we | 293 // MetricsUtils.HistogramDelta. It should live in a test-specific file, but we |
303 // currently can't have test-specific native code packaged in test-specific Java | 294 // currently can't have test-specific native code packaged in test-specific Java |
304 // targets - see http://crbug.com/415945. | 295 // targets - see http://crbug.com/415945. |
(...skipping 12 matching lines...) Expand all Loading... |
317 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples(); | 308 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples(); |
318 return samples->GetCount(static_cast<int>(sample)); | 309 return samples->GetCount(static_cast<int>(sample)); |
319 } | 310 } |
320 | 311 |
321 bool RegisterRecordHistogram(JNIEnv* env) { | 312 bool RegisterRecordHistogram(JNIEnv* env) { |
322 return RegisterNativesImpl(env); | 313 return RegisterNativesImpl(env); |
323 } | 314 } |
324 | 315 |
325 } // namespace android | 316 } // namespace android |
326 } // namespace base | 317 } // namespace base |
OLD | NEW |