1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
|
// 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.
#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_
#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_
#include <list>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "components/segmentation_platform/internal/execution/model_execution_status.h"
#include "components/segmentation_platform/internal/metadata/metadata_utils.h"
#include "components/segmentation_platform/internal/selection/segment_result_provider.h"
#include "components/segmentation_platform/public/config.h"
#include "components/segmentation_platform/public/model_provider.h"
#include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
#include "components/segmentation_platform/public/proto/types.pb.h"
#include "components/segmentation_platform/public/segment_selection_result.h"
namespace segmentation_platform::stats {
using proto::SegmentId;
// Keep in sync with AdaptiveToolbarSegmentSwitch in enums.xml.
// Visible for testing.
enum class AdaptiveToolbarSegmentSwitch {
kUnknown = 0,
kNoneToNewTab = 1,
kNoneToShare = 2,
kNoneToVoice = 3,
kNewTabToNone = 4,
kShareToNone = 5,
kVoiceToNone = 6,
kNewTabToShare = 7,
kNewTabToVoice = 8,
kShareToNewTab = 9,
kShareToVoice = 10,
kVoiceToNewTab = 11,
kVoiceToShare = 12,
kMaxValue = kVoiceToShare,
};
// Keep in sync with SegmentationBooleanSegmentSwitch in enums.xml.
// Visible for testing.
enum class BooleanSegmentSwitch {
kUnknown = 0,
kNoneToEnabled = 1,
kEnabledToNone = 2,
kMaxValue = kEnabledToNone,
};
// Records the time difference between when a new version of model from
// optimization guide is available and when the model is initialized in the
// client.
void RecordModelUpdateTimeDifference(SegmentId segment_id,
int64_t model_update_time);
// Records the result of segment selection whenever segment selection is
// computed.
void RecordSegmentSelectionComputed(
const Config& config,
SegmentId new_selection,
std::optional<SegmentId> previous_selection);
// Records the post processed result whenever computed. This is recorded when
// results are obtained by eithier executing the model or getting a valid score
// from database.
void RecordClassificationResultComputed(
const Config& config,
const proto::PredictionResult& new_result);
// Records from which old value to which new value the topmost label is changing
// to when prefs expired and is updated with new result.
void RecordClassificationResultUpdated(
const Config& config,
const proto::PredictionResult* old_result,
const proto::PredictionResult& new_result);
// Database Maintenance metrics.
// Records the number of unique signal identifiers that were successfully
// cleaned up.
void RecordMaintenanceCleanupSignalSuccessCount(size_t count);
// Records the result for each compaction attempt for a particular signal type.
void RecordMaintenanceCompactionResult(proto::SignalType signal_type,
bool success);
// Records the number of signal identifiers that were found that we should aim
// to clean up.
void RecordMaintenanceSignalIdentifierCount(size_t count);
// Model Delivery metrics.
// Records whether any incoming ML had metadata attached that
// we were able to parse.
void RecordModelDeliveryHasMetadata(SegmentId segment_id, bool has_metadata);
// Records the number of tensor features an updated server or embedded model
// has.
void RecordModelDeliveryMetadataFeatureCount(SegmentId segment_id,
proto::ModelSource model_source,
size_t count);
// Records the result of validating the metadata of an incoming server or
// embedded model. Recorded before and after it has been merged with the already
// stored metadata.
void RecordModelDeliveryMetadataValidation(
SegmentId segment_id,
proto::ModelSource model_source,
bool processed,
metadata_utils::ValidationResult validation_result);
// Record what type of server or embedded model metadata we received .
void RecordModelDeliveryReceived(SegmentId segment_id,
proto::ModelSource model_source);
// Records the result of attempting to save an updated version of the server or
// embedded model metadata.
void RecordModelDeliverySaveResult(SegmentId segment_id,
proto::ModelSource model_source,
bool success);
// Records the result of attempting to delete the previous version of a server
// model metadata.
void RecordModelDeliveryDeleteResult(SegmentId segment_id,
proto::ModelSource model_source,
bool success);
// Records whether the currently stored segment_id matches the incoming
// segment_id for a particular model_source, as these are expected to match.
void RecordModelDeliverySegmentIdMatches(SegmentId segment_id,
proto::ModelSource model_source,
bool matches);
// Model Execution metrics.
// Records the duration of processing a single ML feature. This only takes into
// account the time it takes to process (aggregate) a feature result, not
// fetching it from the database. It also takes into account filtering any
// enum histograms.
void RecordModelExecutionDurationFeatureProcessing(SegmentId segment_id,
base::TimeDelta duration);
// Records the duration of executing an ML model. This only takes into account
// the time it takes to invoke and wait for a result from the underlying ML
// infrastructure from //components/optimization_guide, and not fetching the
// relevant data from the database.
void RecordModelExecutionDurationModel(SegmentId segment_id,
bool success,
base::TimeDelta duration);
// Records the duration of fetching data for, processing, and executing an ML
// model.
void RecordModelExecutionDurationTotal(SegmentId segment_id,
ModelExecutionStatus status,
base::TimeDelta duration);
// Records the total duration for GetClassificationResult API starting from the
// time request arrives in segmentation service until the result has been
// returned. It includes feature processing and model execution as well.
void RecordClassificationRequestTotalDuration(const Config& config,
base::TimeDelta duration);
// Records the total duration of on-demand segment selection which includes
// running all the models associated with the client and computing result.
void RecordOnDemandSegmentSelectionDuration(
const Config& config,
const SegmentSelectionResult& result,
base::TimeDelta duration);
// Records the result value after successfully executing an ML model.
void RecordModelExecutionResult(
SegmentId segment_id,
float result,
proto::SegmentationModelMetadata::OutputDescription return_type);
// Records the raw model score. Records each element of the result tensor as a
// separate histogram identified by its index. For binary and multi-class
// models, the raw score is multiplied by 100 to transform as percent score,
// whereas for binned classifier the result is recorded as is in a percent
// range.
void RecordModelExecutionResult(SegmentId segment_id,
const ModelProvider::Response& result,
proto::OutputConfig output_config);
// Records whether the result value of of executing an ML model was successfully
// saved.
void RecordModelExecutionSaveResult(SegmentId segment_id, bool success);
// Records the final execution status for any ML model execution.
void RecordModelExecutionStatus(SegmentId segment_id,
bool default_provider,
ModelExecutionStatus status);
// Records the percent of features in a tensor that are equal to 0 when the
// segmentation model is executed.
void RecordModelExecutionZeroValuePercent(SegmentId segment_id,
const std::vector<float>& tensor);
// Signal Database metrics.
// Records the number of database entries that were fetched from the database
// during a call to GetSamples. This is not the same as the sample count since
// each database entry can contain multiple samples.
void RecordSignalDatabaseGetSamplesDatabaseEntryCount(size_t count);
// Records the result of fetching data from the database during a call to
// GetSamples.
void RecordSignalDatabaseGetSamplesResult(bool success);
// Records the number of samples that were returned after reading entries from
// the database, during a call to GetSamples. This is not the same as the
// database entry count, since each entry can contain multiple samples.
void RecordSignalDatabaseGetSamplesSampleCount(size_t count);
// Records the result of persisting SegmentInfo changes to disk.
void RecordSegmentInfoDatabaseUpdateEntriesResult(SegmentId segment_id,
bool success);
// Records the number of unique user action and histogram signals that we are
// currently tracking.
void RecordSignalsListeningCount(
const std::set<uint64_t>& user_actions,
const std::set<std::pair<std::string, proto::SignalType>>& histograms);
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. Please keep in sync with
// "SegmentationSelectionFailureReason" in
// //tools/metrics/histograms/enums.xml.
enum class SegmentationSelectionFailureReason {
kDeprecatedPlatformDisabled = 0,
kSelectionAvailableInPrefs = 1,
kServerModelDatabaseScoreNotReady = 2,
kServerModelSignalsNotCollected = 3,
kSelectionTtlNotExpired = 4,
kAtLeastOneModelFailedExecution = 5,
kAtLeastOneModelNeedsMoreSignals = 6,
kAtLeastOneModelWithInvalidMetadata = 7,
kFailedToSaveModelResult = 8,
kInvalidSelectionResultInPrefs = 9,
kDBInitFailure = 10,
kServerModelSegmentInfoNotAvailable = 11,
kDefaultModelSignalsNotCollected = 12,
kDefaultModelExecutionFailed = 13,
kDefaultModelSegmentInfoNotAvailable = 14,
kServerModelExecutionFailed = 15,
kSelectionAvailableInProtoPrefs = 16,
kInvalidSelectionResultInProtoPrefs = 17,
kProtoPrefsUpdateNotRequired = 18,
kProtoPrefsUpdated = 19,
kServerModelDatabaseScoreUsed = 20,
kDefaultModelExecutionScoreUsed = 21,
kServerModelExecutionScoreUsed = 22,
kMultiOutputNotSupported = 23,
kOnDemandModelExecutionFailed = 24,
kClassificationResultFromPrefs = 25,
kClassificationResultNotAvailableInPrefs = 26,
kDefaultModelDatabaseScoreUsed = 27,
kDefaultModelDatabaseScoreNotReady = 28,
kCachedResultUnavailableExecutingOndemand = 29,
kOnDemandExecutionFailedReturningCachedResult = 30,
kMaxValue = kOnDemandExecutionFailedReturningCachedResult,
};
// Records the reason for failure or success to compute a segment selection.
void RecordSegmentSelectionFailure(const Config& config,
SegmentationSelectionFailureReason reason);
// Keep in sync with SegmentationPlatformFeatureProcessingError in
// //tools/metrics/histograms/enums.xml.
enum class FeatureProcessingError {
kUkmEngineDisabled = 0,
kUmaValidationError = 1,
kSqlValidationError = 2,
kCustomInputError = 3,
kSqlBindValuesError = 4,
kSqlQueryRunError = 5,
kResultTensorError = 6,
kSuccess = 7,
kMaxValue = kSuccess,
};
// Return a string display for the given FeatureProcessingError.
std::string FeatureProcessingErrorToString(FeatureProcessingError error);
// Records the type of error encountered during feature processing.
void RecordFeatureProcessingError(SegmentId segment_id,
FeatureProcessingError error);
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. Please keep in sync with
// "SegmentationModelAvailability" in //tools/metrics/histograms/enums.xml.
enum class SegmentationModelAvailability {
kModelHandlerCreated = 0,
kModelAvailable = 1,
kMetadataInvalid = 2,
kNoModelAvailable = 3,
kMaxValue = kNoModelAvailable
};
// Records the availability of segmentation models for each target needed.
void RecordModelAvailability(SegmentId segment_id,
SegmentationModelAvailability availability);
// Records the number of input tensor that's causing a failure to upload
// structured metrics.
void RecordTooManyInputTensors(int tensor_size);
// Analytics events for training data collection. Sync with
// SegmentationPlatformTrainingDataCollectionEvent in enums.xml.
enum class TrainingDataCollectionEvent {
kImmediateCollectionStart = 0,
kImmediateCollectionSuccess = 1,
kModelInfoMissing = 2,
kMetadataValidationFailed = 3,
kGetInputTensorsFailed = 4,
kNotEnoughCollectionTime = 5,
kUkmReportingFailed = 6,
kPartialDataNotAllowed = 7,
kContinousCollectionStart = 8,
kContinousCollectionSuccess = 9,
kCollectAndStoreInputsSuccess = 10,
kObservationTimeReached = 11,
kDelayedTaskPosted = 12,
kImmediateObservationPosted = 13,
kWaitingForNonDelayedTrigger = 14,
kHistogramTriggerHit = 15,
kNoSegmentInfo = 16,
kDisallowedForRecording = 17,
kObservationDisallowed = 18,
kTrainingDataMissing = 19,
kOnDecisionTimeTypeMistmatch = 20,
kDelayTriggerSampled = 21,
kContinousExactPredictionTimeCollectionStart = 22,
kContinousExactPredictionTimeCollectionSuccess = 23,
kMaxValue = kContinousExactPredictionTimeCollectionSuccess
};
std::string TrainingDataCollectionEventToErrorMsg(
TrainingDataCollectionEvent event);
// Records analytics for training data collection.
void RecordTrainingDataCollectionEvent(SegmentId segment_id,
TrainingDataCollectionEvent event);
SegmentationSelectionFailureReason GetSuccessOrFailureReason(
SegmentResultProvider::ResultState result_state);
// Helper to collect UMA metrics and record in a non-blocking thread.
class BackgroundUmaRecorder {
public:
// Delay to collect metrics and record. Set to short time so if Chrome dies we
// don't lose too many metrics.
constexpr static base::TimeDelta kMetricsCollectionDelay = base::Seconds(5);
static BackgroundUmaRecorder& GetInstance();
BackgroundUmaRecorder(const BackgroundUmaRecorder&) = delete;
BackgroundUmaRecorder& operator=(const BackgroundUmaRecorder&) = delete;
// If initialized then records metrics in a worker thread, otherwise records
// metrics in current thread, blocking. Can be called multiple times safely.
void Initialize();
void InitializeForTesting(
scoped_refptr<base::SequencedTaskRunner> bg_task_runner);
// Force flush all samples in current thread.
void FlushSamples();
// Add metrics to UMA.
void AddMetric(base::OnceClosure add_sample);
scoped_refptr<base::SequencedTaskRunner> bg_task_runner_for_testing() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
return bg_task_runner_;
}
private:
friend class base::NoDestructor<BackgroundUmaRecorder>;
BackgroundUmaRecorder();
~BackgroundUmaRecorder();
base::Lock lock_;
std::list<base::OnceClosure> add_samples_ GUARDED_BY(lock_);
bool pending_task_ GUARDED_BY(lock_){false};
scoped_refptr<base::SequencedTaskRunner> bg_task_runner_;
// Protects `bg_task_runner_`. If we need to record metrics from non-main
// thread, do not use this class and record directly.
SEQUENCE_CHECKER(sequence_check_);
base::WeakPtrFactory<BackgroundUmaRecorder> weak_factory_{this};
};
} // namespace segmentation_platform::stats
#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_STATS_H_
|