| Index: components/feature_engagement_tracker/internal/stats.cc
|
| diff --git a/components/feature_engagement_tracker/internal/stats.cc b/components/feature_engagement_tracker/internal/stats.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a3e3e2ce0ab3e874cbfa161a29f5ab1d7f017591
|
| --- /dev/null
|
| +++ b/components/feature_engagement_tracker/internal/stats.cc
|
| @@ -0,0 +1,192 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "components/feature_engagement_tracker/internal/stats.h"
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/metrics/histogram_functions.h"
|
| +#include "base/metrics/histogram_macros.h"
|
| +#include "base/metrics/user_metrics.h"
|
| +#include "components/feature_engagement_tracker/public/feature_list.h"
|
| +
|
| +namespace feature_engagement_tracker {
|
| +namespace stats {
|
| +namespace {
|
| +
|
| +// Histogram suffixes for database metrics, must match the ones in
|
| +// histograms.xml.
|
| +const char kEventStoreSuffix[] = "EventStore";
|
| +const char kAvailabilityStoreSuffix[] = "AvailabilityStore";
|
| +
|
| +// Helper function to log a TriggerHelpUIResult.
|
| +void LogTriggerHelpUIResult(const std::string& name,
|
| + TriggerHelpUIResult result) {
|
| + // Must not use histograms macros here because we pass in the histogram name.
|
| + base::UmaHistogramEnumeration(name, result, TriggerHelpUIResult::COUNT);
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +std::string ToDbHistogramSuffix(StoreType type) {
|
| + switch (type) {
|
| + case StoreType::EVENTS_STORE:
|
| + return std::string(kEventStoreSuffix);
|
| + case StoreType::AVAILABILITY_STORE:
|
| + return std::string(kAvailabilityStoreSuffix);
|
| + default:
|
| + NOTREACHED();
|
| + return std::string();
|
| + }
|
| +}
|
| +
|
| +void RecordNotifyEvent(const std::string& event_name,
|
| + const Configuration* config,
|
| + bool is_model_ready) {
|
| + DCHECK(!event_name.empty());
|
| + DCHECK(config);
|
| +
|
| + // Find which feature this event belongs to.
|
| + const Configuration::ConfigMap& features = config->GetRegisteredFeatures();
|
| + std::string feature_name;
|
| + for (const auto& element : features) {
|
| + const base::Feature* feature = element.first;
|
| + const FeatureConfig& feature_config = element.second;
|
| +
|
| + // Track used event separately.
|
| + if (feature_config.used.name == event_name) {
|
| + feature_name = feature->name;
|
| + DCHECK(!feature_name.empty());
|
| + std::string used_event_action = "InProductHelp.NotifyUsedEvent.";
|
| + used_event_action.append(feature_name);
|
| + base::RecordComputedAction(used_event_action);
|
| + break;
|
| + }
|
| +
|
| + // Find if the |event_name| matches any configuration.
|
| + for (const auto& event : feature_config.event_configs) {
|
| + if (event.name == event_name) {
|
| + feature_name = feature->name;
|
| + break;
|
| + }
|
| + }
|
| + if (feature_config.trigger.name == event_name) {
|
| + feature_name = feature->name;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + // Do nothing if no events in the configuration matches the |event_name|.
|
| + if (feature_name.empty())
|
| + return;
|
| +
|
| + std::string event_action = "InProductHelp.NotifyEvent.";
|
| + event_action.append(feature_name);
|
| + base::RecordComputedAction(event_action);
|
| +
|
| + std::string event_histogram = "InProductHelp.NotifyEventReadyState.";
|
| + event_histogram.append(feature_name);
|
| + base::UmaHistogramBoolean(event_histogram, is_model_ready);
|
| +}
|
| +
|
| +void RecordShouldTriggerHelpUI(const base::Feature& feature,
|
| + const ConditionValidator::Result& result) {
|
| + // Records the user action.
|
| + std::string name = "InProductHelp.ShouldTriggerHelpUI.";
|
| + name.append(feature.name);
|
| + base::RecordComputedAction(name);
|
| +
|
| + // Total count histogram, used to compute the percentage of each failure type.
|
| + if (result.NoErrors()) {
|
| + LogTriggerHelpUIResult(name, TriggerHelpUIResult::SUCCESS);
|
| + } else {
|
| + LogTriggerHelpUIResult(name, TriggerHelpUIResult::FAILURE);
|
| + }
|
| +
|
| + // Histogram about the failure reasons.
|
| + if (!result.event_model_ready_ok)
|
| + LogTriggerHelpUIResult(name, TriggerHelpUIResult::FAILURE_MODEL_NOT_READY);
|
| + if (!result.currently_showing_ok) {
|
| + LogTriggerHelpUIResult(name,
|
| + TriggerHelpUIResult::FAILURE_CURRENTLY_SHOWING);
|
| + }
|
| + if (!result.feature_enabled_ok) {
|
| + LogTriggerHelpUIResult(name, TriggerHelpUIResult::FAILURE_FEATURE_DISABLED);
|
| + }
|
| + if (!result.config_ok) {
|
| + LogTriggerHelpUIResult(name, TriggerHelpUIResult::FAILURE_CONFIG_INVALID);
|
| + }
|
| + if (!result.used_ok) {
|
| + LogTriggerHelpUIResult(
|
| + name, TriggerHelpUIResult::FAILURE_USED_PRECONDITION_UNMET);
|
| + }
|
| + if (!result.trigger_ok) {
|
| + LogTriggerHelpUIResult(
|
| + name, TriggerHelpUIResult::FAILURE_TRIGGER_PRECONDITION_UNMET);
|
| + }
|
| + if (!result.preconditions_ok) {
|
| + LogTriggerHelpUIResult(
|
| + name, TriggerHelpUIResult::FAILURE_OTHER_PRECONDITION_UNMET);
|
| + }
|
| + if (!result.session_rate_ok) {
|
| + LogTriggerHelpUIResult(name, TriggerHelpUIResult::FAILURE_SESSION_RATE);
|
| + }
|
| + if (!result.availability_model_ready_ok) {
|
| + LogTriggerHelpUIResult(
|
| + name, TriggerHelpUIResult::FAILURE_AVAILABILITY_MODEL_NOT_READY);
|
| + }
|
| + if (!result.availability_ok) {
|
| + LogTriggerHelpUIResult(
|
| + name, TriggerHelpUIResult::FAILURE_AVAILABILITY_PRECONDITION_UNMET);
|
| + }
|
| +}
|
| +
|
| +void RecordUserDismiss() {
|
| + base::RecordAction(base::UserMetricsAction("InProductHelp.Dismissed"));
|
| +}
|
| +
|
| +void RecordDbUpdate(bool success, StoreType type) {
|
| + std::string histogram_name =
|
| + "InProductHelp.Db.Update." + ToDbHistogramSuffix(type);
|
| + base::UmaHistogramBoolean(histogram_name, success);
|
| +}
|
| +
|
| +void RecordDbInitEvent(bool success, StoreType type) {
|
| + std::string histogram_name =
|
| + "InProductHelp.Db.Init." + ToDbHistogramSuffix(type);
|
| + base::UmaHistogramBoolean(histogram_name, success);
|
| +}
|
| +
|
| +void RecordEventDbLoadEvent(bool success, const std::vector<Event>& events) {
|
| + std::string histogram_name =
|
| + "InProductHelp.Db.Load." + ToDbHistogramSuffix(StoreType::EVENTS_STORE);
|
| + base::UmaHistogramBoolean(histogram_name, success);
|
| + UMA_HISTOGRAM_BOOLEAN("InProductHelp.Db.Load", success);
|
| +
|
| + if (!success)
|
| + return;
|
| +
|
| + // Tracks total number of events records when the database is successfully
|
| + // loaded.
|
| + int event_count = 0;
|
| + for (const auto& event : events)
|
| + event_count += event.events_size();
|
| + UMA_HISTOGRAM_COUNTS_1000("InProductHelp.Db.TotalEvents", event_count);
|
| +}
|
| +
|
| +void RecordAvailabilityDbLoadEvent(bool success) {
|
| + std::string histogram_name =
|
| + "InProductHelp.Db.Load." +
|
| + ToDbHistogramSuffix(StoreType::AVAILABILITY_STORE);
|
| + base::UmaHistogramBoolean(histogram_name, success);
|
| + UMA_HISTOGRAM_BOOLEAN("InProductHelp.Db.Load", success);
|
| +}
|
| +
|
| +void RecordConfigParsingEvent(ConfigParsingEvent event) {
|
| + UMA_HISTOGRAM_ENUMERATION("InProductHelp.Config.ParsingEvent", event,
|
| + ConfigParsingEvent::COUNT);
|
| +}
|
| +
|
| +} // namespace stats
|
| +} // namespace feature_engagement_tracker
|
|
|