chromium/chrome/browser/metrics/chrome_browser_sampling_trials.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/metrics/chrome_browser_sampling_trials.h"

#include "base/feature_list.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/metrics/chrome_metrics_services_manager_client.h"
#include "chrome/common/channel_info.h"
#include "components/ukm/ukm_recorder_impl.h"
#include "components/version_info/channel.h"

namespace metrics {
namespace {

// Note that the trial name must be kept in sync with the server config
// controlling sampling. If they don't match, then clients will be shuffled into
// different groups when the server config takes over from the fallback trial.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
constexpr char kSamplingTrialName[] = "MetricsAndCrashSampling";
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_ANDROID)
constexpr char kPostFREFixSamplingTrialName[] =
    "PostFREFixMetricsAndCrashSampling";
#endif  // BUILDFLAG(IS_ANDROID)
constexpr char kUkmSamplingTrialName[] =;

#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)
// Appends a group to the sampling controlling |trial|. The group will be
// associated with a variation param for reporting sampling |rate| in per mille.
void AppendSamplingTrialGroup(const std::string& group_name,
                              int rate,
                              base::FieldTrial* trial) {
  std::map<std::string, std::string> params = {
      {metrics::internal::kRateParamName, base::NumberToString(rate)}};
  base::AssociateFieldTrialParams(trial->trial_name(), group_name, params);
  trial->AppendGroup(group_name, rate);
}

// Unconditionally attempts to create a field trial to control client side
// metrics/crash sampling to use as a fallback when one hasn't been
// provided. This is expected to occur on first-run on platforms that don't
// have first-run variations support. This should only be called when there is
// no existing field trial controlling the sampling feature, and on the
// correct platform. |trial_name| is the name of the trial. |feature_name| is
// the name of the feature that determines sampling. |sampled_in_rate| is the
// sampling rate per mille.
void CreateFallbackSamplingTrial(
    const base::FieldTrial::EntropyProvider& entropy_provider,
    const std::string& trial_name,
    const std::string& feature_name,
    const int sampled_in_rate_per_mille,
    const bool starts_active,
    base::FeatureList* feature_list) {
  scoped_refptr<base::FieldTrial> trial(
      base::FieldTrialList::FactoryGetFieldTrial(
          trial_name, /*total_probability=*/1000, "Default", entropy_provider));

  // Like the trial name, the order that these two groups are added to the trial
  // must be kept in sync with the order that they appear in the server config.
  // The desired order is: OutOfReportingSample, InReportingSample.

  const char kSampledOutGroup[] = "OutOfReportingSample";
  const int sampled_out_rate_per_mille = 1000 - sampled_in_rate_per_mille;
  AppendSamplingTrialGroup(kSampledOutGroup, sampled_out_rate_per_mille,
                           trial.get());

  const char kInSampleGroup[] = "InReportingSample";
  AppendSamplingTrialGroup(kInSampleGroup, sampled_in_rate_per_mille,
                           trial.get());

  // Set up the feature. This must be done after all groups are added since
  // GetGroupNameWithoutActivation() will finalize the group choice.
  const std::string& group_name = trial->GetGroupNameWithoutActivation();

  feature_list->RegisterFieldTrialOverride(
      feature_name,
      group_name == kSampledOutGroup
          ? base::FeatureList::OVERRIDE_DISABLE_FEATURE
          : base::FeatureList::OVERRIDE_ENABLE_FEATURE,
      trial.get());

  if (starts_active) {
    trial->Activate();
  }
}
#endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID)

// Unconditionally attempts to create a field trial to control client side
// UKM sampling to use as a fallback when one hasn't been provided. This is
// expected to occur on first-run on platforms that don't have first-run
// variations support. This should only be called when there is no existing
// field trial controlling the sampling feature.
void CreateFallbackUkmSamplingTrial(
    const base::FieldTrial::EntropyProvider& entropy_provider,
    bool is_stable_channel,
    base::FeatureList* feature_list) {}

}  // namespace

void CreateFallbackSamplingTrialsIfNeeded(
    const base::FieldTrial::EntropyProvider& entropy_provider,
    base::FeatureList* feature_list) {}

void CreateFallbackUkmSamplingTrialIfNeeded(
    const base::FieldTrial::EntropyProvider& entropy_provider,
    base::FeatureList* feature_list) {}

}  // namespace metrics