stats.cc 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569
  1. // Copyright 2021 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. #include "components/segmentation_platform/internal/stats.h"
  5. #include "base/metrics/histogram_functions.h"
  6. #include "base/metrics/histogram_macros.h"
  7. #include "base/notreached.h"
  8. #include "base/strings/strcat.h"
  9. #include "components/segmentation_platform/public/config.h"
  10. #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
  11. #include "components/segmentation_platform/public/proto/types.pb.h"
  12. namespace segmentation_platform::stats {
  13. namespace {
  14. // Keep in sync with AdaptiveToolbarButtonVariant in enums.xml.
  15. enum class AdaptiveToolbarButtonVariant {
  16. kUnknown = 0,
  17. kNone = 1,
  18. kNewTab = 2,
  19. kShare = 3,
  20. kVoice = 4,
  21. kMaxValue = kVoice,
  22. };
  23. // This is the segmentation subset of
  24. // proto::SegmentId.
  25. // Keep in sync with SegmentationPlatformSegmentationModel in
  26. // //tools/metrics/histograms/enums.xml.
  27. // See also SegmentationModel variant in
  28. // //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
  29. enum class SegmentationModel {
  30. kUnknown = 0,
  31. kNewTab = 4,
  32. kShare = 5,
  33. kVoice = 6,
  34. kDummy = 10,
  35. kChromeStartAndroid = 11,
  36. kQueryTiles = 12,
  37. kChromeLowUserEngagement = 16,
  38. kFeedUserSegment = 17,
  39. kContextualPageActionPriceTracking = 18,
  40. kMaxValue = kContextualPageActionPriceTracking,
  41. };
  42. AdaptiveToolbarButtonVariant OptimizationTargetToAdaptiveToolbarButtonVariant(
  43. SegmentId segment_id) {
  44. switch (segment_id) {
  45. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  46. return AdaptiveToolbarButtonVariant::kNewTab;
  47. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  48. return AdaptiveToolbarButtonVariant::kShare;
  49. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  50. return AdaptiveToolbarButtonVariant::kVoice;
  51. case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
  52. return AdaptiveToolbarButtonVariant::kNone;
  53. default:
  54. NOTREACHED();
  55. return AdaptiveToolbarButtonVariant::kUnknown;
  56. }
  57. }
  58. bool IsBooleanSegment(const std::string& segmentation_key) {
  59. // Please keep in sync with BooleanModel variant in
  60. // //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
  61. return segmentation_key == kChromeStartAndroidSegmentationKey ||
  62. segmentation_key == kQueryTilesSegmentationKey ||
  63. segmentation_key == kChromeLowUserEngagementSegmentationKey ||
  64. segmentation_key == kFeedUserSegmentationKey;
  65. }
  66. BooleanSegmentSwitch GetBooleanSegmentSwitch(SegmentId new_selection,
  67. SegmentId previous_selection) {
  68. if (new_selection != SegmentId::OPTIMIZATION_TARGET_UNKNOWN &&
  69. previous_selection == SegmentId::OPTIMIZATION_TARGET_UNKNOWN) {
  70. return BooleanSegmentSwitch::kNoneToEnabled;
  71. } else if (new_selection == SegmentId::OPTIMIZATION_TARGET_UNKNOWN &&
  72. previous_selection != SegmentId::OPTIMIZATION_TARGET_UNKNOWN) {
  73. return BooleanSegmentSwitch::kEnabledToNone;
  74. }
  75. return BooleanSegmentSwitch::kUnknown;
  76. }
  77. AdaptiveToolbarSegmentSwitch GetAdaptiveToolbarSegmentSwitch(
  78. SegmentId new_selection,
  79. SegmentId previous_selection) {
  80. switch (previous_selection) {
  81. case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
  82. switch (new_selection) {
  83. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  84. return AdaptiveToolbarSegmentSwitch::kNoneToNewTab;
  85. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  86. return AdaptiveToolbarSegmentSwitch::kNoneToShare;
  87. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  88. return AdaptiveToolbarSegmentSwitch::kNoneToVoice;
  89. default:
  90. NOTREACHED();
  91. return AdaptiveToolbarSegmentSwitch::kUnknown;
  92. }
  93. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  94. switch (new_selection) {
  95. case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
  96. return AdaptiveToolbarSegmentSwitch::kNewTabToNone;
  97. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  98. return AdaptiveToolbarSegmentSwitch::kNewTabToShare;
  99. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  100. return AdaptiveToolbarSegmentSwitch::kNewTabToVoice;
  101. default:
  102. NOTREACHED();
  103. return AdaptiveToolbarSegmentSwitch::kUnknown;
  104. }
  105. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  106. switch (new_selection) {
  107. case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
  108. return AdaptiveToolbarSegmentSwitch::kShareToNone;
  109. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  110. return AdaptiveToolbarSegmentSwitch::kShareToNewTab;
  111. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  112. return AdaptiveToolbarSegmentSwitch::kShareToVoice;
  113. default:
  114. NOTREACHED();
  115. return AdaptiveToolbarSegmentSwitch::kUnknown;
  116. }
  117. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  118. switch (new_selection) {
  119. case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
  120. return AdaptiveToolbarSegmentSwitch::kVoiceToNone;
  121. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  122. return AdaptiveToolbarSegmentSwitch::kVoiceToNewTab;
  123. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  124. return AdaptiveToolbarSegmentSwitch::kVoiceToShare;
  125. default:
  126. NOTREACHED();
  127. return AdaptiveToolbarSegmentSwitch::kUnknown;
  128. }
  129. default:
  130. NOTREACHED();
  131. return AdaptiveToolbarSegmentSwitch::kUnknown;
  132. }
  133. }
  134. SegmentationModel OptimizationTargetToSegmentationModel(SegmentId segment_id) {
  135. switch (segment_id) {
  136. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  137. return SegmentationModel::kNewTab;
  138. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  139. return SegmentationModel::kShare;
  140. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  141. return SegmentationModel::kVoice;
  142. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY:
  143. return SegmentationModel::kDummy;
  144. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID:
  145. return SegmentationModel::kChromeStartAndroid;
  146. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES:
  147. return SegmentationModel::kQueryTiles;
  148. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT:
  149. return SegmentationModel::kChromeLowUserEngagement;
  150. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_FEED_USER:
  151. return SegmentationModel::kFeedUserSegment;
  152. case SegmentId::OPTIMIZATION_TARGET_CONTEXTUAL_PAGE_ACTION_PRICE_TRACKING:
  153. return SegmentationModel::kContextualPageActionPriceTracking;
  154. default:
  155. return SegmentationModel::kUnknown;
  156. }
  157. }
  158. // Should map to ModelExecutionStatus variant string in
  159. // //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
  160. absl::optional<base::StringPiece> ModelExecutionStatusToHistogramVariant(
  161. ModelExecutionStatus status) {
  162. switch (status) {
  163. case ModelExecutionStatus::kSuccess:
  164. return "Success";
  165. case ModelExecutionStatus::kExecutionError:
  166. return "ExecutionError";
  167. // Only record duration histograms when tflite model is executed. These
  168. // cases mean the execution was skipped.
  169. case ModelExecutionStatus::kSkippedInvalidMetadata:
  170. case ModelExecutionStatus::kSkippedModelNotReady:
  171. case ModelExecutionStatus::kSkippedHasFreshResults:
  172. case ModelExecutionStatus::kSkippedNotEnoughSignals:
  173. case ModelExecutionStatus::kSkippedResultNotExpired:
  174. case ModelExecutionStatus::kFailedToSaveResultAfterSuccess:
  175. return absl::nullopt;
  176. }
  177. }
  178. // Should map to SignalType variant string in
  179. // //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
  180. std::string SignalTypeToHistogramVariant(proto::SignalType signal_type) {
  181. switch (signal_type) {
  182. case proto::SignalType::USER_ACTION:
  183. return "UserAction";
  184. case proto::SignalType::HISTOGRAM_ENUM:
  185. return "HistogramEnum";
  186. case proto::SignalType::HISTOGRAM_VALUE:
  187. return "HistogramValue";
  188. default:
  189. NOTREACHED();
  190. return "Unknown";
  191. }
  192. }
  193. float ZeroValueFraction(const std::vector<float>& tensor) {
  194. if (tensor.size() == 0)
  195. return 0;
  196. size_t zero_values = 0;
  197. for (float feature : tensor) {
  198. if (feature == 0)
  199. ++zero_values;
  200. }
  201. return static_cast<float>(zero_values) / static_cast<float>(tensor.size());
  202. }
  203. } // namespace
  204. void RecordModelScore(SegmentId segment_id, float score) {
  205. // Special case adaptive toolbar models since it already has histograms being
  206. // recorded and updating names will affect current work.
  207. switch (segment_id) {
  208. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  209. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  210. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  211. base::UmaHistogramPercentage(
  212. "SegmentationPlatform.AdaptiveToolbar.ModelScore." +
  213. SegmentIdToHistogramVariant(segment_id),
  214. score * 100);
  215. break;
  216. default:
  217. break;
  218. }
  219. switch (segment_id) {
  220. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
  221. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
  222. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
  223. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY:
  224. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID:
  225. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES:
  226. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT:
  227. case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_FEED_USER:
  228. case SegmentId::OPTIMIZATION_TARGET_CONTEXTUAL_PAGE_ACTION_PRICE_TRACKING:
  229. // Assumes all models return score between 0 and 1. This is true for all
  230. // the models we have currently.
  231. base::UmaHistogramPercentage("SegmentationPlatform.ModelScore." +
  232. SegmentIdToHistogramVariant(segment_id),
  233. score * 100);
  234. break;
  235. default:
  236. break;
  237. }
  238. }
  239. void RecordModelUpdateTimeDifference(SegmentId segment_id,
  240. int64_t model_update_time) {
  241. // |model_update_time| might be empty for data persisted before M101.
  242. if (model_update_time) {
  243. base::Time model_updated_time = base::Time::FromDeltaSinceWindowsEpoch(
  244. base::Seconds(model_update_time));
  245. base::UmaHistogramCounts1000(
  246. "SegmentationPlatform.Init.ModelUpdatedTimeDifferenceInDays." +
  247. SegmentIdToHistogramVariant(segment_id),
  248. (base::Time::Now() - model_updated_time).InDays());
  249. }
  250. }
  251. void RecordSegmentSelectionComputed(
  252. const std::string& segmentation_key,
  253. SegmentId new_selection,
  254. absl::optional<SegmentId> previous_selection) {
  255. // Special case adaptive toolbar since it already has histograms being
  256. // recorded and updating names will affect current work.
  257. if (segmentation_key == kAdaptiveToolbarSegmentationKey) {
  258. base::UmaHistogramEnumeration(
  259. "SegmentationPlatform.AdaptiveToolbar.SegmentSelection.Computed",
  260. OptimizationTargetToAdaptiveToolbarButtonVariant(new_selection));
  261. }
  262. std::string computed_hist = base::StrCat(
  263. {"SegmentationPlatform.", SegmentationKeyToUmaName(segmentation_key),
  264. ".SegmentSelection.Computed2"});
  265. base::UmaHistogramEnumeration(
  266. computed_hist, OptimizationTargetToSegmentationModel(new_selection));
  267. SegmentId prev_segment = previous_selection.has_value()
  268. ? previous_selection.value()
  269. : SegmentId::OPTIMIZATION_TARGET_UNKNOWN;
  270. if (prev_segment == new_selection)
  271. return;
  272. std::string switched_hist = base::StrCat(
  273. {"SegmentationPlatform.", SegmentationKeyToUmaName(segmentation_key),
  274. ".SegmentSwitched"});
  275. if (segmentation_key == kAdaptiveToolbarSegmentationKey) {
  276. base::UmaHistogramEnumeration(
  277. switched_hist,
  278. GetAdaptiveToolbarSegmentSwitch(new_selection, prev_segment));
  279. } else if (IsBooleanSegment(segmentation_key)) {
  280. base::UmaHistogramEnumeration(
  281. switched_hist, GetBooleanSegmentSwitch(new_selection, prev_segment));
  282. }
  283. // Do not record switched histogram for all keys by default, the client needs
  284. // to write custom logic for other kinds of segments.
  285. }
  286. void RecordMaintenanceCleanupSignalSuccessCount(size_t count) {
  287. UMA_HISTOGRAM_COUNTS_1000(
  288. "SegmentationPlatform.Maintenance.CleanupSignalSuccessCount", count);
  289. }
  290. void RecordMaintenanceCompactionResult(proto::SignalType signal_type,
  291. bool success) {
  292. base::UmaHistogramBoolean(
  293. "SegmentationPlatform.Maintenance.CompactionResult." +
  294. SignalTypeToHistogramVariant(signal_type),
  295. success);
  296. }
  297. void RecordMaintenanceSignalIdentifierCount(size_t count) {
  298. UMA_HISTOGRAM_COUNTS_1000(
  299. "SegmentationPlatform.Maintenance.SignalIdentifierCount", count);
  300. }
  301. void RecordModelDeliveryHasMetadata(SegmentId segment_id, bool has_metadata) {
  302. base::UmaHistogramBoolean("SegmentationPlatform.ModelDelivery.HasMetadata." +
  303. SegmentIdToHistogramVariant(segment_id),
  304. has_metadata);
  305. }
  306. void RecordModelDeliveryMetadataFeatureCount(SegmentId segment_id,
  307. size_t count) {
  308. base::UmaHistogramCounts1000(
  309. "SegmentationPlatform.ModelDelivery.Metadata.FeatureCount." +
  310. SegmentIdToHistogramVariant(segment_id),
  311. count);
  312. }
  313. void RecordModelDeliveryMetadataValidation(
  314. SegmentId segment_id,
  315. bool processed,
  316. metadata_utils::ValidationResult validation_result) {
  317. // Should map to ValidationPhase variant string in
  318. // //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
  319. std::string validation_phase = processed ? "Processed" : "Incoming";
  320. base::UmaHistogramEnumeration(
  321. "SegmentationPlatform.ModelDelivery.Metadata.Validation." +
  322. validation_phase + "." + SegmentIdToHistogramVariant(segment_id),
  323. validation_result);
  324. }
  325. void RecordModelDeliveryReceived(SegmentId segment_id) {
  326. UMA_HISTOGRAM_ENUMERATION("SegmentationPlatform.ModelDelivery.Received",
  327. OptimizationTargetToSegmentationModel(segment_id));
  328. }
  329. void RecordModelDeliverySaveResult(SegmentId segment_id, bool success) {
  330. base::UmaHistogramBoolean("SegmentationPlatform.ModelDelivery.SaveResult." +
  331. SegmentIdToHistogramVariant(segment_id),
  332. success);
  333. }
  334. void RecordModelDeliverySegmentIdMatches(SegmentId segment_id, bool matches) {
  335. base::UmaHistogramBoolean(
  336. "SegmentationPlatform.ModelDelivery.SegmentIdMatches." +
  337. SegmentIdToHistogramVariant(segment_id),
  338. matches);
  339. }
  340. void RecordModelExecutionDurationFeatureProcessing(SegmentId segment_id,
  341. base::TimeDelta duration) {
  342. base::UmaHistogramTimes(
  343. "SegmentationPlatform.ModelExecution.Duration.FeatureProcessing." +
  344. SegmentIdToHistogramVariant(segment_id),
  345. duration);
  346. }
  347. void RecordModelExecutionDurationModel(SegmentId segment_id,
  348. bool success,
  349. base::TimeDelta duration) {
  350. ModelExecutionStatus status = success ? ModelExecutionStatus::kSuccess
  351. : ModelExecutionStatus::kExecutionError;
  352. absl::optional<base::StringPiece> status_variant =
  353. ModelExecutionStatusToHistogramVariant(status);
  354. if (!status_variant)
  355. return;
  356. base::UmaHistogramTimes(
  357. base::StrCat({"SegmentationPlatform.ModelExecution.Duration.Model.",
  358. SegmentIdToHistogramVariant(segment_id), ".",
  359. *status_variant}),
  360. duration);
  361. }
  362. void RecordModelExecutionDurationTotal(SegmentId segment_id,
  363. ModelExecutionStatus status,
  364. base::TimeDelta duration) {
  365. absl::optional<base::StringPiece> status_variant =
  366. ModelExecutionStatusToHistogramVariant(status);
  367. if (!status_variant)
  368. return;
  369. base::UmaHistogramTimes(
  370. base::StrCat({"SegmentationPlatform.ModelExecution.Duration.Total.",
  371. SegmentIdToHistogramVariant(segment_id), ".",
  372. *status_variant}),
  373. duration);
  374. }
  375. void RecordOnDemandSegmentSelectionDuration(
  376. const std::string& segmentation_key,
  377. const SegmentSelectionResult& result,
  378. base::TimeDelta duration) {
  379. std::string histogram_prefix =
  380. base::StrCat({"SegmentationPlatform.SegmentSelectionOnDemand.Duration.",
  381. SegmentationKeyToUmaName(segmentation_key), "."});
  382. base::UmaHistogramTimes(base::StrCat({histogram_prefix, "Any"}), duration);
  383. std::string histogram_name =
  384. base::StrCat({histogram_prefix,
  385. result.segment.has_value()
  386. ? SegmentIdToHistogramVariant(result.segment.value())
  387. : "None"});
  388. base::UmaHistogramTimes(histogram_name, duration);
  389. }
  390. void RecordModelExecutionResult(SegmentId segment_id, float result) {
  391. base::UmaHistogramPercentage("SegmentationPlatform.ModelExecution.Result." +
  392. SegmentIdToHistogramVariant(segment_id),
  393. result * 100);
  394. }
  395. void RecordModelExecutionSaveResult(SegmentId segment_id, bool success) {
  396. base::UmaHistogramBoolean("SegmentationPlatform.ModelExecution.SaveResult." +
  397. SegmentIdToHistogramVariant(segment_id),
  398. success);
  399. }
  400. void RecordModelExecutionStatus(SegmentId segment_id,
  401. bool default_provider,
  402. ModelExecutionStatus status) {
  403. if (!default_provider) {
  404. base::UmaHistogramEnumeration(
  405. "SegmentationPlatform.ModelExecution.Status." +
  406. SegmentIdToHistogramVariant(segment_id),
  407. status);
  408. } else {
  409. base::UmaHistogramEnumeration(
  410. "SegmentationPlatform.ModelExecution.DefaultProvider.Status." +
  411. SegmentIdToHistogramVariant(segment_id),
  412. status);
  413. }
  414. }
  415. void RecordModelExecutionZeroValuePercent(SegmentId segment_id,
  416. const std::vector<float>& tensor) {
  417. base::UmaHistogramPercentage(
  418. "SegmentationPlatform.ModelExecution.ZeroValuePercent." +
  419. SegmentIdToHistogramVariant(segment_id),
  420. ZeroValueFraction(tensor) * 100);
  421. }
  422. void RecordSignalDatabaseGetSamplesDatabaseEntryCount(size_t count) {
  423. UMA_HISTOGRAM_COUNTS_1000(
  424. "SegmentationPlatform.SignalDatabase.GetSamples.DatabaseEntryCount",
  425. count);
  426. }
  427. void RecordSignalDatabaseGetSamplesResult(bool success) {
  428. UMA_HISTOGRAM_BOOLEAN("SegmentationPlatform.SignalDatabase.GetSamples.Result",
  429. success);
  430. }
  431. void RecordSignalDatabaseGetSamplesSampleCount(size_t count) {
  432. UMA_HISTOGRAM_COUNTS_10000(
  433. "SegmentationPlatform.SignalDatabase.GetSamples.SampleCount", count);
  434. }
  435. void RecordSignalsListeningCount(
  436. const std::set<uint64_t>& user_actions,
  437. const std::set<std::pair<std::string, proto::SignalType>>& histograms) {
  438. uint64_t user_action_count = user_actions.size();
  439. uint64_t histogram_enum_count = 0;
  440. uint64_t histogram_value_count = 0;
  441. for (auto& s : histograms) {
  442. if (s.second == proto::SignalType::HISTOGRAM_ENUM)
  443. ++histogram_enum_count;
  444. if (s.second == proto::SignalType::HISTOGRAM_VALUE)
  445. ++histogram_value_count;
  446. }
  447. base::UmaHistogramCounts1000(
  448. "SegmentationPlatform.Signals.ListeningCount." +
  449. SignalTypeToHistogramVariant(proto::SignalType::USER_ACTION),
  450. user_action_count);
  451. base::UmaHistogramCounts1000(
  452. "SegmentationPlatform.Signals.ListeningCount." +
  453. SignalTypeToHistogramVariant(proto::SignalType::HISTOGRAM_ENUM),
  454. histogram_enum_count);
  455. base::UmaHistogramCounts1000(
  456. "SegmentationPlatform.Signals.ListeningCount." +
  457. SignalTypeToHistogramVariant(proto::SignalType::HISTOGRAM_VALUE),
  458. histogram_value_count);
  459. }
  460. void RecordSegmentSelectionFailure(const std::string& segmentation_key,
  461. SegmentationSelectionFailureReason reason) {
  462. base::UmaHistogramEnumeration(
  463. base::StrCat({"SegmentationPlatform.SelectionFailedReason.",
  464. SegmentationKeyToUmaName(segmentation_key)}),
  465. reason);
  466. }
  467. std::string FeatureProcessingErrorToString(FeatureProcessingError error) {
  468. switch (error) {
  469. case FeatureProcessingError::kUkmEngineDisabled:
  470. return "UkmEngineDisabled";
  471. case FeatureProcessingError::kUmaValidationError:
  472. return "UmaValidationError";
  473. case FeatureProcessingError::kSqlValidationError:
  474. return "SqlValidationError";
  475. case FeatureProcessingError::kCustomInputError:
  476. return "CustomInputError";
  477. case FeatureProcessingError::kSqlBindValuesError:
  478. return "SqlBindValuesError";
  479. case FeatureProcessingError::kSqlQueryRunError:
  480. return "SqlQueryRunError";
  481. case FeatureProcessingError::kResultTensorError:
  482. return "ResultTensorError";
  483. default:
  484. return "Other";
  485. }
  486. }
  487. void RecordFeatureProcessingError(SegmentId segment_id,
  488. FeatureProcessingError error) {
  489. base::UmaHistogramEnumeration(
  490. "SegmentationPlatform.FeatureProcessing.Error." +
  491. SegmentIdToHistogramVariant(segment_id),
  492. error);
  493. }
  494. void RecordModelAvailability(SegmentId segment_id,
  495. SegmentationModelAvailability availability) {
  496. base::UmaHistogramEnumeration("SegmentationPlatform.ModelAvailability." +
  497. SegmentIdToHistogramVariant(segment_id),
  498. availability);
  499. }
  500. void RecordTooManyInputTensors(int tensor_size) {
  501. UMA_HISTOGRAM_COUNTS_100(
  502. "SegmentationPlatform.StructuredMetrics.TooManyTensors.Count",
  503. tensor_size);
  504. }
  505. void RecordTrainingDataCollectionEvent(SegmentId segment_id,
  506. TrainingDataCollectionEvent event) {
  507. base::UmaHistogramEnumeration(
  508. "SegmentationPlatform.TrainingDataCollectionEvents." +
  509. SegmentIdToHistogramVariant(segment_id),
  510. event);
  511. }
  512. } // namespace segmentation_platform::stats