field_trial_params.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef BASE_METRICS_FIELD_TRIAL_PARAMS_H_
  5. #define BASE_METRICS_FIELD_TRIAL_PARAMS_H_
  6. #include <map>
  7. #include <string>
  8. #include "base/base_export.h"
  9. #include "base/logging.h"
  10. #include "base/notreached.h"
  11. #include "base/time/time.h"
  12. namespace base {
  13. struct Feature;
  14. // Key-value mapping type for field trial parameters.
  15. typedef std::map<std::string, std::string> FieldTrialParams;
  16. // Param string decoding function for AssociateFieldTrialParamsFromString().
  17. typedef std::string (*FieldTrialParamsDecodeStringFunc)(const std::string& str);
  18. // Unescapes special characters from the given string. Used in
  19. // AssociateFieldTrialParamsFromString() as one of the feature params decoding
  20. // functions.
  21. BASE_EXPORT std::string UnescapeValue(const std::string& value);
  22. // Associates the specified set of key-value |params| with the field trial
  23. // specified by |trial_name| and |group_name|. Fails and returns false if the
  24. // specified field trial already has params associated with it or the trial
  25. // is already active (group() has been called on it). Thread safe.
  26. BASE_EXPORT bool AssociateFieldTrialParams(const std::string& trial_name,
  27. const std::string& group_name,
  28. const FieldTrialParams& params);
  29. // Provides a mechanism to associate multiple set of params to multiple groups
  30. // with a formatted string as returned by FieldTrialList::AllParamsToString().
  31. // |decode_data_func| allows specifying a custom decoding function.
  32. BASE_EXPORT bool AssociateFieldTrialParamsFromString(
  33. const std::string& params_string,
  34. FieldTrialParamsDecodeStringFunc decode_data_func);
  35. // Retrieves the set of key-value |params| for the specified field trial, based
  36. // on its selected group. If the field trial does not exist or its selected
  37. // group does not have any parameters associated with it, returns false and
  38. // does not modify |params|. Calling this function will result in the field
  39. // trial being marked as active if found (i.e. group() will be called on it),
  40. // if it wasn't already. Thread safe.
  41. BASE_EXPORT bool GetFieldTrialParams(const std::string& trial_name,
  42. FieldTrialParams* params);
  43. // Retrieves the set of key-value |params| for the field trial associated with
  44. // the specified |feature|. A feature is associated with at most one field
  45. // trial and selected group. See base/feature_list.h for more information on
  46. // features. If the feature is not enabled, or if there's no associated params,
  47. // returns false and does not modify |params|. Calling this function will
  48. // result in the associated field trial being marked as active if found (i.e.
  49. // group() will be called on it), if it wasn't already. Thread safe.
  50. BASE_EXPORT bool GetFieldTrialParamsByFeature(const base::Feature& feature,
  51. FieldTrialParams* params);
  52. // Retrieves a specific parameter value corresponding to |param_name| for the
  53. // specified field trial, based on its selected group. If the field trial does
  54. // not exist or the specified parameter does not exist, returns an empty
  55. // string. Calling this function will result in the field trial being marked as
  56. // active if found (i.e. group() will be called on it), if it wasn't already.
  57. // Thread safe.
  58. BASE_EXPORT std::string GetFieldTrialParamValue(const std::string& trial_name,
  59. const std::string& param_name);
  60. // Retrieves a specific parameter value corresponding to |param_name| for the
  61. // field trial associated with the specified |feature|. A feature is associated
  62. // with at most one field trial and selected group. See base/feature_list.h for
  63. // more information on features. If the feature is not enabled, or the
  64. // specified parameter does not exist, returns an empty string. Calling this
  65. // function will result in the associated field trial being marked as active if
  66. // found (i.e. group() will be called on it), if it wasn't already. Thread safe.
  67. BASE_EXPORT std::string GetFieldTrialParamValueByFeature(
  68. const base::Feature& feature,
  69. const std::string& param_name);
  70. // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
  71. // string value into an int using base::StringToInt() and returns it, if
  72. // successful. Otherwise, it returns |default_value|. If the string value is not
  73. // empty and the conversion does not succeed, it produces a warning to LOG.
  74. BASE_EXPORT int GetFieldTrialParamByFeatureAsInt(const base::Feature& feature,
  75. const std::string& param_name,
  76. int default_value);
  77. // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
  78. // string value into a double using base::StringToDouble() and returns it, if
  79. // successful. Otherwise, it returns |default_value|. If the string value is not
  80. // empty and the conversion does not succeed, it produces a warning to LOG.
  81. BASE_EXPORT double GetFieldTrialParamByFeatureAsDouble(
  82. const base::Feature& feature,
  83. const std::string& param_name,
  84. double default_value);
  85. // Same as GetFieldTrialParamValueByFeature(). On top of that, it converts the
  86. // string value into a boolean and returns it, if successful. Otherwise, it
  87. // returns |default_value|. The only string representations accepted here are
  88. // "true" and "false". If the string value is not empty and the conversion does
  89. // not succeed, it produces a warning to LOG.
  90. BASE_EXPORT bool GetFieldTrialParamByFeatureAsBool(
  91. const base::Feature& feature,
  92. const std::string& param_name,
  93. bool default_value);
  94. // Shared declaration for various FeatureParam<T> types.
  95. //
  96. // This template is defined for the following types T:
  97. // bool
  98. // int
  99. // double
  100. // std::string
  101. // enum types
  102. // base::TimeDelta
  103. //
  104. // See the individual definitions below for the appropriate interfaces.
  105. // Attempting to use it with any other type is a compile error.
  106. template <typename T, bool IsEnum = std::is_enum<T>::value>
  107. struct FeatureParam {
  108. // Prevent use of FeatureParam<> with unsupported types (e.g. void*). Uses T
  109. // in its definition so that evaluation is deferred until the template is
  110. // instantiated.
  111. static_assert(!std::is_same<T, T>::value, "unsupported FeatureParam<> type");
  112. };
  113. // Declares a string-valued parameter. Example:
  114. //
  115. // constexpr FeatureParam<string> kAssistantName{
  116. // &kAssistantFeature, "assistant_name", "HAL"};
  117. //
  118. // If the feature is not set, or set to the empty string, then Get() will return
  119. // the default value.
  120. template <>
  121. struct FeatureParam<std::string> {
  122. constexpr FeatureParam(const Feature* feature,
  123. const char* name,
  124. const char* default_value)
  125. : feature(feature), name(name), default_value(default_value) {}
  126. BASE_EXPORT std::string Get() const;
  127. const Feature* const feature;
  128. const char* const name;
  129. const char* const default_value;
  130. };
  131. // Declares a double-valued parameter. Example:
  132. //
  133. // constexpr FeatureParam<double> kAssistantTriggerThreshold{
  134. // &kAssistantFeature, "trigger_threshold", 0.10};
  135. //
  136. // If the feature is not set, or set to an invalid double value, then Get() will
  137. // return the default value.
  138. template <>
  139. struct FeatureParam<double> {
  140. constexpr FeatureParam(const Feature* feature,
  141. const char* name,
  142. double default_value)
  143. : feature(feature), name(name), default_value(default_value) {}
  144. BASE_EXPORT double Get() const;
  145. const Feature* const feature;
  146. const char* const name;
  147. const double default_value;
  148. };
  149. // Declares an int-valued parameter. Example:
  150. //
  151. // constexpr FeatureParam<int> kAssistantParallelism{
  152. // &kAssistantFeature, "parallelism", 4};
  153. //
  154. // If the feature is not set, or set to an invalid int value, then Get() will
  155. // return the default value.
  156. template <>
  157. struct FeatureParam<int> {
  158. constexpr FeatureParam(const Feature* feature,
  159. const char* name,
  160. int default_value)
  161. : feature(feature), name(name), default_value(default_value) {}
  162. BASE_EXPORT int Get() const;
  163. const Feature* const feature;
  164. const char* const name;
  165. const int default_value;
  166. };
  167. // Declares a bool-valued parameter. Example:
  168. //
  169. // constexpr FeatureParam<int> kAssistantIsHelpful{
  170. // &kAssistantFeature, "is_helpful", true};
  171. //
  172. // If the feature is not set, or set to value other than "true" or "false", then
  173. // Get() will return the default value.
  174. template <>
  175. struct FeatureParam<bool> {
  176. constexpr FeatureParam(const Feature* feature,
  177. const char* name,
  178. bool default_value)
  179. : feature(feature), name(name), default_value(default_value) {}
  180. BASE_EXPORT bool Get() const;
  181. const Feature* const feature;
  182. const char* const name;
  183. const bool default_value;
  184. };
  185. // Declares an TimeDelta-valued parameter. Example:
  186. //
  187. // constexpr base::FeatureParam<base::TimeDelta> kPerAgentDelayMs{
  188. // &kPerAgentSchedulingExperiments, "delay_ms", base::TimeDelta()};
  189. //
  190. // If the feature is not set, or set to an invalid value (as defined by
  191. // base::TimeDelta::FromString()), then Get() will return the default value.
  192. template <>
  193. struct FeatureParam<base::TimeDelta> {
  194. constexpr FeatureParam(const Feature* feature,
  195. const char* name,
  196. base::TimeDelta default_value)
  197. : feature(feature), name(name), default_value(default_value) {}
  198. BASE_EXPORT base::TimeDelta Get() const;
  199. const Feature* const feature;
  200. const char* const name;
  201. const base::TimeDelta default_value;
  202. };
  203. BASE_EXPORT void LogInvalidEnumValue(const Feature& feature,
  204. const std::string& param_name,
  205. const std::string& value_as_string,
  206. int default_value_as_int);
  207. // Feature param declaration for an enum, with associated options. Example:
  208. //
  209. // constexpr FeatureParam<ShapeEnum>::Option kShapeParamOptions[] = {
  210. // {SHAPE_CIRCLE, "circle"},
  211. // {SHAPE_CYLINDER, "cylinder"},
  212. // {SHAPE_PAPERCLIP, "paperclip"}};
  213. // constexpr FeatureParam<ShapeEnum> kAssistantShapeParam{
  214. // &kAssistantFeature, "shape", SHAPE_CIRCLE, &kShapeParamOptions};
  215. //
  216. // With this declaration, the parameter may be set to "circle", "cylinder", or
  217. // "paperclip", and that will be translated to one of the three enum values. By
  218. // default, or if the param is set to an unknown value, the parameter will be
  219. // assumed to be SHAPE_CIRCLE.
  220. template <typename Enum>
  221. struct FeatureParam<Enum, true> {
  222. struct Option {
  223. constexpr Option(Enum value, const char* name) : value(value), name(name) {}
  224. const Enum value;
  225. const char* const name;
  226. };
  227. template <size_t option_count>
  228. constexpr FeatureParam(const Feature* feature,
  229. const char* name,
  230. const Enum default_value,
  231. const Option (*options)[option_count])
  232. : feature(feature),
  233. name(name),
  234. default_value(default_value),
  235. options(*options),
  236. option_count(option_count) {
  237. static_assert(option_count >= 1, "FeatureParam<enum> has no options");
  238. }
  239. Enum Get() const {
  240. std::string value = GetFieldTrialParamValueByFeature(*feature, name);
  241. if (value.empty())
  242. return default_value;
  243. for (size_t i = 0; i < option_count; ++i) {
  244. if (value == options[i].name)
  245. return options[i].value;
  246. }
  247. LogInvalidEnumValue(*feature, name, value, static_cast<int>(default_value));
  248. return default_value;
  249. }
  250. // Returns the param-string for the given enum value.
  251. std::string GetName(Enum value) const {
  252. for (size_t i = 0; i < option_count; ++i) {
  253. if (value == options[i].value)
  254. return options[i].name;
  255. }
  256. NOTREACHED();
  257. return "";
  258. }
  259. const base::Feature* const feature;
  260. const char* const name;
  261. const Enum default_value;
  262. const Option* const options;
  263. const size_t option_count;
  264. };
  265. } // namespace base
  266. #endif // BASE_METRICS_FIELD_TRIAL_PARAMS_H_