chromium/chromeos/components/quick_answers/utils/quick_answers_metrics.cc

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chromeos/components/quick_answers/utils/quick_answers_metrics.h"

#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "components/language/core/browser/language_usage_metrics.h"

namespace quick_answers {

namespace {

const char kQuickAnswerActiveImpression[] = "QuickAnswers.ActiveImpression";
const char kQuickAnswerClick[] = "QuickAnswers.Click";
const char kQuickAnswerResult[] = "QuickAnswers.Result";
const char kQuickAnswerIntent[] = "QuickAnswers.Intent";
const char kQuickAnswerLoadingStatus[] = "QuickAnswers.Loading.Status";
const char kQuickAnswerLoadingDuration[] = "QuickAnswers.Loading.Duration";
const char kQuickAnswerSelectedContentLength[] =
    "QuickAnswers.SelectedContent.Length";
const char kQuickAnswersRequestTextLength[] = "QuickAnswers.RequestTextLength";
const char kQuickAnswersTtsEngineEvent[] =
    "QuickAnswers.TextToSpeech.EngineEvent";
const char kQuickAnswersDictionaryIntentSource[] =
    "QuickAnswers.DictionaryIntent.Source";
const char kQuickAnswersDictionaryIntentLanguage[] =
    "QuickAnswers.DictionaryIntent.Language";
const char kQuickAnswersNetworkError[] = "QuickAnswers.NetworkError.IntentType";
const char kQuickAnswersNetworkResponseCode[] =
    "QuickAnswers.NetworkError.ResponseCode";
const char kQuickAnswerFeatureEnabled[] = "QuickAnswers.FeatureEnabled";

const char kDurationSuffix[] = ".Duration";
const char kDefinitionSuffix[] = ".Definition";
const char kTranslationSuffix[] = ".Translation";
const char kUnitConversionSuffix[] = ".UnitConversion";

std::string ResultTypeToString(ResultType result_type) {
  switch (result_type) {
    case ResultType::kNoResult:
      return "NoResult";
    case ResultType::kDefinitionResult:
      return "Definition";
    case ResultType::kTranslationResult:
      return "Translation";
    case ResultType::kUnitConversionResult:
      return "UnitConversion";
    default:
      NOTREACHED_IN_MIGRATION() << "Invalid ResultType.";
      return ".Unknown";
  }
}

void RecordTypeAndDuration(const std::string& prefix,
                           ResultType result_type,
                           const base::TimeDelta duration,
                           bool is_medium_bucketization) {
  // Record by result type.
  base::UmaHistogramSparse(prefix, static_cast<int>(result_type));

  const std::string duration_histogram = prefix + kDurationSuffix;
  const std::string result_type_histogram_name =
      base::StringPrintf("%s.%s", duration_histogram.c_str(),
                         ResultTypeToString(result_type).c_str());
  // Record sliced by duration and result type.
  if (is_medium_bucketization) {
    base::UmaHistogramMediumTimes(duration_histogram, duration);
    base::UmaHistogramMediumTimes(result_type_histogram_name.c_str(), duration);
  } else {
    base::UmaHistogramTimes(duration_histogram, duration);
    base::UmaHistogramTimes(result_type_histogram_name.c_str(), duration);
  }
}

}  // namespace

void RecordResult(ResultType result_type, const base::TimeDelta duration) {
  RecordTypeAndDuration(kQuickAnswerResult, result_type, duration,
                        /*is_medium_bucketization=*/false);
}

void RecordLoadingStatus(LoadStatus status, const base::TimeDelta duration) {
  base::UmaHistogramEnumeration(kQuickAnswerLoadingStatus, status);
  base::UmaHistogramTimes(kQuickAnswerLoadingDuration, duration);
}

void RecordClick(ResultType result_type, const base::TimeDelta duration) {
  RecordTypeAndDuration(kQuickAnswerClick, result_type, duration,
                        /*is_medium_bucketization=*/true);
}

void RecordSelectedTextLength(int length) {
  base::UmaHistogramCounts1000(kQuickAnswerSelectedContentLength, length);
}

void RecordRequestTextLength(IntentType intent_type, int length) {
  std::string histogram_name = kQuickAnswersRequestTextLength;
  switch (intent_type) {
    case IntentType::kDictionary:
      histogram_name += kDefinitionSuffix;
      break;
    case IntentType::kTranslation:
      histogram_name += kTranslationSuffix;
      break;
    case IntentType::kUnit:
      histogram_name += kUnitConversionSuffix;
      break;
    case IntentType::kUnknown:
      return;
  }

  base::UmaHistogramCounts1000(histogram_name, length);
}

void RecordActiveImpression(ResultType result_type,
                            const base::TimeDelta duration) {
  RecordTypeAndDuration(kQuickAnswerActiveImpression, result_type, duration,
                        /*is_medium_bucketization=*/true);
}

void RecordIntentType(IntentType intent_type) {
  base::UmaHistogramEnumeration(kQuickAnswerIntent, intent_type);
}

void RecordNetworkError(IntentType intent_type, int response_code) {
  base::UmaHistogramEnumeration(kQuickAnswersNetworkError, intent_type);

  std::string histogram_name = kQuickAnswersNetworkResponseCode;
  switch (intent_type) {
    case IntentType::kDictionary:
      histogram_name += kDefinitionSuffix;
      break;
    case IntentType::kTranslation:
      histogram_name += kTranslationSuffix;
      break;
    case IntentType::kUnit:
      histogram_name += kUnitConversionSuffix;
      break;
    case IntentType::kUnknown:
      return;
  }

  base::UmaHistogramSparse(histogram_name, response_code);
}

void RecordTtsEngineEvent(TtsEngineEvent event) {
  base::UmaHistogramEnumeration(kQuickAnswersTtsEngineEvent, event);
}

void RecordDictionaryIntentSource(DictionaryIntentSource source) {
  base::UmaHistogramEnumeration(kQuickAnswersDictionaryIntentSource, source);
}

void RecordDictionaryIntentLanguage(const std::string& language) {
  base::UmaHistogramSparse(
      kQuickAnswersDictionaryIntentLanguage,
      language::LanguageUsageMetrics::ToLanguageCodeHash(language));
}

void RecordFeatureEnabled(bool enabled) {
  base::UmaHistogramBoolean(kQuickAnswerFeatureEnabled, enabled);
}

}  // namespace quick_answers