| // Copyright 2022 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "libhwsec/middleware/metrics.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include <base/strings/string_split.h> |
| #include <metrics/metrics_library.h> |
| |
| #include "libhwsec/backend/pinweaver_manager/sync_hash_tree_types.h" |
| #include "libhwsec/error/tpm_retry_action.h" |
| #include "libhwsec/status.h" |
| |
| namespace { |
| constexpr char kHwsecMetricsPrefix[] = "Platform.Libhwsec.RetryAction"; |
| constexpr size_t kHwsecMetricsPrefixLength = sizeof(kHwsecMetricsPrefix) - 1; |
| constexpr char kPinWeaverSyncMetricsPrefix[] = |
| "Platform.Libhwsec.PinWeaverManager.SyncHashTree."; |
| constexpr char kPinWeaverReplayTypeNormal[] = ".Normal"; |
| constexpr char kPinWeaverReplayTypeFull[] = ".Full"; |
| } // namespace |
| |
| namespace hwsec { |
| |
| const char* GetPinWeaverReplayEntryTypeName(ReplayEntryType type) { |
| switch (type) { |
| case ReplayEntryType::kNormal: |
| return "Normal"; |
| case ReplayEntryType::kMismatchedHash: |
| return "MismatchedHash"; |
| case ReplayEntryType::kSecondEntry: |
| return "SecondEntry"; |
| } |
| } |
| |
| const char* GetPinWeaverLogEntryTypeName(LogEntryType type) { |
| switch (type) { |
| case LogEntryType::kInsert: |
| return "ReplayInsert"; |
| case LogEntryType::kCheck: |
| return "ReplayCheck"; |
| case LogEntryType::kRemove: |
| return "ReplayRemove"; |
| case LogEntryType::kReset: |
| return "ReplayReset"; |
| case LogEntryType::kInvalid: |
| return "ReplayInvalid"; |
| } |
| } |
| |
| bool Metrics::SendFuncResultToUMA(const std::string& func_name, |
| const Status& status) { |
| TPMRetryAction action; |
| if (status.ok()) { |
| action = TPMRetryAction::kNone; |
| } else { |
| action = status->ToTPMRetryAction(); |
| } |
| |
| std::string current_uma = kHwsecMetricsPrefix; |
| current_uma += "."; |
| current_uma += func_name; |
| |
| bool result = true; |
| |
| while (current_uma.size() >= kHwsecMetricsPrefixLength) { |
| result &= metrics_->SendEnumToUMA(current_uma, action); |
| |
| size_t pos = current_uma.find_last_of('.'); |
| if (pos == std::string::npos) { |
| break; |
| } |
| |
| current_uma.resize(pos); |
| } |
| |
| return result; |
| } |
| |
| bool Metrics::SendPinWeaverSyncOutcomeToUMA(SyncOutcome result) { |
| std::string current_uma = |
| std::string(kPinWeaverSyncMetricsPrefix) + "SyncOutcome"; |
| return metrics_->SendEnumToUMA(current_uma, result); |
| } |
| |
| bool Metrics::SendPinWeaverLogReplayResultToUMA(ReplayEntryType type, |
| LogReplayResult result) { |
| std::string current_uma = |
| std::string(kPinWeaverSyncMetricsPrefix) + "ReplayLogResult"; |
| bool ret = metrics_->SendEnumToUMA(current_uma, result); |
| |
| // Report again specifying whether it's a full replay. |
| if (type == ReplayEntryType::kNormal) { |
| current_uma.append(kPinWeaverReplayTypeNormal); |
| } else { |
| // ReplayEntryType::kMismatchedHash/kSecondEntry happens during full replay. |
| current_uma.append(kPinWeaverReplayTypeFull); |
| } |
| return ret && metrics_->SendEnumToUMA(current_uma, result); |
| } |
| |
| bool Metrics::SendPinWeaverReplayOperationResultToUMA( |
| ReplayEntryType replay_type, |
| LogEntryType entry_type, |
| const Status& status) { |
| std::string hist_str = std::string("PinWeaverManager.") + |
| GetPinWeaverLogEntryTypeName(entry_type) + "." + |
| GetPinWeaverReplayEntryTypeName(replay_type); |
| return SendFuncResultToUMA(hist_str, status); |
| } |
| |
| } // namespace hwsec |