// Copyright 2017 The Chromium OS 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 "authpolicy/authpolicy_metrics.h"

#include <algorithm>
#include <string>
#include <utility>

#include <base/logging.h>

namespace authpolicy {

namespace {

// Prefix for all metric names.
const char* kMetricNamePrefix = "AuthPolicy.";

std::string MakeFullName(const char* metric_name) {
  return std::string(kMetricNamePrefix) + metric_name;
}

// UMA histogram parameters. The bucket layout is exponential with implicit
// underflow and overflow buckets for [0, min_sample - 1) and [max_sample, inf),
// respectively, counting towards |num_buckets|. See MetricsLibrary::SendToUMA
// and base::Histogram for more details. |enum_value| is a safety parameter to
// make sure that the array index matches the enum value.
struct HistogramParams {
  int enum_value;
  const char* metric_name;
  int min_sample;
  int max_sample;
  int num_buckets;
};

// |max_sample| is the max time in milliseconds. Keep in sync with TimerType!
constexpr HistogramParams kTimerHistogramParams[TIMER_COUNT] = {
    {TIMER_NET_ADS_GPO_LIST, "TimeToRunNetAdsGpo", 1, 120000, 50},
    {TIMER_NET_ADS_INFO, "TimeToRunNetAdsInfo", 1, 120000, 50},
    {TIMER_NET_ADS_JOIN, "TimeToRunNetAdsJoin", 1, 120000, 50},
    {TIMER_NET_ADS_SEARCH, "TimeToRunNetAdsSearch", 1, 120000, 50},
    {TIMER_NET_ADS_WORKGROUP, "TimeToRunNetAdsWorkgroup", 1, 120000, 50},
    {TIMER_KINIT, "TimeToRunKinit", 1, 120000, 50},
    {TIMER_KLIST, "TimeToRunKlist", 1, 120000, 50},
    {TIMER_KPASSWD, "TimeToRunKpasswd", 1, 120000, 50},
    {TIMER_SMBCLIENT, "TimeToRunSmbclient", 1, 120000, 50},
    {TIMER_AUTHENTICATE_USER, "TimeToAuthenticateUser", 1, 600000, 50},
    {TIMER_GET_USER_STATUS, "TimeToGetUserStatus", 1, 600000, 50},
    {TIMER_GET_USER_KERBEROS_FILES, "TimeToGetUserKerberosFiles", 1, 10000, 50},
    {TIMER_JOIN_AD_DOMAIN, "TimeToJoinADDomain", 1, 600000, 50},
    {TIMER_REFRESH_USER_POLICY, "TimeToRefreshUserPolicy", 1, 600000, 50},
    {TIMER_REFRESH_DEVICE_POLICY, "TimeToRefreshDevicePolicy", 1, 600000, 50},
};

// UMA histogram parameters. The |max_sample| for the *_TRY_COUNT stats to
// (max_tries - 1), so that the overflow bucket captures everything that failed
// too many times. Keep in sync with MetricType!
constexpr HistogramParams kMetricHistogramParams[METRIC_COUNT] = {
    {METRIC_KINIT_FAILED_TRY_COUNT, "FailedTriesOfKinit", 1, 59, 30},
    {METRIC_SMBCLIENT_FAILED_TRY_COUNT, "FailedTriesOfSmbClient", 1, 4, 5},
    {METRIC_DOWNLOAD_GPO_COUNT, "NumGposToDownload", 1, 1000, 50},
};

// Error metric name plus a parameter to make sure array indices match enum
// values, see HistogramParams.
struct ErrorMetricParams {
  int enum_value;
  const char* metric_name;
};

// Keep in sync with ErrorMetricType!
constexpr ErrorMetricParams kErrorMetricParams[ERROR_OF_COUNT] = {
    {ERROR_OF_AUTHENTICATE_USER, "ErrorTypeOfAuthenticateUser"},
    {ERROR_OF_GET_USER_STATUS, "ErrorTypeOfGetUserStatus"},
    {ERROR_OF_GET_USER_KERBEROS_FILES, "ErrorTypeOfGetUserKerberosFiles"},
    {ERROR_OF_JOIN_AD_DOMAIN, "ErrorTypeOfJoinADDomain"},
    {ERROR_OF_REFRESH_USER_POLICY, "ErrorTypeOfRefreshUserPolicy"},
    {ERROR_OF_REFRESH_DEVICE_POLICY, "ErrorTypeOfRefreshDevicePolicy"},
    {ERROR_OF_AUTO_TGT_RENEWAL, "ErrorTypeOfAutoTgtRenewal"},
    {ERROR_OF_AUTO_MACHINE_PASSWORD_CHANGE,
     "ErrorTypeOfAutoMachinePasswordChange"},
};

}  // namespace

ScopedTimerReporter::ScopedTimerReporter(TimerType timer_type)
    : ScopedTimerReporter(CheckedTimerType(timer_type)) {}

ScopedTimerReporter::ScopedTimerReporter(CheckedTimerType timer_type)
    : timer_(MakeFullName(kTimerHistogramParams[timer_type.value_].metric_name),
             kTimerHistogramParams[timer_type.value_].min_sample,
             kTimerHistogramParams[timer_type.value_].max_sample,
             kTimerHistogramParams[timer_type.value_].num_buckets) {
  timer_.Start();
}

ScopedTimerReporter::~ScopedTimerReporter() {
  const bool success = (timer_.Stop() && timer_.ReportMilliseconds());
  if (!success)
    LOG(WARNING) << "Timer " << timer_.histogram_name() << " failed to report.";
}

ScopedTimerReporter::CheckedTimerType::CheckedTimerType(TimerType value)
    : value_(std::min(static_cast<TimerType>(TIMER_COUNT - 1),
                      std::max(static_cast<TimerType>(0), value))) {
  DCHECK(value >= 0 && value < TIMER_COUNT);
}

// Verifies that the array order in the k*Params matches the enum_value.
template <typename T, const T* params, int n>
void CheckArrayOrder() {
  static_assert(params[n].enum_value == n, "Bad array order");
  CheckArrayOrder<T, params, n + 1>();
}
template <>
void CheckArrayOrder<HistogramParams, kTimerHistogramParams, TIMER_COUNT>() {}
template <>
void CheckArrayOrder<HistogramParams, kMetricHistogramParams, METRIC_COUNT>() {}
template <>
void CheckArrayOrder<ErrorMetricParams, kErrorMetricParams, ERROR_OF_COUNT>() {}

AuthPolicyMetrics::AuthPolicyMetrics() {
  CheckArrayOrder<HistogramParams, kTimerHistogramParams, 0>();
  CheckArrayOrder<HistogramParams, kMetricHistogramParams, 0>();
  CheckArrayOrder<ErrorMetricParams, kErrorMetricParams, 0>();

  chromeos_metrics::TimerReporter::set_metrics_lib(&metrics_);
}

AuthPolicyMetrics::~AuthPolicyMetrics() {
  chromeos_metrics::TimerReporter::set_metrics_lib(nullptr);
}

void AuthPolicyMetrics::Report(MetricType metric_type, int sample) {
  DCHECK(metric_type >= 0 && metric_type < METRIC_COUNT);
  metrics_.SendToUMA(
      MakeFullName(kMetricHistogramParams[metric_type].metric_name), sample,
      kMetricHistogramParams[metric_type].min_sample,
      kMetricHistogramParams[metric_type].max_sample,
      kMetricHistogramParams[metric_type].num_buckets);
}

void AuthPolicyMetrics::ReportError(ErrorMetricType metric_type,
                                    ErrorType error) {
  DCHECK(metric_type >= 0 && metric_type < ERROR_OF_COUNT);
  metrics_.SendEnumToUMA(
      MakeFullName(kErrorMetricParams[metric_type].metric_name),
      static_cast<int>(error), static_cast<int>(ERROR_COUNT));
}

}  // namespace authpolicy
