chromium/base/metrics/field_trial.h

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

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
#pragma allow_unsafe_buffers
#endif

// The FieldTrial class handles the lower level configuration of running A/B
// tests.
//
// Most server-side experiments should be configured using Features which
// have a simpler interface. See base/feature_list.h for details on
// configurating a Feature for an experiment.

// In certain cases you may still need to use FieldTrial directly. This is
// generally for either:
// - Client-configured experiments:
//     The experiment is controlled directly in the code. For example, if the
//     server controlled behavior is not yet available. See below documentation.
// - Synthetic field trials:
//     These act like field trials for reporting purposes, but the group
//     placement is controlled directly. See RegisterSyntheticFieldTrial().

// If you have access, see go/client-side-field-trials for additional context.

//------------------------------------------------------------------------------
// Details:

// FieldTrial is a class for handling details of statistical experiments
// performed by actual users in the field (i.e., in a shipped or beta product).
// All code is called exclusively on the UI thread currently. It only handles
// the lower level details, server-side experiments should use
// generally use Features (see above).
//
// The simplest example is an experiment to see whether one of two options
// produces "better" results across our user population.  In that scenario, UMA
// data is uploaded to aggregate the test results, and this FieldTrial class
// manages the state of each such experiment (state == which option was
// pseudo-randomly selected).
//
// States are typically generated randomly, either based on a one time
// randomization (which will yield the same results, in terms of selecting
// the client for a field trial or not, for every run of the program on a
// given machine), or by a session randomization (generated each time the
// application starts up, but held constant during the duration of the
// process).

//------------------------------------------------------------------------------
// Example:  Suppose we have an experiment involving memory, such as determining
// the impact of some pruning algorithm. Note that using this API directly is
// not recommended, see above.

// // FieldTrials are reference counted, and persist automagically until
// // process teardown, courtesy of their automatic registration in
// // FieldTrialList.
// scoped_refptr<base::FieldTrial> trial(
//     base::FieldTrialList::FactoryGetFieldTrial(
//         "MemoryExperiment", 1000, "StandardMem", entropy_provider);
//
// trial->AppendGroup("HighMem", 20);  // 2% in HighMem group.
// trial->AppendGroup("LowMem", 20);   // 2% in LowMem group.
// // Take action depending of which group we randomly land in.
// if (trial->group_name() == "HighMem")
//   SetPruningAlgorithm(kType1);
// else if (trial->group_name() == "LowMem")
//   SetPruningAlgorithm(kType2);

//------------------------------------------------------------------------------

#ifndef BASE_METRICS_FIELD_TRIAL_H_
#define BASE_METRICS_FIELD_TRIAL_H_

#include <stddef.h>
#include <stdint.h>

#include <atomic>
#include <functional>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <string_view>
#include <vector>

#include "base/atomicops.h"
#include "base/base_export.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/metrics/persistent_memory_allocator.h"
#include "base/pickle.h"
#include "base/synchronization/lock.h"
#include "base/types/expected.h"
#include "base/types/pass_key.h"
#include "build/blink_buildflags.h"
#include "build/build_config.h"

#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_APPLE)
#include "base/files/platform_file.h"
#include "base/posix/global_descriptors.h"
#endif

namespace base {

namespace test {
class ScopedFeatureList;
}  // namespace test

class CompareActiveGroupToFieldTrialMatcher;
class FieldTrialList;
struct LaunchOptions;

#if BUILDFLAG(USE_BLINK)
namespace shared_memory {
enum class SharedMemoryError;
}  // namespace shared_memory
#endif

class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {};

//------------------------------------------------------------------------------
// Class with a list of all active field trials.  A trial is active if it has
// been registered, which includes evaluating its state based on its
// probability. Only one instance of this class exists and outside of testing,
// will live for the entire life time of the process.
class BASE_EXPORT FieldTrialList {};

}  // namespace base

#endif  // BASE_METRICS_FIELD_TRIAL_H_