| 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 "components/metrics/profiler/profiler_metrics_provider.h" | 5 #include "components/metrics/profiler/profiler_metrics_provider.h" |
| 6 | 6 |
| 7 #include <ctype.h> | 7 #include <ctype.h> |
| 8 #include <string> | 8 #include <string> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/tracked_objects.h" | 11 #include "base/tracked_objects.h" |
| 12 #include "components/metrics/metrics_log.h" | 12 #include "components/metrics/metrics_log.h" |
| 13 #include "components/nacl/common/nacl_process_type.h" | 13 #include "components/nacl/common/nacl_process_type.h" |
| 14 #include "components/variations/variations_associated_data.h" | 14 #include "components/variations/variations_associated_data.h" |
| 15 #include "content/public/common/process_type.h" | 15 #include "content/public/common/process_type.h" |
| 16 | 16 |
| 17 using tracked_objects::ProcessDataSnapshot; | |
| 18 | |
| 19 namespace metrics { | 17 namespace metrics { |
| 20 | 18 |
| 21 namespace { | 19 namespace { |
| 22 | 20 |
| 23 ProfilerEventProto::TrackedObject::ProcessType AsProtobufProcessType( | 21 ProfilerEventProto::TrackedObject::ProcessType AsProtobufProcessType( |
| 24 int process_type) { | 22 int process_type) { |
| 25 switch (process_type) { | 23 switch (process_type) { |
| 26 case content::PROCESS_TYPE_BROWSER: | 24 case content::PROCESS_TYPE_BROWSER: |
| 27 return ProfilerEventProto::TrackedObject::BROWSER; | 25 return ProfilerEventProto::TrackedObject::BROWSER; |
| 28 case content::PROCESS_TYPE_RENDERER: | 26 case content::PROCESS_TYPE_RENDERER: |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 68 |
| 71 // Normalizes a source filename (which is platform- and build-method-dependent) | 69 // Normalizes a source filename (which is platform- and build-method-dependent) |
| 72 // by extracting the last component of the full file name. | 70 // by extracting the last component of the full file name. |
| 73 // Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" => | 71 // Example: "c:\b\build\slave\win\build\src\chrome\app\chrome_main.cc" => |
| 74 // "chrome_main.cc". | 72 // "chrome_main.cc". |
| 75 std::string NormalizeFileName(const std::string& file_name) { | 73 std::string NormalizeFileName(const std::string& file_name) { |
| 76 const size_t offset = file_name.find_last_of("\\/"); | 74 const size_t offset = file_name.find_last_of("\\/"); |
| 77 return offset != std::string::npos ? file_name.substr(offset + 1) : file_name; | 75 return offset != std::string::npos ? file_name.substr(offset + 1) : file_name; |
| 78 } | 76 } |
| 79 | 77 |
| 80 void WriteProfilerData(const ProcessDataSnapshot& profiler_data, | 78 void WriteProfilerData( |
| 81 int process_type, | 79 const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, |
| 82 ProfilerEventProto* performance_profile) { | 80 int process_id, |
| 83 for (std::vector<tracked_objects::TaskSnapshot>::const_iterator it = | 81 int process_type, |
| 84 profiler_data.tasks.begin(); | 82 ProfilerEventProto* performance_profile) { |
| 85 it != profiler_data.tasks.end(); | 83 for (const auto& i : process_data_phase.tasks) { |
| 86 ++it) { | 84 const tracked_objects::DeathDataSnapshot& death_data = i.death_data; |
| 87 const tracked_objects::DeathDataSnapshot& death_data = it->death_data; | |
| 88 ProfilerEventProto::TrackedObject* tracked_object = | 85 ProfilerEventProto::TrackedObject* tracked_object = |
| 89 performance_profile->add_tracked_object(); | 86 performance_profile->add_tracked_object(); |
| 90 tracked_object->set_birth_thread_name_hash( | 87 tracked_object->set_birth_thread_name_hash( |
| 91 MetricsLog::Hash(MapThreadName(it->birth.thread_name))); | 88 MetricsLog::Hash(MapThreadName(i.birth.thread_name))); |
| 92 tracked_object->set_exec_thread_name_hash( | 89 tracked_object->set_exec_thread_name_hash( |
| 93 MetricsLog::Hash(MapThreadName(it->death_thread_name))); | 90 MetricsLog::Hash(MapThreadName(i.death_thread_name))); |
| 94 tracked_object->set_source_file_name_hash( | 91 tracked_object->set_source_file_name_hash( |
| 95 MetricsLog::Hash(NormalizeFileName( | 92 MetricsLog::Hash(NormalizeFileName(i.birth.location.file_name))); |
| 96 it->birth.location.file_name))); | |
| 97 tracked_object->set_source_function_name_hash( | 93 tracked_object->set_source_function_name_hash( |
| 98 MetricsLog::Hash(it->birth.location.function_name)); | 94 MetricsLog::Hash(i.birth.location.function_name)); |
| 99 tracked_object->set_source_line_number(it->birth.location.line_number); | 95 tracked_object->set_source_line_number(i.birth.location.line_number); |
| 100 tracked_object->set_exec_count(death_data.count); | 96 tracked_object->set_exec_count(death_data.count); |
| 101 tracked_object->set_exec_time_total(death_data.run_duration_sum); | 97 tracked_object->set_exec_time_total(death_data.run_duration_sum); |
| 102 tracked_object->set_exec_time_sampled(death_data.run_duration_sample); | 98 tracked_object->set_exec_time_sampled(death_data.run_duration_sample); |
| 103 tracked_object->set_queue_time_total(death_data.queue_duration_sum); | 99 tracked_object->set_queue_time_total(death_data.queue_duration_sum); |
| 104 tracked_object->set_queue_time_sampled(death_data.queue_duration_sample); | 100 tracked_object->set_queue_time_sampled(death_data.queue_duration_sample); |
| 105 tracked_object->set_process_type(AsProtobufProcessType(process_type)); | 101 tracked_object->set_process_type(AsProtobufProcessType(process_type)); |
| 106 tracked_object->set_process_id(profiler_data.process_id); | 102 tracked_object->set_process_id(process_id); |
| 107 } | 103 } |
| 108 } | 104 } |
| 109 | 105 |
| 110 // Returns true if the user is assigned to the experiment group for enabled | 106 // Returns true if the user is assigned to the experiment group for enabled |
| 111 // cellular uploads. | 107 // cellular uploads. |
| 112 bool IsCellularEnabledByExperiment() { | 108 bool IsCellularEnabledByExperiment() { |
| 113 const std::string group_name = | 109 const std::string group_name = |
| 114 base::FieldTrialList::FindFullName("UMA_EnableCellularLogUpload"); | 110 base::FieldTrialList::FindFullName("UMA_EnableCellularLogUpload"); |
| 115 return group_name == "Enabled"; | 111 return group_name == "Enabled"; |
| 116 } | 112 } |
| 117 | 113 |
| 118 } // namespace | 114 } // namespace |
| 119 | 115 |
| 120 ProfilerMetricsProvider::ProfilerMetricsProvider() : has_profiler_data_(false) { | 116 ProfilerMetricsProvider::ProfilerMetricsProvider() { |
| 121 } | 117 } |
| 122 | 118 |
| 123 ProfilerMetricsProvider::ProfilerMetricsProvider( | 119 ProfilerMetricsProvider::ProfilerMetricsProvider( |
| 124 const base::Callback<void(bool*)>& cellular_callback) | 120 const base::Callback<void(bool*)>& cellular_callback) { |
| 125 : has_profiler_data_(false), cellular_callback_(cellular_callback) { | |
| 126 } | 121 } |
| 127 | 122 |
| 128 ProfilerMetricsProvider::~ProfilerMetricsProvider() { | 123 ProfilerMetricsProvider::~ProfilerMetricsProvider() { |
| 129 } | 124 } |
| 130 | 125 |
| 131 void ProfilerMetricsProvider::ProvideGeneralMetrics( | 126 void ProfilerMetricsProvider::ProvideGeneralMetrics( |
| 132 ChromeUserMetricsExtension* uma_proto) { | 127 ChromeUserMetricsExtension* uma_proto) { |
| 133 if (!has_profiler_data_) | |
| 134 return; | |
| 135 | |
| 136 DCHECK_EQ(tracked_objects::TIME_SOURCE_TYPE_WALL_TIME, | 128 DCHECK_EQ(tracked_objects::TIME_SOURCE_TYPE_WALL_TIME, |
| 137 tracked_objects::GetTimeSourceType()); | 129 tracked_objects::GetTimeSourceType()); |
| 138 | 130 |
| 139 DCHECK_EQ(0, uma_proto->profiler_event_size()); | 131 DCHECK_EQ(0, uma_proto->profiler_event_size()); |
| 140 ProfilerEventProto* profile = uma_proto->add_profiler_event(); | 132 |
| 141 profile->Swap(&profiler_event_cache_); | 133 for (const auto& i : profiler_events_cache_) { |
| 142 has_profiler_data_ = false; | 134 uma_proto->add_profiler_event()->CopyFrom(i.second); |
| 135 } |
| 136 |
| 137 profiler_events_cache_.clear(); |
| 143 } | 138 } |
| 144 | 139 |
| 145 void ProfilerMetricsProvider::RecordProfilerData( | 140 void ProfilerMetricsProvider::RecordProfilerData( |
| 146 const tracked_objects::ProcessDataSnapshot& process_data, | 141 const tracked_objects::ProcessDataPhaseSnapshot& process_data_phase, |
| 147 int process_type) { | 142 int process_id, |
| 143 int process_type, |
| 144 int profiling_phase, |
| 145 const base::TimeDelta& profiling_phase_start, |
| 146 const base::TimeDelta& profiling_phase_finish, |
| 147 const ProfilerEventsSet& past_profiler_events) { |
| 148 if (IsCellularConnection() && IsCellularEnabledByExperiment()) | 148 if (IsCellularConnection() && IsCellularEnabledByExperiment()) |
| 149 return; | 149 return; |
| 150 if (tracked_objects::GetTimeSourceType() != | 150 if (tracked_objects::GetTimeSourceType() != |
| 151 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME) { | 151 tracked_objects::TIME_SOURCE_TYPE_WALL_TIME) { |
| 152 // We currently only support the default time source, wall clock time. | 152 // We currently only support the default time source, wall clock time. |
| 153 return; | 153 return; |
| 154 } | 154 } |
| 155 | 155 |
| 156 has_profiler_data_ = true; | 156 const bool new_phase = profiler_events_cache_.find(profiling_phase) == |
| 157 profiler_event_cache_.set_profile_version( | 157 profiler_events_cache_.end(); |
| 158 ProfilerEventProto::VERSION_STARTUP_PROFILE); | 158 ProfilerEventProto* profiler_event = &profiler_events_cache_[profiling_phase]; |
| 159 profiler_event_cache_.set_time_source(ProfilerEventProto::WALL_CLOCK_TIME); | 159 |
| 160 WriteProfilerData(process_data, process_type, &profiler_event_cache_); | 160 if (new_phase) { |
| 161 profiler_event->set_profile_version( |
| 162 ProfilerEventProto::VERSION_SPLIT_PROFILE); |
| 163 profiler_event->set_time_source(ProfilerEventProto::WALL_CLOCK_TIME); |
| 164 profiler_event->set_profiling_start_ms( |
| 165 profiling_phase_start.InMilliseconds()); |
| 166 profiler_event->set_profiling_finish_ms( |
| 167 profiling_phase_finish.InMilliseconds()); |
| 168 for (const auto& i : past_profiler_events) { |
| 169 profiler_event->add_past_session_events(i); |
| 170 } |
| 171 } |
| 172 |
| 173 WriteProfilerData(process_data_phase, process_id, process_type, |
| 174 profiler_event); |
| 161 } | 175 } |
| 162 | 176 |
| 163 bool ProfilerMetricsProvider::IsCellularConnection() { | 177 bool ProfilerMetricsProvider::IsCellularConnection() { |
| 164 bool is_cellular = false; | 178 bool is_cellular = false; |
| 165 // For android get current connection type from NetworkMetricsProvider if the | 179 // For android get current connection type from NetworkMetricsProvider if the |
| 166 // callback exists. | 180 // callback exists. |
| 167 #if defined(OS_ANDROID) | 181 #if defined(OS_ANDROID) |
| 168 if (!cellular_callback_.is_null()) | 182 if (!cellular_callback_.is_null()) |
| 169 cellular_callback_.Run(&is_cellular); | 183 cellular_callback_.Run(&is_cellular); |
| 170 #endif | 184 #endif |
| 171 return is_cellular; | 185 return is_cellular; |
| 172 } | 186 } |
| 173 | 187 |
| 174 } // namespace metrics | 188 } // namespace metrics |
| OLD | NEW |