blob: 8f519f926b63ee0e5c734960e4cb65ea61a635ac [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/segmentation_platform/internal/stats.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "components/segmentation_platform/internal/post_processor/post_processor.h"
#include "components/segmentation_platform/public/constants.h"
#include "components/segmentation_platform/public/proto/model_metadata.pb.h"
#include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
#include "components/segmentation_platform/public/proto/types.pb.h"
namespace segmentation_platform::stats {
namespace {
// Keep in sync with AdaptiveToolbarButtonVariant in enums.xml.
enum class AdaptiveToolbarButtonVariant {
kUnknown = 0,
kNone = 1,
kNewTab = 2,
kShare = 3,
kVoice = 4,
kMaxValue = kVoice,
};
// It should only used for legacy models without descriptors of return type in
// the metadata.
proto::SegmentationModelMetadata::OutputDescription
GetOptimizationTargetOutputDescription(SegmentId segment_id) {
switch (segment_id) {
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_DUMMY:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_START_ANDROID:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_QUERY_TILES:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_CHROME_LOW_USER_ENGAGEMENT:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_FEED_USER:
case SegmentId::OPTIMIZATION_TARGET_CONTEXTUAL_PAGE_ACTION_PRICE_TRACKING:
case SegmentId::OPTIMIZATION_TARGET_WEB_APP_INSTALLATION_PROMO:
return proto::SegmentationModelMetadata::RETURN_TYPE_PROBABILITY;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SEARCH_USER:
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_TABLET_PRODUCTIVITY_USER:
return proto::SegmentationModelMetadata::RETURN_TYPE_MULTISEGMENT;
default:
return proto::SegmentationModelMetadata::UNKNOWN_RETURN_TYPE;
}
}
AdaptiveToolbarButtonVariant OptimizationTargetToAdaptiveToolbarButtonVariant(
SegmentId segment_id) {
switch (segment_id) {
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
return AdaptiveToolbarButtonVariant::kNewTab;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
return AdaptiveToolbarButtonVariant::kShare;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
return AdaptiveToolbarButtonVariant::kVoice;
case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
return AdaptiveToolbarButtonVariant::kNone;
default:
NOTREACHED();
return AdaptiveToolbarButtonVariant::kUnknown;
}
}
BooleanSegmentSwitch GetBooleanSegmentSwitch(SegmentId new_selection,
SegmentId previous_selection) {
if (new_selection != SegmentId::OPTIMIZATION_TARGET_UNKNOWN &&
previous_selection == SegmentId::OPTIMIZATION_TARGET_UNKNOWN) {
return BooleanSegmentSwitch::kNoneToEnabled;
} else if (new_selection == SegmentId::OPTIMIZATION_TARGET_UNKNOWN &&
previous_selection != SegmentId::OPTIMIZATION_TARGET_UNKNOWN) {
return BooleanSegmentSwitch::kEnabledToNone;
}
return BooleanSegmentSwitch::kUnknown;
}
AdaptiveToolbarSegmentSwitch GetAdaptiveToolbarSegmentSwitch(
SegmentId new_selection,
SegmentId previous_selection) {
switch (previous_selection) {
case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
switch (new_selection) {
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
return AdaptiveToolbarSegmentSwitch::kNoneToNewTab;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
return AdaptiveToolbarSegmentSwitch::kNoneToShare;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
return AdaptiveToolbarSegmentSwitch::kNoneToVoice;
default:
NOTREACHED();
return AdaptiveToolbarSegmentSwitch::kUnknown;
}
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
switch (new_selection) {
case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
return AdaptiveToolbarSegmentSwitch::kNewTabToNone;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
return AdaptiveToolbarSegmentSwitch::kNewTabToShare;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
return AdaptiveToolbarSegmentSwitch::kNewTabToVoice;
default:
NOTREACHED();
return AdaptiveToolbarSegmentSwitch::kUnknown;
}
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
switch (new_selection) {
case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
return AdaptiveToolbarSegmentSwitch::kShareToNone;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
return AdaptiveToolbarSegmentSwitch::kShareToNewTab;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
return AdaptiveToolbarSegmentSwitch::kShareToVoice;
default:
NOTREACHED();
return AdaptiveToolbarSegmentSwitch::kUnknown;
}
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_VOICE:
switch (new_selection) {
case SegmentId::OPTIMIZATION_TARGET_UNKNOWN:
return AdaptiveToolbarSegmentSwitch::kVoiceToNone;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
return AdaptiveToolbarSegmentSwitch::kVoiceToNewTab;
case SegmentId::OPTIMIZATION_TARGET_SEGMENTATION_SHARE:
return AdaptiveToolbarSegmentSwitch::kVoiceToShare;
default:
NOTREACHED();
return AdaptiveToolbarSegmentSwitch::kUnknown;
}
default:
NOTREACHED();
return AdaptiveToolbarSegmentSwitch::kUnknown;
}
}
// Should map to ModelExecutionStatus variant string in
// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
absl::optional<base::StringPiece> ModelExecutionStatusToHistogramVariant(
ModelExecutionStatus status) {
switch (status) {
case ModelExecutionStatus::kSuccess:
return "Success";
case ModelExecutionStatus::kExecutionError:
return "ExecutionError";
// Only record duration histograms when tflite model is executed. These
// cases mean the execution was skipped.
case ModelExecutionStatus::kSkippedInvalidMetadata:
case ModelExecutionStatus::kSkippedModelNotReady:
case ModelExecutionStatus::kSkippedHasFreshResults:
case ModelExecutionStatus::kSkippedNotEnoughSignals:
case ModelExecutionStatus::kSkippedResultNotExpired:
case ModelExecutionStatus::kFailedToSaveResultAfterSuccess:
return absl::nullopt;
}
}
// Should map to SignalType variant string in
// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
std::string SignalTypeToHistogramVariant(proto::SignalType signal_type) {
switch (signal_type) {
case proto::SignalType::USER_ACTION:
return "UserAction";
case proto::SignalType::HISTOGRAM_ENUM:
return "HistogramEnum";
case proto::SignalType::HISTOGRAM_VALUE:
return "HistogramValue";
default:
NOTREACHED();
return "Unknown";
}
}
float ZeroValueFraction(const std::vector<float>& tensor) {
if (tensor.size() == 0)
return 0;
size_t zero_values = 0;
for (float feature : tensor) {
if (feature == 0)
++zero_values;
}
return static_cast<float>(zero_values) / static_cast<float>(tensor.size());
}
} // namespace
void RecordModelUpdateTimeDifference(SegmentId segment_id,
int64_t model_update_time) {
// |model_update_time| might be empty for data persisted before M101.
if (model_update_time) {
base::Time model_updated_time = base::Time::FromDeltaSinceWindowsEpoch(
base::Seconds(model_update_time));
base::UmaHistogramCounts1000(
"SegmentationPlatform.Init.ModelUpdatedTimeDifferenceInDays." +
SegmentIdToHistogramVariant(segment_id),
(base::Time::Now() - model_updated_time).InDays());
}
}
void RecordSegmentSelectionComputed(
const Config& config,
SegmentId new_selection,
absl::optional<SegmentId> previous_selection) {
// Special case adaptive toolbar since it already has histograms being
// recorded and updating names will affect current work.
if (config.segmentation_key == kAdaptiveToolbarSegmentationKey) {
base::UmaHistogramEnumeration(
"SegmentationPlatform.AdaptiveToolbar.SegmentSelection.Computed",
OptimizationTargetToAdaptiveToolbarButtonVariant(new_selection));
}
std::string computed_hist =
base::StrCat({"SegmentationPlatform.", config.segmentation_uma_name,
".SegmentSelection.Computed2"});
base::UmaHistogramSparse(computed_hist, new_selection);
SegmentId prev_segment = previous_selection.has_value()
? previous_selection.value()
: SegmentId::OPTIMIZATION_TARGET_UNKNOWN;
if (prev_segment == new_selection || config.on_demand_execution)
return;
std::string switched_hist =
base::StrCat({"SegmentationPlatform.", config.segmentation_uma_name,
".SegmentSwitched"});
if (config.segmentation_key == kAdaptiveToolbarSegmentationKey) {
base::UmaHistogramEnumeration(
switched_hist,
GetAdaptiveToolbarSegmentSwitch(new_selection, prev_segment));
} else if (config.is_boolean_segment) {
base::UmaHistogramEnumeration(
switched_hist, GetBooleanSegmentSwitch(new_selection, prev_segment));
}
// Do not record switched histogram for all keys by default, the client needs
// to write custom logic for other kinds of segments.
}
void RecordClassificationResultComputed(
const Config& config,
const proto::PredictionResult& new_result) {
PostProcessor post_processor;
int new_result_top_label = post_processor.GetIndexOfTopLabel(new_result);
std::string computed_hist =
base::StrCat({"SegmentationPlatform.", config.segmentation_uma_name,
".PostProcessing.TopLabel.Computed"});
base::UmaHistogramSparse(computed_hist, new_result_top_label);
}
void RecordClassificationResultUpdated(
const Config& config,
const absl::optional<proto::PredictionResult>& old_result,
const proto::PredictionResult& new_result) {
if (config.on_demand_execution) {
return;
}
PostProcessor post_processor;
int new_result_top_label = post_processor.GetIndexOfTopLabel(new_result);
int old_result_top_label =
old_result.has_value()
? post_processor.GetIndexOfTopLabel(old_result.value())
: -2;
if (old_result_top_label == new_result_top_label) {
return;
}
std::string switched_hist =
base::StrCat({"SegmentationPlatform.", config.segmentation_uma_name,
".PostProcessing.TopLabel.Switched"});
// There is no easy way to record this metric for label switch. So we encode
// it as follows: Multiply the index value of the old value by 100 and add the
// new index value. Note, there might be negative integers, but regardless
// this will generate a unique value for each type of label switch.
// For example, for a 3-label case, any transition will look like
// none -> label 0 : -200
// none -> label 1 : -199
// none -> label 2 : -198
// label 0 -> none : -2
// label 0 -> label 1 : 1
// label 0 -> label 2 : 2
// label 1 -> none : 98
// label 1 -> label 0 : 100
// label 1 -> label 2 : 102
// label 2 -> none : 198
// label 2 -> label 0 : 200
// label 2 -> label 1 : 201
int switch_value = old_result_top_label * 100 + new_result_top_label;
base::UmaHistogramSparse(switched_hist, switch_value);
}
void RecordMaintenanceCleanupSignalSuccessCount(size_t count) {
UMA_HISTOGRAM_COUNTS_1000(
"SegmentationPlatform.Maintenance.CleanupSignalSuccessCount", count);
}
void RecordMaintenanceCompactionResult(proto::SignalType signal_type,
bool success) {
base::UmaHistogramBoolean(
"SegmentationPlatform.Maintenance.CompactionResult." +
SignalTypeToHistogramVariant(signal_type),
success);
}
void RecordMaintenanceSignalIdentifierCount(size_t count) {
UMA_HISTOGRAM_COUNTS_1000(
"SegmentationPlatform.Maintenance.SignalIdentifierCount", count);
}
void RecordModelDeliveryHasMetadata(SegmentId segment_id, bool has_metadata) {
base::UmaHistogramBoolean("SegmentationPlatform.ModelDelivery.HasMetadata." +
SegmentIdToHistogramVariant(segment_id),
has_metadata);
}
void RecordModelDeliveryMetadataFeatureCount(SegmentId segment_id,
size_t count) {
base::UmaHistogramCounts1000(
"SegmentationPlatform.ModelDelivery.Metadata.FeatureCount." +
SegmentIdToHistogramVariant(segment_id),
count);
}
void RecordModelDeliveryMetadataValidation(
SegmentId segment_id,
bool processed,
metadata_utils::ValidationResult validation_result) {
// Should map to ValidationPhase variant string in
// //tools/metrics/histograms/metadata/segmentation_platform/histograms.xml.
std::string validation_phase = processed ? "Processed" : "Incoming";
base::UmaHistogramEnumeration(
"SegmentationPlatform.ModelDelivery.Metadata.Validation." +
validation_phase + "." + SegmentIdToHistogramVariant(segment_id),
validation_result);
}
void RecordModelDeliveryReceived(SegmentId segment_id) {
base::UmaHistogramSparse("SegmentationPlatform.ModelDelivery.Received",
segment_id);
}
void RecordModelDeliverySaveResult(SegmentId segment_id, bool success) {
base::UmaHistogramBoolean("SegmentationPlatform.ModelDelivery.SaveResult." +
SegmentIdToHistogramVariant(segment_id),
success);
}
void RecordModelDeliverySegmentIdMatches(SegmentId segment_id, bool matches) {
base::UmaHistogramBoolean(
"SegmentationPlatform.ModelDelivery.SegmentIdMatches." +
SegmentIdToHistogramVariant(segment_id),
matches);
}
void RecordModelExecutionDurationFeatureProcessing(SegmentId segment_id,
base::TimeDelta duration) {
base::UmaHistogramTimes(
"SegmentationPlatform.ModelExecution.Duration.FeatureProcessing." +
SegmentIdToHistogramVariant(segment_id),
duration);
}
void RecordModelExecutionDurationModel(SegmentId segment_id,
bool success,
base::TimeDelta duration) {
ModelExecutionStatus status = success ? ModelExecutionStatus::kSuccess
: ModelExecutionStatus::kExecutionError;
absl::optional<base::StringPiece> status_variant =
ModelExecutionStatusToHistogramVariant(status);
if (!status_variant)
return;
base::UmaHistogramTimes(
base::StrCat({"SegmentationPlatform.ModelExecution.Duration.Model.",
SegmentIdToHistogramVariant(segment_id), ".",
*status_variant}),
duration);
}
void RecordModelExecutionDurationTotal(SegmentId segment_id,
ModelExecutionStatus status,
base::TimeDelta duration) {
absl::optional<base::StringPiece> status_variant =
ModelExecutionStatusToHistogramVariant(status);
if (!status_variant)
return;
base::UmaHistogramTimes(
base::StrCat({"SegmentationPlatform.ModelExecution.Duration.Total.",
SegmentIdToHistogramVariant(segment_id), ".",
*status_variant}),
duration);
}
void RecordClassificationRequestTotalDuration(
const std::string& segmentation_key,
base::TimeDelta duration) {
std::string histogram_name =
base::StrCat({"SegmentationPlatform.ClassificationRequest.TotalDuration.",
SegmentationKeyToUmaName(segmentation_key)});
base::UmaHistogramTimes(histogram_name, duration);
}
void RecordOnDemandSegmentSelectionDuration(
const std::string& segmentation_key,
const SegmentSelectionResult& result,
base::TimeDelta duration) {
std::string histogram_prefix =
base::StrCat({"SegmentationPlatform.SegmentSelectionOnDemand.Duration.",
SegmentationKeyToUmaName(segmentation_key), "."});
base::UmaHistogramTimes(base::StrCat({histogram_prefix, "Any"}), duration);
std::string histogram_name =
base::StrCat({histogram_prefix,
result.segment.has_value()
? SegmentIdToHistogramVariant(result.segment.value())
: "None"});
base::UmaHistogramTimes(histogram_name, duration);
}
void RecordModelExecutionResult(
SegmentId segment_id,
float result,
proto::SegmentationModelMetadata::OutputDescription return_type) {
if (return_type == proto::SegmentationModelMetadata::UNKNOWN_RETURN_TYPE) {
return_type = GetOptimizationTargetOutputDescription(segment_id);
}
if (return_type ==
proto::SegmentationModelMetadata::RETURN_TYPE_MULTISEGMENT) {
// This type of model return score between 0 and 100.
base::UmaHistogramPercentage("SegmentationPlatform.ModelExecution.Result." +
SegmentIdToHistogramVariant(segment_id),
base::ClampRound(result));
return;
} else if (return_type ==
proto::SegmentationModelMetadata::RETURN_TYPE_INTEGER) {
// This type of model return an unbound float score.
base::UmaHistogramPercentage("SegmentationPlatform.ModelExecution.Result." +
SegmentIdToHistogramVariant(segment_id),
static_cast<int>(result));
return;
}
// All other models type return score between 0 and 1.
base::UmaHistogramPercentage("SegmentationPlatform.ModelExecution.Result." +
SegmentIdToHistogramVariant(segment_id),
result * 100);
}
void RecordModelExecutionResult(SegmentId segment_id,
const ModelProvider::Response& result,
proto::OutputConfig output_config) {
// Only for binary and multi-class classifier, we treat the score as a
// probability score and multiply by 100. For others, it's kept as is.
bool is_probability_score = false;
switch (output_config.predictor().PredictorType_case()) {
case proto::Predictor::kBinaryClassifier:
[[fallthrough]];
case proto::Predictor::kMultiClassClassifier:
is_probability_score = true;
break;
case proto::Predictor::kBinnedClassifier:
[[fallthrough]];
case proto::Predictor::kRegressor:
is_probability_score = false;
break;
default:
NOTREACHED();
}
for (size_t i = 0; i < result.size(); i++) {
std::string histogram_name = "SegmentationPlatform.ModelExecution.Result." +
base::NumberToString(i) + "." +
SegmentIdToHistogramVariant(segment_id);
int scaled_model_score = is_probability_score ? result[i] * 100 : result[i];
base::UmaHistogramPercentage(histogram_name, scaled_model_score);
}
}
void RecordModelExecutionSaveResult(SegmentId segment_id, bool success) {
base::UmaHistogramBoolean("SegmentationPlatform.ModelExecution.SaveResult." +
SegmentIdToHistogramVariant(segment_id),
success);
}
void RecordModelExecutionStatus(SegmentId segment_id,
bool default_provider,
ModelExecutionStatus status) {
if (!default_provider) {
base::UmaHistogramEnumeration(
"SegmentationPlatform.ModelExecution.Status." +
SegmentIdToHistogramVariant(segment_id),
status);
} else {
base::UmaHistogramEnumeration(
"SegmentationPlatform.ModelExecution.DefaultProvider.Status." +
SegmentIdToHistogramVariant(segment_id),
status);
}
}
void RecordModelExecutionZeroValuePercent(SegmentId segment_id,
const std::vector<float>& tensor) {
base::UmaHistogramPercentage(
"SegmentationPlatform.ModelExecution.ZeroValuePercent." +
SegmentIdToHistogramVariant(segment_id),
ZeroValueFraction(tensor) * 100);
}
void RecordSignalDatabaseGetSamplesDatabaseEntryCount(size_t count) {
UMA_HISTOGRAM_COUNTS_1000(
"SegmentationPlatform.SignalDatabase.GetSamples.DatabaseEntryCount",
count);
}
void RecordSignalDatabaseGetSamplesResult(bool success) {
UMA_HISTOGRAM_BOOLEAN("SegmentationPlatform.SignalDatabase.GetSamples.Result",
success);
}
void RecordSignalDatabaseGetSamplesSampleCount(size_t count) {
UMA_HISTOGRAM_COUNTS_10000(
"SegmentationPlatform.SignalDatabase.GetSamples.SampleCount", count);
}
void RecordSignalsListeningCount(
const std::set<uint64_t>& user_actions,
const std::set<std::pair<std::string, proto::SignalType>>& histograms) {
uint64_t user_action_count = user_actions.size();
uint64_t histogram_enum_count = 0;
uint64_t histogram_value_count = 0;
for (auto& s : histograms) {
if (s.second == proto::SignalType::HISTOGRAM_ENUM)
++histogram_enum_count;
if (s.second == proto::SignalType::HISTOGRAM_VALUE)
++histogram_value_count;
}
base::UmaHistogramCounts1000(
"SegmentationPlatform.Signals.ListeningCount." +
SignalTypeToHistogramVariant(proto::SignalType::USER_ACTION),
user_action_count);
base::UmaHistogramCounts1000(
"SegmentationPlatform.Signals.ListeningCount." +
SignalTypeToHistogramVariant(proto::SignalType::HISTOGRAM_ENUM),
histogram_enum_count);
base::UmaHistogramCounts1000(
"SegmentationPlatform.Signals.ListeningCount." +
SignalTypeToHistogramVariant(proto::SignalType::HISTOGRAM_VALUE),
histogram_value_count);
}
void RecordSegmentSelectionFailure(const Config& config,
SegmentationSelectionFailureReason reason) {
base::UmaHistogramEnumeration(
base::StrCat({"SegmentationPlatform.SelectionFailedReason.",
config.segmentation_uma_name}),
reason);
}
void RecordSegmentSelectionFailure(const std::string& segmentation_key,
SegmentationSelectionFailureReason reason) {
base::UmaHistogramEnumeration(
base::StrCat({"SegmentationPlatform.SelectionFailedReason.",
SegmentationKeyToUmaName(segmentation_key)}),
reason);
}
std::string FeatureProcessingErrorToString(FeatureProcessingError error) {
switch (error) {
case FeatureProcessingError::kUkmEngineDisabled:
return "UkmEngineDisabled";
case FeatureProcessingError::kUmaValidationError:
return "UmaValidationError";
case FeatureProcessingError::kSqlValidationError:
return "SqlValidationError";
case FeatureProcessingError::kCustomInputError:
return "CustomInputError";
case FeatureProcessingError::kSqlBindValuesError:
return "SqlBindValuesError";
case FeatureProcessingError::kSqlQueryRunError:
return "SqlQueryRunError";
case FeatureProcessingError::kResultTensorError:
return "ResultTensorError";
default:
return "Other";
}
}
void RecordFeatureProcessingError(SegmentId segment_id,
FeatureProcessingError error) {
base::UmaHistogramEnumeration(
"SegmentationPlatform.FeatureProcessing.Error." +
SegmentIdToHistogramVariant(segment_id),
error);
}
void RecordModelAvailability(SegmentId segment_id,
SegmentationModelAvailability availability) {
base::UmaHistogramEnumeration("SegmentationPlatform.ModelAvailability." +
SegmentIdToHistogramVariant(segment_id),
availability);
}
void RecordTooManyInputTensors(int tensor_size) {
UMA_HISTOGRAM_COUNTS_100(
"SegmentationPlatform.StructuredMetrics.TooManyTensors.Count",
tensor_size);
}
void RecordTrainingDataCollectionEvent(SegmentId segment_id,
TrainingDataCollectionEvent event) {
base::UmaHistogramEnumeration(
"SegmentationPlatform.TrainingDataCollectionEvents." +
SegmentIdToHistogramVariant(segment_id),
event);
}
// This conversion exists because segment selector uses the result state
// differently. TODO(ritikagup): Remove this conversion when selector is
// deleted.
SegmentationSelectionFailureReason GetSuccessOrFailureReason(
SegmentResultProvider::ResultState result_state) {
switch (result_state) {
case SegmentResultProvider::ResultState::kUnknown:
NOTREACHED();
return SegmentationSelectionFailureReason::kMaxValue;
case SegmentResultProvider::ResultState::kSuccessFromDatabase:
return SegmentationSelectionFailureReason::kScoreUsedFromDatabase;
case SegmentResultProvider::ResultState::kDefaultModelScoreUsed:
return SegmentationSelectionFailureReason::kScoreComputedFromDefaultModel;
case SegmentResultProvider::ResultState::kTfliteModelScoreUsed:
return SegmentationSelectionFailureReason::kScoreComputedFromTfliteModel;
case SegmentResultProvider::ResultState::kDatabaseScoreNotReady:
return SegmentationSelectionFailureReason::kAtLeastOneSegmentNotReady;
case SegmentResultProvider::ResultState::kSegmentNotAvailable:
return SegmentationSelectionFailureReason::kAtLeastOneSegmentNotAvailable;
case SegmentResultProvider::ResultState::kSignalsNotCollected:
return SegmentationSelectionFailureReason::
kAtLeastOneSegmentSignalsNotCollected;
case SegmentResultProvider::ResultState::kDefaultModelMetadataMissing:
return SegmentationSelectionFailureReason::
kAtLeastOneSegmentDefaultMissingMetadata;
case SegmentResultProvider::ResultState::kDefaultModelSignalNotCollected:
return SegmentationSelectionFailureReason::
kAtLeastOneSegmentDefaultSignalNotCollected;
case SegmentResultProvider::ResultState::kDefaultModelExecutionFailed:
return SegmentationSelectionFailureReason::
kAtLeastOneSegmentDefaultExecFailed;
case SegmentResultProvider::ResultState::kTfliteModelExecutionFailed:
return SegmentationSelectionFailureReason::
kAtLeastOneSegmentTfliteExecFailed;
}
}
} // namespace segmentation_platform::stats