chromium/chrome/services/system_signals/win/metrics_utils.cc

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

#include "chrome/services/system_signals/win/metrics_utils.h"

#include <cmath>
#include <optional>
#include <string_view>

#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
#include "base/win/wmi.h"

namespace system_signals {

namespace {

// Returns a percentage number representing the error rate when given the number
// of successfully parsed items as `items_count`, and the number of items that
// were not successfully parsed as `errors_count`.
int CalculateErrorRate(size_t items_count, size_t errors_count) {
  auto total_count = items_count + errors_count;
  if (total_count == 0) {
    return 0;
  }

  return std::round(100.0 * errors_count / total_count);
}

template <typename T, typename U>
void LogResponse(std::string_view histogram_variant,
                 size_t items_count,
                 const std::optional<T>& query_error,
                 const std::vector<U>& parsing_errors) {
  static constexpr char kCollectionHistogramPrefix[] =
      "Enterprise.SystemSignals.Collection";
  if (query_error) {
    base::UmaHistogramEnumeration(
        base::StrCat(
            {kCollectionHistogramPrefix, histogram_variant, ".QueryError"}),
        query_error.value());
    return;
  }

  static constexpr char kParsingError[] = ".ParsingError";
  if (!parsing_errors.empty()) {
    auto parsing_error_histogram = base::StrCat(
        {kCollectionHistogramPrefix, histogram_variant, kParsingError});
    for (auto error : parsing_errors) {
      base::UmaHistogramEnumeration(parsing_error_histogram, error);
    }
  }

  base::UmaHistogramPercentage(
      base::StrCat({kCollectionHistogramPrefix, histogram_variant,
                    kParsingError, ".Rate"}),
      CalculateErrorRate(items_count, parsing_errors.size()));
}

}  // namespace

void LogWscAvResponse(const device_signals::WscAvProductsResponse& response) {
  LogResponse(".WSC.AntiVirus", response.av_products.size(),
              response.query_error, response.parsing_errors);
}

void LogWmiHotfixResponse(const device_signals::WmiHotfixesResponse& response) {
  LogResponse(".WMI.Hotfixes", response.hotfixes.size(), response.query_error,
              response.parsing_errors);
}

}  // namespace system_signals