blob: 35bad8f050ee7fc75efbb03e000c372dbb3a8199 [file] [log] [blame]
// Copyright 2019 The Chromium 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 "components/metrics/structured/event_base.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "components/metrics/structured/enums.h"
#include "components/metrics/structured/event.h"
#include "components/metrics/structured/event_validator.h"
#include "components/metrics/structured/project_validator.h"
#include "components/metrics/structured/recorder.h"
#include "components/metrics/structured/structured_metrics_client.h"
#include "components/metrics/structured/structured_metrics_validator.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace metrics {
namespace structured {
EventBase::EventBase(uint64_t event_name_hash,
uint64_t project_name_hash,
IdType id_type,
IdScope id_scope,
StructuredEventProto_EventType event_type,
int key_rotation_period)
: event_name_hash_(event_name_hash),
project_name_hash_(project_name_hash),
id_type_(id_type),
id_scope_(id_scope),
event_type_(event_type),
key_rotation_period_(key_rotation_period) {}
EventBase::EventBase(const EventBase& other) = default;
EventBase::~EventBase() = default;
absl::optional<int> EventBase::LastKeyRotation() {
return Recorder::GetInstance()->LastKeyRotation(project_name_hash_);
}
void EventBase::AddHmacMetric(uint64_t name_hash, const std::string& value) {
Metric metric(name_hash, MetricType::kHmac);
metric.hmac_value = value;
metrics_.push_back(metric);
}
void EventBase::AddIntMetric(uint64_t name_hash, int64_t value) {
Metric metric(name_hash, MetricType::kInt);
metric.int_value = value;
metrics_.push_back(metric);
}
void EventBase::AddRawStringMetric(uint64_t name_hash,
const std::string& value) {
Metric metric(name_hash, MetricType::kRawString);
metric.string_value = value;
metrics_.push_back(metric);
}
EventBase::Metric::Metric(uint64_t name_hash, MetricType type)
: name_hash(name_hash), type(type) {}
EventBase::Metric::~Metric() = default;
bool EventBase::Metric::operator==(const EventBase::Metric& other) const {
// Terminate early to avoid accessing irrelevant values.
if (name_hash != other.name_hash || type != other.type)
return false;
switch (type) {
case MetricType::kHmac:
return hmac_value == other.hmac_value;
case MetricType::kInt:
return int_value == other.int_value;
case MetricType::kRawString:
return string_value == other.string_value;
}
NOTREACHED();
}
// static
absl::optional<EventBase> EventBase::FromEvent(const Event& event) {
auto project_validator = validator::GetProjectValidator(event.project_name());
if (!project_validator.has_value())
return absl::nullopt;
const auto event_validator =
project_validator.value()->GetEventValidator(event.event_name());
if (!event_validator.has_value())
return absl::nullopt;
EventBase event_base(event_validator.value()->event_hash(),
project_validator.value()->project_hash(),
project_validator.value()->id_type(),
project_validator.value()->id_scope(),
project_validator.value()->event_type(),
project_validator.value()->key_rotation_period());
for (const auto& metric_value : event.metric_values()) {
// Validate that both name and metric type are valid structured metrics.
absl::optional<EventValidator::MetricMetadata> metric_metadata =
event_validator.value()->GetMetricMetadata(metric_value.first);
if (!metric_metadata.has_value() ||
metric_metadata.value().metric_type != metric_value.second.type) {
return absl::nullopt;
}
const auto& value = metric_value.second.value;
switch (metric_value.second.type) {
case Event::MetricType::kHmac:
event_base.AddHmacMetric(metric_metadata.value().metric_name_hash,
value.GetString());
break;
case Event::MetricType::kLong:
int64_t long_value;
base::StringToInt64(value.GetString(), &long_value);
event_base.AddIntMetric(metric_metadata.value().metric_name_hash,
long_value);
break;
case Event::MetricType::kInt:
event_base.AddIntMetric(metric_metadata.value().metric_name_hash,
value.GetInt());
break;
case Event::MetricType::kRawString:
event_base.AddRawStringMetric(metric_metadata.value().metric_name_hash,
value.GetString());
break;
// TODO(jongahn): Support these types.
case Event::MetricType::kBoolean:
case Event::MetricType::kDouble:
VLOG(1) << "Metric type not supported";
NOTREACHED();
break;
}
}
return event_base;
}
} // namespace structured
} // namespace metrics