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 <map> | 7 #include <map> |
8 | 8 |
9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
13 #include "base/metrics/statistics_recorder.h" | 13 #include "base/metrics/statistics_recorder.h" |
14 #include "base/synchronization/lock.h" | 14 #include "base/synchronization/lock.h" |
| 15 #include "base/time/time.h" |
15 #include "jni/RecordHistogram_jni.h" | 16 #include "jni/RecordHistogram_jni.h" |
16 | 17 |
17 namespace base { | 18 namespace base { |
18 namespace android { | 19 namespace android { |
19 namespace { | 20 namespace { |
20 | 21 |
21 // Simple thread-safe wrapper for caching histograms. This avoids | 22 // Simple thread-safe wrapper for caching histograms. This avoids |
22 // relatively expensive JNI string translation for each recording. | 23 // relatively expensive JNI string translation for each recording. |
23 class HistogramCache { | 24 class HistogramCache { |
24 public: | 25 public: |
(...skipping 14 matching lines...) Expand all Loading... |
39 return InsertLocked(j_histogram_key, histogram); | 40 return InsertLocked(j_histogram_key, histogram); |
40 } | 41 } |
41 | 42 |
42 HistogramBase* EnumeratedHistogram(JNIEnv* env, | 43 HistogramBase* EnumeratedHistogram(JNIEnv* env, |
43 jstring j_histogram_name, | 44 jstring j_histogram_name, |
44 jint j_histogram_key, | 45 jint j_histogram_key, |
45 jint j_boundary) { | 46 jint j_boundary) { |
46 DCHECK(j_histogram_name); | 47 DCHECK(j_histogram_name); |
47 DCHECK(j_histogram_key); | 48 DCHECK(j_histogram_key); |
48 HistogramBase* histogram = FindLocked(j_histogram_key); | 49 HistogramBase* histogram = FindLocked(j_histogram_key); |
49 if (histogram) | 50 int boundary = static_cast<int>(j_boundary); |
| 51 if (histogram) { |
| 52 DCHECK(histogram->HasConstructionArguments(1, boundary, boundary + 1)); |
50 return histogram; | 53 return histogram; |
| 54 } |
51 | 55 |
52 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); | 56 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
53 // Note: This caching bypasses the boundary validation that occurs between | |
54 // repeated lookups by the same name. It is up to the caller to ensure that | |
55 // the provided boundary remains consistent. | |
56 int boundary = static_cast<int>(j_boundary); | |
57 histogram = | 57 histogram = |
58 LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1, | 58 LinearHistogram::FactoryGet(histogram_name, 1, boundary, boundary + 1, |
59 HistogramBase::kUmaTargetedHistogramFlag); | 59 HistogramBase::kUmaTargetedHistogramFlag); |
60 return InsertLocked(j_histogram_key, histogram); | 60 return InsertLocked(j_histogram_key, histogram); |
61 } | 61 } |
62 | 62 |
| 63 HistogramBase* CustomTimesHistogram(JNIEnv* env, |
| 64 jstring j_histogram_name, |
| 65 jint j_histogram_key, |
| 66 jlong j_min, |
| 67 jlong j_max, |
| 68 jint j_bucket_count) { |
| 69 DCHECK(j_histogram_name); |
| 70 DCHECK(j_histogram_key); |
| 71 HistogramBase* histogram = FindLocked(j_histogram_key); |
| 72 int64 min = static_cast<int64>(j_min); |
| 73 int64 max = static_cast<int64>(j_max); |
| 74 int bucket_count = static_cast<int>(j_bucket_count); |
| 75 if (histogram) { |
| 76 DCHECK(histogram->HasConstructionArguments(min, max, bucket_count)); |
| 77 return histogram; |
| 78 } |
| 79 |
| 80 std::string histogram_name = ConvertJavaStringToUTF8(env, j_histogram_name); |
| 81 // This intentionally uses FactoryGet and not FactoryTimeGet. FactoryTimeGet |
| 82 // is just a convenience for constructing the underlying Histogram with |
| 83 // TimeDelta arguments. |
| 84 histogram = Histogram::FactoryGet(histogram_name, min, max, bucket_count, |
| 85 HistogramBase::kUmaTargetedHistogramFlag); |
| 86 return InsertLocked(j_histogram_key, histogram); |
| 87 } |
| 88 |
63 private: | 89 private: |
64 HistogramBase* FindLocked(jint j_histogram_key) { | 90 HistogramBase* FindLocked(jint j_histogram_key) { |
65 base::AutoLock locked(lock_); | 91 base::AutoLock locked(lock_); |
66 auto histogram_it = histograms_.find(j_histogram_key); | 92 auto histogram_it = histograms_.find(j_histogram_key); |
67 return histogram_it != histograms_.end() ? histogram_it->second : nullptr; | 93 return histogram_it != histograms_.end() ? histogram_it->second : nullptr; |
68 } | 94 } |
69 | 95 |
70 HistogramBase* InsertLocked(jint j_histogram_key, HistogramBase* histogram) { | 96 HistogramBase* InsertLocked(jint j_histogram_key, HistogramBase* histogram) { |
71 base::AutoLock locked(lock_); | 97 base::AutoLock locked(lock_); |
72 histograms_.insert(std::make_pair(j_histogram_key, histogram)); | 98 histograms_.insert(std::make_pair(j_histogram_key, histogram)); |
(...skipping 27 matching lines...) Expand all Loading... |
100 jint j_histogram_key, | 126 jint j_histogram_key, |
101 jint j_sample, | 127 jint j_sample, |
102 jint j_boundary) { | 128 jint j_boundary) { |
103 int sample = static_cast<int>(j_sample); | 129 int sample = static_cast<int>(j_sample); |
104 | 130 |
105 g_histograms.Get() | 131 g_histograms.Get() |
106 .EnumeratedHistogram(env, j_histogram_name, j_histogram_key, j_boundary) | 132 .EnumeratedHistogram(env, j_histogram_name, j_histogram_key, j_boundary) |
107 ->Add(sample); | 133 ->Add(sample); |
108 } | 134 } |
109 | 135 |
| 136 void RecordCustomTimesHistogramMilliseconds(JNIEnv* env, |
| 137 jclass clazz, |
| 138 jstring j_histogram_name, |
| 139 jint j_histogram_key, |
| 140 jlong j_duration, |
| 141 jlong j_min, |
| 142 jlong j_max, |
| 143 jint j_num_buckets) { |
| 144 g_histograms.Get() |
| 145 .CustomTimesHistogram(env, j_histogram_name, j_histogram_key, j_min, |
| 146 j_max, j_num_buckets) |
| 147 ->AddTime(TimeDelta::FromMilliseconds(static_cast<int64>(j_duration))); |
| 148 } |
| 149 |
110 void Initialize(JNIEnv* env, jclass) { | 150 void Initialize(JNIEnv* env, jclass) { |
111 StatisticsRecorder::Initialize(); | 151 StatisticsRecorder::Initialize(); |
112 } | 152 } |
113 | 153 |
114 // This backs a Java test util for testing histograms - | 154 // This backs a Java test util for testing histograms - |
115 // MetricsUtils.HistogramDelta. It should live in a test-specific file, but we | 155 // MetricsUtils.HistogramDelta. It should live in a test-specific file, but we |
116 // currently can't have test-specific native code packaged in test-specific Java | 156 // currently can't have test-specific native code packaged in test-specific Java |
117 // targets - see http://crbug.com/415945. | 157 // targets - see http://crbug.com/415945. |
118 jint GetHistogramValueCountForTesting(JNIEnv* env, | 158 jint GetHistogramValueCountForTesting(JNIEnv* env, |
119 jclass clazz, | 159 jclass clazz, |
120 jstring histogram_name, | 160 jstring histogram_name, |
121 jint sample) { | 161 jint sample) { |
122 HistogramBase* histogram = StatisticsRecorder::FindHistogram( | 162 HistogramBase* histogram = StatisticsRecorder::FindHistogram( |
123 android::ConvertJavaStringToUTF8(env, histogram_name)); | 163 android::ConvertJavaStringToUTF8(env, histogram_name)); |
124 if (histogram == nullptr) { | 164 if (histogram == nullptr) { |
125 // No samples have been recorded for this histogram (yet?). | 165 // No samples have been recorded for this histogram (yet?). |
126 return 0; | 166 return 0; |
127 } | 167 } |
128 | 168 |
129 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples(); | 169 scoped_ptr<HistogramSamples> samples = histogram->SnapshotSamples(); |
130 return samples->GetCount(static_cast<int>(sample)); | 170 return samples->GetCount(static_cast<int>(sample)); |
131 } | 171 } |
132 | 172 |
133 bool RegisterRecordHistogram(JNIEnv* env) { | 173 bool RegisterRecordHistogram(JNIEnv* env) { |
134 return RegisterNativesImpl(env); | 174 return RegisterNativesImpl(env); |
135 } | 175 } |
136 | 176 |
137 } // namespace android | 177 } // namespace android |
138 } // namespace base | 178 } // namespace base |
OLD | NEW |