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 <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <cstring> | 11 #include <cstring> |
12 #include <map> | 12 #include <map> |
13 #include <string> | 13 #include <string> |
14 #include <utility> | 14 #include <utility> |
15 #include <vector> | 15 #include <vector> |
16 | 16 |
17 #include "base/bind.h" | 17 #include "base/bind.h" |
18 #include "base/location.h" | 18 #include "base/location.h" |
19 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/macros.h" | 20 #include "base/macros.h" |
21 #include "base/memory/singleton.h" | 21 #include "base/memory/singleton.h" |
22 #include "base/metrics/field_trial.h" | 22 #include "base/metrics/field_trial_params.h" |
23 #include "base/metrics/metrics_hashes.h" | 23 #include "base/metrics/metrics_hashes.h" |
| 24 #include "base/process/process_info.h" |
24 #include "base/profiler/stack_sampling_profiler.h" | 25 #include "base/profiler/stack_sampling_profiler.h" |
25 #include "base/single_thread_task_runner.h" | 26 #include "base/single_thread_task_runner.h" |
26 #include "base/synchronization/lock.h" | 27 #include "base/synchronization/lock.h" |
27 #include "base/threading/thread_task_runner_handle.h" | 28 #include "base/threading/thread_task_runner_handle.h" |
28 #include "base/time/time.h" | 29 #include "base/time/time.h" |
| 30 #include "build/build_config.h" |
29 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" | 31 #include "components/metrics/proto/chrome_user_metrics_extension.pb.h" |
30 | 32 |
31 using base::StackSamplingProfiler; | 33 using base::StackSamplingProfiler; |
32 | 34 |
33 namespace metrics { | 35 namespace metrics { |
34 | 36 |
35 namespace { | 37 namespace { |
36 | 38 |
| 39 // Interval for periodic (post-startup) sampling, when enabled. |
| 40 constexpr base::TimeDelta kPeriodicSamplingInterval = |
| 41 base::TimeDelta::FromSeconds(1); |
| 42 |
37 // Provide a mapping from the C++ "enum" definition of various process mile- | 43 // Provide a mapping from the C++ "enum" definition of various process mile- |
38 // stones to the equivalent protobuf "enum" definition. This table-lookup | 44 // stones to the equivalent protobuf "enum" definition. This table-lookup |
39 // conversion allows for the implementation to evolve and still be compatible | 45 // conversion allows for the implementation to evolve and still be compatible |
40 // with the protobuf -- even if there are ever more than 32 defined proto | 46 // with the protobuf -- even if there are ever more than 32 defined proto |
41 // values, though never more than 32 could be in-use in a given C++ version | 47 // values, though never more than 32 could be in-use in a given C++ version |
42 // of the code. | 48 // of the code. |
43 const ProcessPhase | 49 const ProcessPhase |
44 kProtoPhases[CallStackProfileMetricsProvider::MILESTONES_MAX_VALUE] = { | 50 kProtoPhases[CallStackProfileMetricsProvider::MILESTONES_MAX_VALUE] = { |
45 ProcessPhase::MAIN_LOOP_START, | 51 ProcessPhase::MAIN_LOOP_START, |
46 ProcessPhase::MAIN_NAVIGATION_START, | 52 ProcessPhase::MAIN_NAVIGATION_START, |
47 ProcessPhase::MAIN_NAVIGATION_FINISHED, | 53 ProcessPhase::MAIN_NAVIGATION_FINISHED, |
48 ProcessPhase::FIRST_NONEMPTY_PAINT, | 54 ProcessPhase::FIRST_NONEMPTY_PAINT, |
49 | 55 |
50 ProcessPhase::SHUTDOWN_START, | 56 ProcessPhase::SHUTDOWN_START, |
51 }; | 57 }; |
52 | 58 |
| 59 // Parameters for browser process sampling. Not const since these may be |
| 60 // changed when transitioning from start-up profiling to periodic profiling. |
| 61 CallStackProfileParams g_browser_process_sampling_params( |
| 62 metrics::CallStackProfileParams::BROWSER_PROCESS, |
| 63 metrics::CallStackProfileParams::UI_THREAD, |
| 64 metrics::CallStackProfileParams::PROCESS_STARTUP, |
| 65 metrics::CallStackProfileParams::MAY_SHUFFLE); |
| 66 |
53 // ProfilesState -------------------------------------------------------------- | 67 // ProfilesState -------------------------------------------------------------- |
54 | 68 |
55 // A set of profiles and the CallStackProfileMetricsProvider state associated | 69 // A set of profiles and the CallStackProfileMetricsProvider state associated |
56 // with them. | 70 // with them. |
57 struct ProfilesState { | 71 struct ProfilesState { |
58 ProfilesState(const CallStackProfileParams& params, | 72 ProfilesState(const CallStackProfileParams& params, |
59 StackSamplingProfiler::CallStackProfiles profiles, | 73 StackSamplingProfiler::CallStackProfiles profiles); |
60 base::TimeTicks start_timestamp); | |
61 ProfilesState(ProfilesState&&); | 74 ProfilesState(ProfilesState&&); |
62 ProfilesState& operator=(ProfilesState&&); | 75 ProfilesState& operator=(ProfilesState&&); |
63 | 76 |
64 // The metrics-related parameters provided to | 77 // The metrics-related parameters provided to |
65 // CallStackProfileMetricsProvider::GetProfilerCallback(). | 78 // CallStackProfileMetricsProvider::GetProfilerCallback(). |
66 CallStackProfileParams params; | 79 CallStackProfileParams params; |
67 | 80 |
68 // The call stack profiles collected by the profiler. | 81 // The call stack profiles collected by the profiler. |
69 StackSamplingProfiler::CallStackProfiles profiles; | 82 StackSamplingProfiler::CallStackProfiles profiles; |
70 | 83 |
71 // The time at which the CallStackProfileMetricsProvider became aware of the | |
72 // request for profiling. In particular, this is when callback was requested | |
73 // via CallStackProfileMetricsProvider::GetProfilerCallback(). Used to | |
74 // determine if collection was disabled during the collection of the profile. | |
75 base::TimeTicks start_timestamp; | |
76 | |
77 private: | 84 private: |
78 DISALLOW_COPY_AND_ASSIGN(ProfilesState); | 85 DISALLOW_COPY_AND_ASSIGN(ProfilesState); |
79 }; | 86 }; |
80 | 87 |
81 ProfilesState::ProfilesState(const CallStackProfileParams& params, | 88 ProfilesState::ProfilesState(const CallStackProfileParams& params, |
82 StackSamplingProfiler::CallStackProfiles profiles, | 89 StackSamplingProfiler::CallStackProfiles profiles) |
83 base::TimeTicks start_timestamp) | 90 : params(params), profiles(std::move(profiles)) {} |
84 : params(params), | |
85 profiles(std::move(profiles)), | |
86 start_timestamp(start_timestamp) {} | |
87 | 91 |
88 ProfilesState::ProfilesState(ProfilesState&&) = default; | 92 ProfilesState::ProfilesState(ProfilesState&&) = default; |
89 | 93 |
90 // Some versions of GCC need this for push_back to work with std::move. | 94 // Some versions of GCC need this for push_back to work with std::move. |
91 ProfilesState& ProfilesState::operator=(ProfilesState&&) = default; | 95 ProfilesState& ProfilesState::operator=(ProfilesState&&) = default; |
92 | 96 |
93 // PendingProfiles ------------------------------------------------------------ | 97 // PendingProfiles ------------------------------------------------------------ |
94 | 98 |
95 // Singleton class responsible for retaining profiles received via the callback | 99 // Singleton class responsible for retaining profiles received via the callback |
96 // created by CallStackProfileMetricsProvider::GetProfilerCallback(). These are | 100 // created by GetProfilerCallback(). These are then sent to UMA on the |
97 // then sent to UMA on the invocation of | 101 // invocation of CallStackProfileMetricsProvider::ProvideGeneralMetrics(). We |
98 // CallStackProfileMetricsProvider::ProvideGeneralMetrics(). We need to store | 102 // need to store the profiles outside of a CallStackProfileMetricsProvider |
99 // the profiles outside of a CallStackProfileMetricsProvider instance since | 103 // instance since callers may start profiling before the |
100 // callers may start profiling before the CallStackProfileMetricsProvider is | 104 // CallStackProfileMetricsProvider is created. |
101 // created. | |
102 // | 105 // |
103 // Member functions on this class may be called on any thread. | 106 // Member functions on this class may be called on any thread. |
104 class PendingProfiles { | 107 class PendingProfiles { |
105 public: | 108 public: |
106 static PendingProfiles* GetInstance(); | 109 static PendingProfiles* GetInstance(); |
107 | 110 |
108 void Swap(std::vector<ProfilesState>* profiles); | 111 void Swap(std::vector<ProfilesState>* profiles); |
109 | 112 |
110 // Enables the collection of profiles by CollectProfilesIfCollectionEnabled if | 113 // Enables the collection of profiles by CollectProfilesIfCollectionEnabled if |
111 // |enabled| is true. Otherwise, clears current profiles and ignores profiles | 114 // |enabled| is true. Otherwise, clears current profiles and ignores profiles |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 } | 176 } |
174 | 177 |
175 void PendingProfiles::CollectProfilesIfCollectionEnabled( | 178 void PendingProfiles::CollectProfilesIfCollectionEnabled( |
176 ProfilesState profiles) { | 179 ProfilesState profiles) { |
177 base::AutoLock scoped_lock(lock_); | 180 base::AutoLock scoped_lock(lock_); |
178 | 181 |
179 // Only collect if collection is not disabled and hasn't been disabled | 182 // Only collect if collection is not disabled and hasn't been disabled |
180 // since the start of collection for this profile. | 183 // since the start of collection for this profile. |
181 if (!collection_enabled_ || | 184 if (!collection_enabled_ || |
182 (!last_collection_disable_time_.is_null() && | 185 (!last_collection_disable_time_.is_null() && |
183 last_collection_disable_time_ >= profiles.start_timestamp)) { | 186 last_collection_disable_time_ >= profiles.params.start_timestamp)) { |
184 return; | 187 return; |
185 } | 188 } |
186 | 189 |
| 190 if (profiles.params.trigger == CallStackProfileParams::PERIODIC_COLLECTION) { |
| 191 DCHECK_EQ(1U, profiles.profiles.size()); |
| 192 profiles.profiles[0].sampling_period = kPeriodicSamplingInterval; |
| 193 // Use the process uptime as the collection time to indicate when this |
| 194 // profile was collected. This is useful to account for uptime bias during |
| 195 // analysis. |
| 196 profiles.profiles[0].profile_duration = internal::GetUptime(); |
| 197 } |
| 198 |
187 profiles_.push_back(std::move(profiles)); | 199 profiles_.push_back(std::move(profiles)); |
188 } | 200 } |
189 | 201 |
190 void PendingProfiles::ResetToDefaultStateForTesting() { | 202 void PendingProfiles::ResetToDefaultStateForTesting() { |
191 base::AutoLock scoped_lock(lock_); | 203 base::AutoLock scoped_lock(lock_); |
192 | 204 |
193 collection_enabled_ = true; | 205 collection_enabled_ = true; |
194 last_collection_disable_time_ = base::TimeTicks(); | 206 last_collection_disable_time_ = base::TimeTicks(); |
195 profiles_.clear(); | 207 profiles_.clear(); |
196 } | 208 } |
197 | 209 |
198 // |collection_enabled_| is initialized to true to collect any profiles that are | 210 // |collection_enabled_| is initialized to true to collect any profiles that are |
199 // generated prior to creation of the CallStackProfileMetricsProvider. The | 211 // generated prior to creation of the CallStackProfileMetricsProvider. The |
200 // ultimate disposition of these pre-creation collected profiles will be | 212 // ultimate disposition of these pre-creation collected profiles will be |
201 // determined by the initial recording state provided to | 213 // determined by the initial recording state provided to |
202 // CallStackProfileMetricsProvider. | 214 // CallStackProfileMetricsProvider. |
203 PendingProfiles::PendingProfiles() : collection_enabled_(true) {} | 215 PendingProfiles::PendingProfiles() : collection_enabled_(true) {} |
204 | 216 |
205 PendingProfiles::~PendingProfiles() {} | 217 PendingProfiles::~PendingProfiles() {} |
206 | 218 |
207 // Functions to process completed profiles ------------------------------------ | 219 // Functions to process completed profiles ------------------------------------ |
208 | 220 |
209 // Will be invoked on either the main thread or the profiler's thread. Provides | 221 // Will be invoked on either the main thread or the profiler's thread. Provides |
210 // the profiles to PendingProfiles to append, if the collecting state allows. | 222 // the profiles to PendingProfiles to append, if the collecting state allows. |
211 void ReceiveCompletedProfilesImpl( | 223 base::Optional<StackSamplingProfiler::SamplingParams> |
212 const CallStackProfileParams& params, | 224 ReceiveCompletedProfilesImpl( |
213 base::TimeTicks start_timestamp, | 225 CallStackProfileParams* params, |
214 StackSamplingProfiler::CallStackProfiles profiles) { | 226 StackSamplingProfiler::CallStackProfiles profiles) { |
215 PendingProfiles::GetInstance()->CollectProfilesIfCollectionEnabled( | 227 PendingProfiles::GetInstance()->CollectProfilesIfCollectionEnabled( |
216 ProfilesState(params, std::move(profiles), start_timestamp)); | 228 ProfilesState(*params, std::move(profiles))); |
| 229 |
| 230 // Now, schedule periodic sampling every 1s, if enabled by trial. |
| 231 // TODO(asvitkine): Support periodic sampling for non-browser processes. |
| 232 // TODO(asvitkine): In the future, we may want to have finer grained control |
| 233 // over this, for example ending sampling after some amount of time. |
| 234 if (CallStackProfileMetricsProvider::IsPeriodicSamplingEnabled() && |
| 235 params->process == CallStackProfileParams::BROWSER_PROCESS && |
| 236 params->thread == CallStackProfileParams::UI_THREAD) { |
| 237 params->trigger = metrics::CallStackProfileParams::PERIODIC_COLLECTION; |
| 238 params->start_timestamp = base::TimeTicks::Now(); |
| 239 |
| 240 StackSamplingProfiler::SamplingParams sampling_params; |
| 241 sampling_params.initial_delay = kPeriodicSamplingInterval; |
| 242 sampling_params.bursts = 1; |
| 243 sampling_params.samples_per_burst = 1; |
| 244 // Below are unused: |
| 245 sampling_params.burst_interval = base::TimeDelta::FromMilliseconds(0); |
| 246 sampling_params.sampling_interval = base::TimeDelta::FromMilliseconds(0); |
| 247 return sampling_params; |
| 248 } |
| 249 return base::Optional<StackSamplingProfiler::SamplingParams>(); |
217 } | 250 } |
218 | 251 |
219 // Invoked on an arbitrary thread. Ignores the provided profiles. | 252 // Invoked on an arbitrary thread. Ignores the provided profiles. |
220 void IgnoreCompletedProfiles( | 253 base::Optional<StackSamplingProfiler::SamplingParams> IgnoreCompletedProfiles( |
221 StackSamplingProfiler::CallStackProfiles profiles) {} | 254 StackSamplingProfiler::CallStackProfiles profiles) { |
| 255 return base::Optional<StackSamplingProfiler::SamplingParams>(); |
| 256 } |
222 | 257 |
223 // Functions to encode protobufs ---------------------------------------------- | 258 // Functions to encode protobufs ---------------------------------------------- |
224 | 259 |
225 // The protobuf expects the MD5 checksum prefix of the module name. | 260 // The protobuf expects the MD5 checksum prefix of the module name. |
226 uint64_t HashModuleFilename(const base::FilePath& filename) { | 261 uint64_t HashModuleFilename(const base::FilePath& filename) { |
227 const base::FilePath::StringType basename = filename.BaseName().value(); | 262 const base::FilePath::StringType basename = filename.BaseName().value(); |
228 // Copy the bytes in basename into a string buffer. | 263 // Copy the bytes in basename into a string buffer. |
229 size_t basename_length_in_bytes = | 264 size_t basename_length_in_bytes = |
230 basename.size() * sizeof(base::FilePath::CharType); | 265 basename.size() * sizeof(base::FilePath::CharType); |
231 std::string name_bytes(basename_length_in_bytes, '\0'); | 266 std::string name_bytes(basename_length_in_bytes, '\0'); |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
398 CallStackProfileParams::Trigger trigger) { | 433 CallStackProfileParams::Trigger trigger) { |
399 switch (trigger) { | 434 switch (trigger) { |
400 case CallStackProfileParams::UNKNOWN: | 435 case CallStackProfileParams::UNKNOWN: |
401 return SampledProfile::UNKNOWN_TRIGGER_EVENT; | 436 return SampledProfile::UNKNOWN_TRIGGER_EVENT; |
402 case CallStackProfileParams::PROCESS_STARTUP: | 437 case CallStackProfileParams::PROCESS_STARTUP: |
403 return SampledProfile::PROCESS_STARTUP; | 438 return SampledProfile::PROCESS_STARTUP; |
404 case CallStackProfileParams::JANKY_TASK: | 439 case CallStackProfileParams::JANKY_TASK: |
405 return SampledProfile::JANKY_TASK; | 440 return SampledProfile::JANKY_TASK; |
406 case CallStackProfileParams::THREAD_HUNG: | 441 case CallStackProfileParams::THREAD_HUNG: |
407 return SampledProfile::THREAD_HUNG; | 442 return SampledProfile::THREAD_HUNG; |
| 443 case CallStackProfileParams::PERIODIC_COLLECTION: |
| 444 return SampledProfile::PERIODIC_COLLECTION; |
408 } | 445 } |
409 NOTREACHED(); | 446 NOTREACHED(); |
410 return SampledProfile::UNKNOWN_TRIGGER_EVENT; | 447 return SampledProfile::UNKNOWN_TRIGGER_EVENT; |
411 } | 448 } |
412 | 449 |
413 } // namespace | 450 } // namespace |
414 | 451 |
| 452 namespace internal { |
| 453 |
| 454 base::TimeDelta GetUptime() { |
| 455 static base::Time process_creation_time; |
| 456 // base::CurrentProcessInfo::CreationTime() is only defined on some platforms. |
| 457 #if (defined(OS_MACOSX) && !defined(OS_IOS)) || defined(OS_WIN) || \ |
| 458 defined(OS_LINUX) |
| 459 if (process_creation_time.is_null()) |
| 460 process_creation_time = base::CurrentProcessInfo::CreationTime(); |
| 461 #else |
| 462 NOTREACHED(); |
| 463 #endif |
| 464 DCHECK(!process_creation_time.is_null()); |
| 465 return base::Time::Now() - process_creation_time; |
| 466 } |
| 467 |
| 468 StackSamplingProfiler::CompletedCallback GetProfilerCallback( |
| 469 CallStackProfileParams* params) { |
| 470 // Ignore the profiles if the collection is disabled. If the collection state |
| 471 // changes while collecting, this will be detected by the callback and |
| 472 // profiles will be ignored at that point. |
| 473 if (!PendingProfiles::GetInstance()->IsCollectionEnabled()) |
| 474 return base::Bind(&IgnoreCompletedProfiles); |
| 475 |
| 476 params->start_timestamp = base::TimeTicks::Now(); |
| 477 return base::Bind(&ReceiveCompletedProfilesImpl, params); |
| 478 } |
| 479 |
| 480 } // namespace internal |
| 481 |
415 // CallStackProfileMetricsProvider -------------------------------------------- | 482 // CallStackProfileMetricsProvider -------------------------------------------- |
416 | 483 |
417 const char CallStackProfileMetricsProvider::kFieldTrialName[] = | 484 const base::Feature CallStackProfileMetricsProvider::kEnableReporting = { |
418 "StackProfiling"; | 485 "SamplingProfilerReporting", base::FEATURE_DISABLED_BY_DEFAULT}; |
419 const char CallStackProfileMetricsProvider::kReportProfilesGroupName[] = | |
420 "Report profiles"; | |
421 | 486 |
422 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() { | 487 CallStackProfileMetricsProvider::CallStackProfileMetricsProvider() { |
423 } | 488 } |
424 | 489 |
425 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() { | 490 CallStackProfileMetricsProvider::~CallStackProfileMetricsProvider() { |
426 } | 491 } |
427 | 492 |
428 // This function can be invoked on an abitrary thread. | |
429 StackSamplingProfiler::CompletedCallback | 493 StackSamplingProfiler::CompletedCallback |
430 CallStackProfileMetricsProvider::GetProfilerCallback( | 494 CallStackProfileMetricsProvider::GetProfilerCallbackForBrowserProcessStartup() { |
431 const CallStackProfileParams& params) { | 495 return internal::GetProfilerCallback(&g_browser_process_sampling_params); |
432 // Ignore the profiles if the collection is disabled. If the collection state | |
433 // changes while collecting, this will be detected by the callback and | |
434 // profiles will be ignored at that point. | |
435 if (!PendingProfiles::GetInstance()->IsCollectionEnabled()) | |
436 return base::Bind(&IgnoreCompletedProfiles); | |
437 | |
438 return base::Bind(&ReceiveCompletedProfilesImpl, params, | |
439 base::TimeTicks::Now()); | |
440 } | 496 } |
441 | 497 |
442 // static | 498 // static |
443 void CallStackProfileMetricsProvider::ReceiveCompletedProfiles( | 499 void CallStackProfileMetricsProvider::ReceiveCompletedProfiles( |
444 const CallStackProfileParams& params, | 500 CallStackProfileParams* params, |
445 base::TimeTicks start_timestamp, | 501 base::StackSamplingProfiler::CallStackProfiles profiles) { |
446 StackSamplingProfiler::CallStackProfiles profiles) { | 502 ReceiveCompletedProfilesImpl(params, std::move(profiles)); |
447 ReceiveCompletedProfilesImpl(params, start_timestamp, std::move(profiles)); | 503 } |
| 504 |
| 505 // static |
| 506 bool CallStackProfileMetricsProvider::IsPeriodicSamplingEnabled() { |
| 507 // Ensure FeatureList has been initialized before calling into an API that |
| 508 // calls base::FeatureList::IsEnabled() internally. While extremely unlikely, |
| 509 // it is possible that the profiler callback and therefore this function get |
| 510 // called before FeatureList initialization (e.g. if machine was suspended). |
| 511 return base::FeatureList::GetInstance() != nullptr && |
| 512 base::GetFieldTrialParamByFeatureAsBool(kEnableReporting, "periodic", |
| 513 false); |
448 } | 514 } |
449 | 515 |
450 void CallStackProfileMetricsProvider::OnRecordingEnabled() { | 516 void CallStackProfileMetricsProvider::OnRecordingEnabled() { |
451 PendingProfiles::GetInstance()->SetCollectionEnabled(true); | 517 PendingProfiles::GetInstance()->SetCollectionEnabled(true); |
452 } | 518 } |
453 | 519 |
454 void CallStackProfileMetricsProvider::OnRecordingDisabled() { | 520 void CallStackProfileMetricsProvider::OnRecordingDisabled() { |
455 PendingProfiles::GetInstance()->SetCollectionEnabled(false); | 521 PendingProfiles::GetInstance()->SetCollectionEnabled(false); |
456 } | 522 } |
457 | 523 |
458 void CallStackProfileMetricsProvider::ProvideGeneralMetrics( | 524 void CallStackProfileMetricsProvider::ProvideGeneralMetrics( |
459 ChromeUserMetricsExtension* uma_proto) { | 525 ChromeUserMetricsExtension* uma_proto) { |
460 std::vector<ProfilesState> pending_profiles; | 526 std::vector<ProfilesState> pending_profiles; |
461 PendingProfiles::GetInstance()->Swap(&pending_profiles); | 527 PendingProfiles::GetInstance()->Swap(&pending_profiles); |
462 | 528 |
463 DCHECK(IsReportingEnabledByFieldTrial() || pending_profiles.empty()); | 529 DCHECK(IsReportingEnabledByFieldTrial() || pending_profiles.empty()); |
464 | 530 |
| 531 // TODO(asvitkine): For post-startup periodic samples, this is currently |
| 532 // wasteful as each sample is reported in its own profile. We should attempt |
| 533 // to merge profiles to save bandwidth. |
465 for (const ProfilesState& profiles_state : pending_profiles) { | 534 for (const ProfilesState& profiles_state : pending_profiles) { |
466 for (const StackSamplingProfiler::CallStackProfile& profile : | 535 for (const StackSamplingProfiler::CallStackProfile& profile : |
467 profiles_state.profiles) { | 536 profiles_state.profiles) { |
468 SampledProfile* sampled_profile = uma_proto->add_sampled_profile(); | 537 SampledProfile* sampled_profile = uma_proto->add_sampled_profile(); |
469 sampled_profile->set_process(ToExecutionContextProcess( | 538 sampled_profile->set_process(ToExecutionContextProcess( |
470 profiles_state.params.process)); | 539 profiles_state.params.process)); |
471 sampled_profile->set_thread(ToExecutionContextThread( | 540 sampled_profile->set_thread(ToExecutionContextThread( |
472 profiles_state.params.thread)); | 541 profiles_state.params.thread)); |
473 sampled_profile->set_trigger_event(ToSampledProfileTriggerEvent( | 542 sampled_profile->set_trigger_event(ToSampledProfileTriggerEvent( |
474 profiles_state.params.trigger)); | 543 profiles_state.params.trigger)); |
475 CopyProfileToProto(profile, profiles_state.params.ordering_spec, | 544 CopyProfileToProto(profile, profiles_state.params.ordering_spec, |
476 sampled_profile->mutable_call_stack_profile()); | 545 sampled_profile->mutable_call_stack_profile()); |
477 } | 546 } |
478 } | 547 } |
479 } | 548 } |
480 | 549 |
481 // static | 550 // static |
482 void CallStackProfileMetricsProvider::ResetStaticStateForTesting() { | 551 void CallStackProfileMetricsProvider::ResetStaticStateForTesting() { |
483 PendingProfiles::GetInstance()->ResetToDefaultStateForTesting(); | 552 PendingProfiles::GetInstance()->ResetToDefaultStateForTesting(); |
484 } | 553 } |
485 | 554 |
486 // static | 555 // static |
487 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { | 556 bool CallStackProfileMetricsProvider::IsReportingEnabledByFieldTrial() { |
488 const std::string group_name = base::FieldTrialList::FindFullName( | 557 return base::FeatureList::IsEnabled(kEnableReporting); |
489 CallStackProfileMetricsProvider::kFieldTrialName); | |
490 return group_name == | |
491 CallStackProfileMetricsProvider::kReportProfilesGroupName; | |
492 } | 558 } |
493 | 559 |
494 } // namespace metrics | 560 } // namespace metrics |
OLD | NEW |