blob: b3bdd183c0c55cfe71b97db72001749aeed72ac2 [file] [log] [blame]
// Copyright 2023 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "rmad/metrics/state_metrics.h"
#include <map>
#include <utility>
#include <base/logging.h>
#include <base/values.h>
#include "rmad/constants.h"
#include "rmad/metrics/metrics_constants.h"
#include "rmad/proto_bindings/rmad.pb.h"
#include "rmad/utils/type_conversions.h"
namespace rmad {
namespace {
// TODO(chenghan): Define this in a common header, e.g. common.h.
const char* GetStateName(RmadState::StateCase state) {
auto it = kStateNames.find(state);
CHECK(it != kStateNames.end());
return it->second.data();
}
} // namespace
bool StateMetricsData::operator==(const StateMetricsData& other) const {
return state_case == other.state_case && is_aborted == other.is_aborted &&
setup_timestamp == other.setup_timestamp &&
overall_time == other.overall_time &&
transition_count == other.transition_count &&
get_log_count == other.get_log_count &&
save_log_count == other.save_log_count;
}
base::Value StateMetricsData::ToValue() const {
base::Value::Dict dict;
dict.Set(kStateCase, static_cast<int>(state_case));
dict.Set(kStateIsAborted, is_aborted);
dict.Set(kStateSetupTimestamp, setup_timestamp);
dict.Set(kStateOverallTime, overall_time);
dict.Set(kStateTransitionsCount, transition_count);
dict.Set(kStateGetLogCount, get_log_count);
dict.Set(kStateSaveLogCount, save_log_count);
return base::Value(std::move(dict));
}
bool StateMetricsData::FromValue(const base::Value* value) {
if (!value || !value->is_dict()) {
return false;
}
const base::Value::Dict& dict = value->GetDict();
StateMetricsData data;
if (auto state_case_it = dict.FindInt(kStateCase)) {
data.state_case = static_cast<RmadState::StateCase>(*state_case_it);
} else {
return false;
}
if (auto is_aborted_it = dict.FindBool(kStateIsAborted)) {
data.is_aborted = *is_aborted_it;
} else {
return false;
}
if (auto setup_timestamp_it = dict.FindDouble(kStateSetupTimestamp)) {
data.setup_timestamp = *setup_timestamp_it;
} else {
return false;
}
if (auto overall_time_it = dict.FindDouble(kStateOverallTime)) {
data.overall_time = *overall_time_it;
} else {
return false;
}
if (auto transition_count_it = dict.FindInt(kStateTransitionsCount)) {
data.transition_count = *transition_count_it;
} else {
return false;
}
if (auto get_log_count_it = dict.FindInt(kStateGetLogCount)) {
data.get_log_count = *get_log_count_it;
} else {
return false;
}
if (auto save_log_count_it = dict.FindInt(kStateSaveLogCount)) {
data.save_log_count = *save_log_count_it;
} else {
return false;
}
*this = std::move(data);
return true;
}
base::Value ConvertToValue(const StateMetricsData& data) {
return data.ToValue();
}
bool ConvertFromValue(const base::Value* value, StateMetricsData* data) {
if (!value) {
return false;
}
return !data || data->FromValue(value);
}
StateMetricsMap::StateMetricsMap(
const std::map<int, StateMetricsData>& state_metrics_map)
: state_metrics_map_(state_metrics_map) {}
bool StateMetricsMap::InitializeState(RmadState::StateCase state_case,
double setup_timestamp) {
if (state_case == RmadState::STATE_NOT_SET) {
return true;
}
int key = static_cast<int>(state_case);
state_metrics_map_[key].setup_timestamp = setup_timestamp;
state_metrics_map_[key].state_case = state_case;
return true;
}
bool StateMetricsMap::UpdateStateOverallTime(RmadState::StateCase state_case,
double leave_timestamp) {
if (state_case == RmadState::STATE_NOT_SET) {
return true;
}
int key = static_cast<int>(state_case);
if (state_metrics_map_.find(key) == state_metrics_map_.end()) {
LOG(ERROR) << GetStateName(state_case)
<< ": Failed to get state metrics to calculate.";
return false;
}
if (state_metrics_map_[key].setup_timestamp < 0.0) {
LOG(ERROR) << GetStateName(state_case) << ": Invalid setup timestamp: "
<< state_metrics_map_[key].setup_timestamp << " is less than 0.";
return false;
}
double time_spent_sec =
(state_case == kInitialStateCase)
? 0
: leave_timestamp - state_metrics_map_[key].setup_timestamp;
if (time_spent_sec < 0) {
LOG(ERROR) << GetStateName(state_case)
<< ": Failed to calculate time spent.";
return false;
}
state_metrics_map_[key].overall_time += time_spent_sec;
state_metrics_map_[key].setup_timestamp = leave_timestamp;
return true;
}
base::Value ConvertToValue(const StateMetricsMap& data) {
// ConvertToValue(std::map<int, T>) is defined in utils/type_conversions.h.
return ConvertToValue(data.GetRawMap());
}
bool ConvertFromValue(const base::Value* value, StateMetricsMap* data) {
if (!value) {
return false;
}
std::map<int, StateMetricsData> state_metrics_map;
if (!ConvertFromValue(value, &state_metrics_map)) {
return false;
}
if (data) {
*data = StateMetricsMap(std::move(state_metrics_map));
}
return true;
}
} // namespace rmad