OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/metrics/call_stack_profile_metrics_provider.h" | 5 #include "components/metrics/call_stack_profile_metrics_provider.h" |
6 | 6 |
7 #include <cstring> | 7 #include <cstring> |
8 #include <map> | 8 #include <map> |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
| 11 #include "base/bind.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/macros.h" | 13 #include "base/macros.h" |
| 14 #include "base/message_loop/message_loop_proxy.h" |
| 15 #include "base/metrics/field_trial.h" |
13 #include "base/profiler/stack_sampling_profiler.h" | 16 #include "base/profiler/stack_sampling_profiler.h" |
14 #include "components/metrics/metrics_hashes.h" | 17 #include "components/metrics/metrics_hashes.h" |
15 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" | 18 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" |
16 | 19 |
17 using base::StackSamplingProfiler; | 20 using base::StackSamplingProfiler; |
18 | 21 |
19 namespace metrics { | 22 namespace metrics { |
20 | 23 |
21 namespace { | 24 namespace { |
22 | 25 |
| 26 // Accepts and ignores the completed profiles. Used when metrics reporting is |
| 27 // disabled. |
| 28 void IgnoreCompletedProfiles( |
| 29 const std::vector<base::StackSamplingProfiler::Profile>& profiles) { |
| 30 } |
| 31 |
23 // The protobuf expects the MD5 checksum prefix of the module name. | 32 // The protobuf expects the MD5 checksum prefix of the module name. |
24 uint64 HashModuleFilename(const base::FilePath& filename) { | 33 uint64 HashModuleFilename(const base::FilePath& filename) { |
25 const base::FilePath::StringType basename = filename.BaseName().value(); | 34 const base::FilePath::StringType basename = filename.BaseName().value(); |
26 // Copy the bytes in basename into a string buffer. | 35 // Copy the bytes in basename into a string buffer. |
27 size_t basename_length_in_bytes = | 36 size_t basename_length_in_bytes = |
28 basename.size() * sizeof(base::FilePath::CharType); | 37 basename.size() * sizeof(base::FilePath::CharType); |
29 std::string name_bytes(basename_length_in_bytes, '\0'); | 38 std::string name_bytes(basename_length_in_bytes, '\0'); |
30 memcpy(&name_bytes[0], &basename[0], basename_length_in_bytes); | 39 memcpy(&name_bytes[0], &basename[0], basename_length_in_bytes); |
31 return HashMetricName(name_bytes); | 40 return HashMetricName(name_bytes); |
32 } | 41 } |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 proto_profile->add_module_id(); | 106 proto_profile->add_module_id(); |
98 module_id->set_build_id(module.id); | 107 module_id->set_build_id(module.id); |
99 module_id->set_name_md5_prefix(HashModuleFilename(module.filename)); | 108 module_id->set_name_md5_prefix(HashModuleFilename(module.filename)); |
100 } | 109 } |
101 | 110 |
102 proto_profile->set_profile_duration_ms( | 111 proto_profile->set_profile_duration_ms( |
103 profile.profile_duration.InMilliseconds()); | 112 profile.profile_duration.InMilliseconds()); |
104 proto_profile->set_sampling_period_ms( | 113 proto_profile->set_sampling_period_ms( |
105 profile.sampling_period.InMilliseconds()); | 114 profile.sampling_period.InMilliseconds()); |
106 } | 115 } |
| 116 |
107 } // namespace | 117 } // namespace |
108 | 118 |
109 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() {} | 119 const char CallStackProfileMetricsProvider::kFieldTrialName[] = |
| 120 "StackProfiling"; |
| 121 const char CallStackProfileMetricsProvider::kReportProfilesGroupName[] = |
| 122 "Report profiles"; |
110 | 123 |
111 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() {} | 124 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() |
| 125 : weak_factory_(this) { |
| 126 } |
| 127 |
| 128 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() { |
| 129 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 130 StackSamplingProfiler::CompletedCallback()); |
| 131 } |
| 132 |
| 133 void CallStackProfileMetricsProvider::OnRecordingEnabled() { |
| 134 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 135 base::Bind(&CallStackProfileMetricsProvider::ReceiveCompletedProfiles, |
| 136 base::MessageLoopProxy::current(), |
| 137 weak_factory_.GetWeakPtr())); |
| 138 } |
| 139 |
| 140 void CallStackProfileMetricsProvider::OnRecordingDisabled() { |
| 141 StackSamplingProfiler::SetDefaultCompletedCallback( |
| 142 base::Bind(&IgnoreCompletedProfiles)); |
| 143 pending_profiles_.clear(); |
| 144 } |
112 | 145 |
113 void CallStackProfileMetricsProvider::ProvideGeneralMetrics( | 146 void CallStackProfileMetricsProvider::ProvideGeneralMetrics( |
114 ChromeUserMetricsExtension* uma_proto) { | 147 ChromeUserMetricsExtension* uma_proto) { |
115 std::vector<StackSamplingProfiler::Profile> profiles; | 148 if (!IsSamplingProfilingReportingEnabled()) |
116 if (!source_profiles_for_test_.empty()) | 149 return; |
117 profiles.swap(source_profiles_for_test_); | |
118 else | |
119 StackSamplingProfiler::GetPendingProfiles(&profiles); | |
120 | 150 |
121 for (const StackSamplingProfiler::Profile& profile : profiles) { | 151 for (const StackSamplingProfiler::Profile& profile : pending_profiles_) { |
122 CallStackProfile* call_stack_profile = | 152 CallStackProfile* call_stack_profile = |
123 uma_proto->add_sampled_profile()->mutable_call_stack_profile(); | 153 uma_proto->add_sampled_profile()->mutable_call_stack_profile(); |
124 CopyProfileToProto(profile, call_stack_profile); | 154 CopyProfileToProto(profile, call_stack_profile); |
125 } | 155 } |
126 } | 156 } |
127 | 157 |
128 void CallStackProfileMetricsProvider::SetSourceProfilesForTesting( | 158 void CallStackProfileMetricsProvider::SetSourceProfilesForTesting( |
129 const std::vector<StackSamplingProfiler::Profile>& profiles) { | 159 const std::vector<StackSamplingProfiler::Profile>& profiles) { |
130 source_profiles_for_test_ = profiles; | 160 pending_profiles_ = profiles; |
| 161 } |
| 162 |
| 163 // static |
| 164 bool CallStackProfileMetricsProvider::IsSamplingProfilingReportingEnabled() { |
| 165 const std::string group_name = |
| 166 base::FieldTrialList::FindFullName( |
| 167 CallStackProfileMetricsProvider::kFieldTrialName); |
| 168 return group_name == |
| 169 CallStackProfileMetricsProvider::kReportProfilesGroupName; |
| 170 } |
| 171 |
| 172 // static |
| 173 // Posts a message back to our own thread to collect the profiles. |
| 174 void CallStackProfileMetricsProvider::ReceiveCompletedProfiles( |
| 175 scoped_refptr<base::MessageLoopProxy> message_loop, |
| 176 base::WeakPtr<CallStackProfileMetricsProvider> provider, |
| 177 const std::vector<base::StackSamplingProfiler::Profile>& profiles) { |
| 178 message_loop->PostTask( |
| 179 FROM_HERE, |
| 180 base::Bind(&CallStackProfileMetricsProvider::AppendCompletedProfiles, |
| 181 provider, |
| 182 profiles)); |
| 183 } |
| 184 |
| 185 void CallStackProfileMetricsProvider::AppendCompletedProfiles( |
| 186 const std::vector<base::StackSamplingProfiler::Profile>& profiles) { |
| 187 pending_profiles_.insert(pending_profiles_.end(), profiles.begin(), |
| 188 profiles.end()); |
131 } | 189 } |
132 | 190 |
133 } // namespace metrics | 191 } // namespace metrics |
OLD | NEW |