diff options
author | asvitkine <asvitkine@chromium.org> | 2014-10-31 14:59:57 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-10-31 22:00:18 +0000 |
commit | e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8 (patch) | |
tree | 538bbae51dc2dd71e8a8c50755cbeb7d0da67c43 | |
parent | 403be2a2a9f71ef7be26dd083d058732577a7ad3 (diff) | |
download | chromium_src-e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8.zip chromium_src-e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8.tar.gz chromium_src-e0dbdbe3aa7dce4dda9e9acb20325d8476003fa8.tar.bz2 |
Plumbing for variations headers from synthetic field trials.
BUG=428055
Review URL: https://codereview.chromium.org/688973004
Cr-Commit-Position: refs/heads/master@{#302331}
-rw-r--r-- | chrome/browser/chrome_browser_main.cc | 1 | ||||
-rw-r--r-- | components/metrics/metrics_service.cc | 19 | ||||
-rw-r--r-- | components/metrics/metrics_service.h | 24 | ||||
-rw-r--r-- | components/variations.gypi | 1 | ||||
-rw-r--r-- | components/variations/net/BUILD.gn | 1 | ||||
-rw-r--r-- | components/variations/net/DEPS | 1 | ||||
-rw-r--r-- | components/variations/net/variations_http_header_provider.cc | 47 | ||||
-rw-r--r-- | components/variations/net/variations_http_header_provider.h | 14 | ||||
-rw-r--r-- | components/variations/variations_associated_data.cc | 18 | ||||
-rw-r--r-- | components/variations/variations_associated_data.h | 10 |
10 files changed, 112 insertions, 24 deletions
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 6ab5340..48e78ea 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc @@ -623,6 +623,7 @@ void ChromeBrowserMainParts::SetupMetricsAndFieldTrials() { command_line->GetSwitchValueASCII(switches::kForceVariationIds)); CHECK(result) << "Invalid --" << switches::kForceVariationIds << " list specified."; + metrics->AddSyntheticTrialObserver(provider); } chrome_variations::VariationsService* variations_service = browser_process_->variations_service(); diff --git a/components/metrics/metrics_service.cc b/components/metrics/metrics_service.cc index 4db3bb5..4fa2e75 100644 --- a/components/metrics/metrics_service.cc +++ b/components/metrics/metrics_service.cc @@ -1138,6 +1138,18 @@ bool MetricsService::UmaMetricsProperlyShutdown() { return clean_shutdown_status_ == CLEANLY_SHUTDOWN; } +void MetricsService::AddSyntheticTrialObserver( + SyntheticTrialObserver* observer) { + synthetic_trial_observer_list_.AddObserver(observer); + if (!synthetic_trial_groups_.empty()) + observer->OnSyntheticTrialsChanged(synthetic_trial_groups_); +} + +void MetricsService::RemoveSyntheticTrialObserver( + SyntheticTrialObserver* observer) { + synthetic_trial_observer_list_.RemoveObserver(observer); +} + void MetricsService::RegisterSyntheticFieldTrial( const SyntheticTrialGroup& trial) { for (size_t i = 0; i < synthetic_trial_groups_.size(); ++i) { @@ -1145,6 +1157,7 @@ void MetricsService::RegisterSyntheticFieldTrial( if (synthetic_trial_groups_[i].id.group != trial.id.group) { synthetic_trial_groups_[i].id.group = trial.id.group; synthetic_trial_groups_[i].start_time = base::TimeTicks::Now(); + NotifySyntheticTrialObservers(); } return; } @@ -1153,6 +1166,7 @@ void MetricsService::RegisterSyntheticFieldTrial( SyntheticTrialGroup trial_group = trial; trial_group.start_time = base::TimeTicks::Now(); synthetic_trial_groups_.push_back(trial_group); + NotifySyntheticTrialObservers(); } void MetricsService::RegisterMetricsProvider( @@ -1166,6 +1180,11 @@ void MetricsService::CheckForClonedInstall( state_manager_->CheckForClonedInstall(task_runner); } +void MetricsService::NotifySyntheticTrialObservers() { + FOR_EACH_OBSERVER(SyntheticTrialObserver, synthetic_trial_observer_list_, + OnSyntheticTrialsChanged(synthetic_trial_groups_)); +} + void MetricsService::GetCurrentSyntheticFieldTrials( std::vector<variations::ActiveGroupId>* synthetic_trials) { DCHECK(synthetic_trials); diff --git a/components/metrics/metrics_service.h b/components/metrics/metrics_service.h index eae44f3..19794ea 100644 --- a/components/metrics/metrics_service.h +++ b/components/metrics/metrics_service.h @@ -21,6 +21,7 @@ #include "base/metrics/histogram_flattener.h" #include "base/metrics/histogram_snapshot_manager.h" #include "base/metrics/user_metrics.h" +#include "base/observer_list.h" #include "base/time/time.h" #include "components/metrics/clean_exit_beacon.h" #include "components/metrics/metrics_log.h" @@ -76,6 +77,17 @@ struct SyntheticTrialGroup { SyntheticTrialGroup(uint32 trial, uint32 group); }; +// Interface class to observe changes to synthetic trials in MetricsService. +class SyntheticTrialObserver { + public: + // Called when the list of synthetic field trial groups has changed. + virtual void OnSyntheticTrialsChanged( + const std::vector<SyntheticTrialGroup>& groups) = 0; + + protected: + virtual ~SyntheticTrialObserver() {} +}; + // See metrics_service.cc for a detailed description. class MetricsService : public base::HistogramFlattener { public: @@ -211,6 +223,12 @@ class MetricsService : public base::HistogramFlattener { // To use this method, SyntheticTrialGroup should friend your class. void RegisterSyntheticFieldTrial(const SyntheticTrialGroup& trial_group); + // Adds an observer to be notified when the synthetic trials list changes. + void AddSyntheticTrialObserver(SyntheticTrialObserver* observer); + + // Removes an existing observer of synthetic trials list changes. + void RemoveSyntheticTrialObserver(SyntheticTrialObserver* observer); + // Register the specified |provider| to provide additional metrics into the // UMA log. Should be called during MetricsService initialization only. void RegisterMetricsProvider(scoped_ptr<MetricsProvider> provider); @@ -358,6 +376,9 @@ class MetricsService : public base::HistogramFlattener { // Sets the value of the specified path in prefs and schedules a save. void RecordBooleanPrefValue(const char* path, bool value); + // Notifies observers on a synthetic trial list change. + void NotifySyntheticTrialObservers(); + // Returns a list of synthetic field trials that were active for the entire // duration of the current log. void GetCurrentSyntheticFieldTrials( @@ -447,6 +468,9 @@ class MetricsService : public base::HistogramFlattener { // Field trial groups that map to Chrome configuration states. SyntheticTrialGroups synthetic_trial_groups_; + // List of observers of |synthetic_trial_groups_| changes. + ObserverList<SyntheticTrialObserver> synthetic_trial_observer_list_; + // Execution phase the browser is in. static ExecutionPhase execution_phase_; diff --git a/components/variations.gypi b/components/variations.gypi index ee3a412..bf2cc37 100644 --- a/components/variations.gypi +++ b/components/variations.gypi @@ -71,6 +71,7 @@ 'dependencies': [ '../base/base.gyp:base', 'components.gyp:google_core_browser', + "components.gyp:metrics", 'variations', ], 'sources': [ diff --git a/components/variations/net/BUILD.gn b/components/variations/net/BUILD.gn index e35f5a84..34158fe 100644 --- a/components/variations/net/BUILD.gn +++ b/components/variations/net/BUILD.gn @@ -12,6 +12,7 @@ source_set("net") { deps = [ "//base", "//components/google/core/browser", + "//components/metrics", "//components/variations/proto", "//net", ] diff --git a/components/variations/net/DEPS b/components/variations/net/DEPS index f4a5acd..1abc71b 100644 --- a/components/variations/net/DEPS +++ b/components/variations/net/DEPS @@ -1,4 +1,5 @@ include_rules = [ "+components/google", + "+components/metrics", "+net", ] diff --git a/components/variations/net/variations_http_header_provider.cc b/components/variations/net/variations_http_header_provider.cc index 1220fae..fa630cf 100644 --- a/components/variations/net/variations_http_header_provider.cc +++ b/components/variations/net/variations_http_header_provider.cc @@ -137,6 +137,20 @@ void VariationsHttpHeaderProvider::OnFieldTrialGroupFinalized( UpdateVariationIDsHeaderValue(); } +void VariationsHttpHeaderProvider::OnSyntheticTrialsChanged( + const std::vector<metrics::SyntheticTrialGroup>& groups) { + base::AutoLock scoped_lock(lock_); + + synthetic_variation_ids_set_.clear(); + for (const metrics::SyntheticTrialGroup& group : groups) { + const VariationID id = + GetGoogleVariationIDFromHashes(GOOGLE_WEB_PROPERTIES, group.id); + if (id != EMPTY_ID) + synthetic_variation_ids_set_.insert(id); + } + UpdateVariationIDsHeaderValue(); +} + void VariationsHttpHeaderProvider::InitVariationIDsCacheIfNeeded() { base::AutoLock scoped_lock(lock_); if (variation_ids_cache_initialized_) @@ -186,7 +200,8 @@ void VariationsHttpHeaderProvider::UpdateVariationIDsHeaderValue() { variation_ids_header_.clear(); if (variation_ids_set_.empty() && default_variation_ids_set_.empty() && - variation_trigger_ids_set_.empty() && default_trigger_id_set_.empty()) { + variation_trigger_ids_set_.empty() && default_trigger_id_set_.empty() && + synthetic_variation_ids_set_.empty()) { return; } @@ -203,26 +218,20 @@ void VariationsHttpHeaderProvider::UpdateVariationIDsHeaderValue() { // Merge the two sets of experiment ids. std::set<VariationID> all_variation_ids_set = default_variation_ids_set_; - for (std::set<VariationID>::const_iterator it = variation_ids_set_.begin(); - it != variation_ids_set_.end(); ++it) { - all_variation_ids_set.insert(*it); - } - ClientVariations proto; - for (std::set<VariationID>::const_iterator it = all_variation_ids_set.begin(); - it != all_variation_ids_set.end(); ++it) { - proto.add_variation_id(*it); - } + for (VariationID id : variation_ids_set_) + all_variation_ids_set.insert(id); + for (VariationID id : synthetic_variation_ids_set_) + all_variation_ids_set.insert(id); std::set<VariationID> all_trigger_ids_set = default_trigger_id_set_; - for (std::set<VariationID>::const_iterator it = - variation_trigger_ids_set_.begin(); - it != variation_trigger_ids_set_.end(); ++it) { - all_trigger_ids_set.insert(*it); - } - for (std::set<VariationID>::const_iterator it = all_trigger_ids_set.begin(); - it != all_trigger_ids_set.end(); ++it) { - proto.add_trigger_variation_id(*it); - } + for (VariationID id : variation_trigger_ids_set_) + all_trigger_ids_set.insert(id); + + ClientVariations proto; + for (VariationID id : all_variation_ids_set) + proto.add_variation_id(id); + for (VariationID id : all_trigger_ids_set) + proto.add_trigger_variation_id(id); std::string serialized; proto.SerializeToString(&serialized); diff --git a/components/variations/net/variations_http_header_provider.h b/components/variations/net/variations_http_header_provider.h index a0e3046..0a511cc 100644 --- a/components/variations/net/variations_http_header_provider.h +++ b/components/variations/net/variations_http_header_provider.h @@ -7,11 +7,13 @@ #include <set> #include <string> +#include <vector> #include "base/basictypes.h" #include "base/gtest_prod_util.h" #include "base/metrics/field_trial.h" #include "base/synchronization/lock.h" +#include "components/metrics/metrics_service.h" #include "components/variations/variations_associated_data.h" namespace content { @@ -31,7 +33,8 @@ namespace variations { // A helper class for maintaining client experiments and metrics state // transmitted in custom HTTP request headers. // This class is a thread-safe singleton. -class VariationsHttpHeaderProvider : base::FieldTrialList::Observer { +class VariationsHttpHeaderProvider : public base::FieldTrialList::Observer, + public metrics::SyntheticTrialObserver { public: static VariationsHttpHeaderProvider* GetInstance(); @@ -66,12 +69,16 @@ class VariationsHttpHeaderProvider : base::FieldTrialList::Observer { VariationsHttpHeaderProvider(); ~VariationsHttpHeaderProvider() override; - // base::FieldTrialList::Observer implementation. + // base::FieldTrialList::Observer: // This will add the variation ID associated with |trial_name| and // |group_name| to the variation ID cache. void OnFieldTrialGroupFinalized(const std::string& trial_name, const std::string& group_name) override; + // metrics::SyntheticTrialObserver: + void OnSyntheticTrialsChanged( + const std::vector<metrics::SyntheticTrialGroup>& groups) override; + // Prepares the variation IDs cache with initial values if not already done. // This method also registers the caller with the FieldTrialList to receive // new variation IDs. @@ -102,6 +109,9 @@ class VariationsHttpHeaderProvider : base::FieldTrialList::Observer { std::set<VariationID> default_variation_ids_set_; std::set<VariationID> default_trigger_id_set_; + // Variations ids from synthetic field trials. + std::set<VariationID> synthetic_variation_ids_set_; + std::string variation_ids_header_; DISALLOW_COPY_AND_ASSIGN(VariationsHttpHeaderProvider); diff --git a/components/variations/variations_associated_data.cc b/components/variations/variations_associated_data.cc index 6ef2343..857ded5 100644 --- a/components/variations/variations_associated_data.cc +++ b/components/variations/variations_associated_data.cc @@ -184,17 +184,29 @@ void AssociateGoogleVariationIDForce(IDCollectionKey key, const std::string& trial_name, const std::string& group_name, VariationID id) { - GroupMapAccessor::GetInstance()->AssociateID( - key, MakeActiveGroupId(trial_name, group_name), id, true); + AssociateGoogleVariationIDForceHashes( + key, MakeActiveGroupId(trial_name, group_name), id); +} + +void AssociateGoogleVariationIDForceHashes(IDCollectionKey key, + const ActiveGroupId& active_group, + VariationID id) { + GroupMapAccessor::GetInstance()->AssociateID(key, active_group, id, true); } VariationID GetGoogleVariationID(IDCollectionKey key, const std::string& trial_name, const std::string& group_name) { - return GroupMapAccessor::GetInstance()->GetID( + return GetGoogleVariationIDFromHashes( key, MakeActiveGroupId(trial_name, group_name)); } +VariationID GetGoogleVariationIDFromHashes( + IDCollectionKey key, + const ActiveGroupId& active_group) { + return GroupMapAccessor::GetInstance()->GetID(key, active_group); +} + bool AssociateVariationParams( const std::string& trial_name, const std::string& group_name, diff --git a/components/variations/variations_associated_data.h b/components/variations/variations_associated_data.h index 8bacae1..3fe70f8 100644 --- a/components/variations/variations_associated_data.h +++ b/components/variations/variations_associated_data.h @@ -82,6 +82,11 @@ void AssociateGoogleVariationIDForce(IDCollectionKey key, const std::string& group_name, VariationID id); +// As above, but takes an ActiveGroupId hash pair, rather than the string names. +void AssociateGoogleVariationIDForceHashes(IDCollectionKey key, + const ActiveGroupId& active_group, + VariationID id); + // Retrieve the variations::VariationID associated with a FieldTrial group for // collection |key|. The group is denoted by |trial_name| and |group_name|. // This will return variations::kEmptyID if there is currently no associated ID @@ -92,6 +97,11 @@ VariationID GetGoogleVariationID(IDCollectionKey key, const std::string& trial_name, const std::string& group_name); +// Same as GetGoogleVariationID(), but takes in a hashed |active_group| rather +// than the string trial and group name. +VariationID GetGoogleVariationIDFromHashes(IDCollectionKey key, + const ActiveGroupId& active_group); + // Associates the specified set of key-value |params| with the variation // specified by |trial_name| and |group_name|. Fails and returns false if the // specified variation already has params associated with it or the field trial |