// Copyright 2018 The Fuchsia 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 "src/logger/event_loggers.h"

#include <memory>
#include <string>

#include <google/protobuf/repeated_field.h>

#include "src/algorithms/rappor/rappor_config_helper.h"
#include "src/lib/util/datetime_util.h"
#include "src/lib/util/status.h"
#include "src/logger/event_record.h"
#include "src/logging.h"
#include "src/pb/event.pb.h"
#include "src/pb/observation.pb.h"
#include "src/registry/metric_definition.pb.h"
#include "src/registry/report_definition.pb.h"
#include "src/tracing.h"

namespace cobalt::logger::internal {

using ::cobalt::local_aggregation::EventAggregator;
using ::cobalt::rappor::RapporConfigHelper;
using ::cobalt::util::TimeToDayIndex;
using ::cobalt::util::TimeToHourId;
using ::google::protobuf::RepeatedField;
using ::google::protobuf::RepeatedPtrField;

constexpr char TRACE_PREFIX[] = "[COBALT_EVENT_TRACE] ";

namespace {

Status FromStatus(const cobalt::util::Status& status) {
  switch (status.error_code()) {
    case cobalt::util::StatusCode::OK:
      return kOK;
    case cobalt::util::StatusCode::INVALID_ARGUMENT:
      return kInvalidArguments;
    default:
      return kOther;
  }
}

}  // namespace

std::unique_ptr<EventLogger> EventLogger::Create(
    MetricDefinition::MetricType metric_type, const Encoder* encoder,
    EventAggregator* event_aggregator, local_aggregation::LocalAggregation* local_aggregation,
    const ObservationWriter* observation_writer,
    const system_data::SystemDataInterface* system_data) {
  switch (metric_type) {
    case MetricDefinition::EVENT_OCCURRED: {
      return std::make_unique<internal::EventOccurredEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::EVENT_COUNT: {
      return std::make_unique<internal::EventCountEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::ELAPSED_TIME: {
      return std::make_unique<internal::ElapsedTimeEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::FRAME_RATE: {
      return std::make_unique<internal::FrameRateEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::MEMORY_USAGE: {
      return std::make_unique<internal::MemoryUsageEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::INT_HISTOGRAM: {
      return std::make_unique<internal::IntHistogramEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::OCCURRENCE: {
      return std::make_unique<internal::OccurrenceEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::INTEGER: {
      return std::make_unique<internal::IntegerEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::INTEGER_HISTOGRAM: {
      return std::make_unique<internal::IntegerHistogramEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::STRING: {
      return std::make_unique<internal::StringEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::CUSTOM: {
      return std::make_unique<internal::CustomEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    default: {
      LOG(ERROR) << "Failed to process a metric type of " << metric_type;
      return nullptr;
    }
  }
}

std::string EventLogger::TraceEvent(const EventRecord& event_record) {
  if (!event_record.metric()->meta_data().also_log_locally()) {
    return "";
  }

  auto event = event_record.event();

  std::stringstream ss;
  ss << "Day index: " << event->day_index() << std::endl;
  if (event->has_event_occurred_event()) {
    const auto& e = event->event_occurred_event();
    ss << "EventOccurredEvent: " << e.event_code() << std::endl;
  } else if (event->has_event_count_event()) {
    const auto& e = event->event_count_event();
    ss << "EventCountEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component()
       << ", PeriodDurationMicros: " << e.period_duration_micros() << ", Count: " << e.count()
       << std::endl;
  } else if (event->has_elapsed_time_event()) {
    const auto& e = event->elapsed_time_event();
    ss << "ElapsedTimeEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component() << ", ElapsedMicros: " << e.elapsed_micros()
       << std::endl;
  } else if (event->has_frame_rate_event()) {
    const auto& e = event->frame_rate_event();
    ss << "FrameRateEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component()
       << ", FramesPer1000Seconds: " << e.frames_per_1000_seconds() << std::endl;
  } else if (event->has_memory_usage_event()) {
    const auto& e = event->memory_usage_event();
    ss << "MemoryUsageEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component() << ", Bytes: " << e.bytes() << std::endl;
  } else if (event->has_int_histogram_event()) {
    const auto& e = event->int_histogram_event();
    ss << "IntHistogramEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component() << std::endl;
    for (const auto& bucket : e.buckets()) {
      ss << "| " << bucket.index() << " = " << bucket.count() << std::endl;
    }
  } else if (event->has_occurrence_event()) {
    const OccurrenceEvent& e = event->occurrence_event();
    ss << "OccurrenceEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Count: " << e.count() << std::endl;
  } else if (event->has_integer_event()) {
    const IntegerEvent& e = event->integer_event();
    ss << "IntegerEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Value: " << e.value() << std::endl;
  } else if (event->has_integer_histogram_event()) {
    const IntegerHistogramEvent& e = event->integer_histogram_event();
    ss << "IntegerHistogramEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    for (const HistogramBucket& bucket : e.buckets()) {
      ss << "| " << bucket.index() << " = " << bucket.count() << std::endl;
    }
  } else if (event->has_string_event()) {
    const StringEvent& e = event->string_event();
    ss << "StringEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", String: " << e.string_value() << std::endl;
  } else if (event->has_custom_event()) {
    const auto& e = event->custom_event();
    ss << "CustomEvent:";
    if (e.values().empty()) {
      ss << " (Empty)";
    }
    ss << std::endl;
    for (const auto& entry : e.values()) {
      switch (entry.second.data_case()) {
        ss << "| " << entry.first << " = ";
        case CustomDimensionValue::kStringValue:
          ss << entry.second.string_value();
          break;
        case CustomDimensionValue::kIntValue:
          ss << entry.second.int_value();
          break;
        case CustomDimensionValue::kBlobValue:
          ss << "Blob";
          break;
        case CustomDimensionValue::kIndexValue:
          ss << entry.second.index_value();
          break;
        case CustomDimensionValue::kDoubleValue:
          ss << entry.second.double_value();
          break;
        default:
          ss << "No dimension value";
          break;
      }
      ss << std::endl;
    }
  }

  return ss.str();
}

void EventLogger::TraceLogFailure(const Status& status, const EventRecord& event_record,
                                  const std::string& trace, const ReportDefinition& report) {
  if (!event_record.metric()->meta_data().also_log_locally()) {
    return;
  }

  LOG(INFO) << TRACE_PREFIX << "("
            << event_record.project_context()->RefMetric(event_record.metric()).FullyQualifiedName()
            << "): Error (" << status << ")" << std::endl
            << trace << "While trying to send report: " << report.report_name() << std::endl;
}

void EventLogger::TraceLogSuccess(const EventRecord& event_record, const std::string& trace) {
  if (!event_record.metric()->meta_data().also_log_locally()) {
    return;
  }

  LOG(INFO) << TRACE_PREFIX << "("
            << event_record.project_context()->RefMetric(event_record.metric()).FullyQualifiedName()
            << "):" << std::endl
            << trace;
}

Status EventLogger::Log(std::unique_ptr<EventRecord> event_record,
                        const std::chrono::system_clock::time_point& event_timestamp) {
  TRACE_DURATION("cobalt_core", "EventLogger::Log", "metric_id", event_record->metric()->id());

  FinalizeEvent(event_record.get(), event_timestamp);

  if (system_data_) {
    if (system_data_->release_stage() > event_record->metric()->meta_data().max_release_stage()) {
      // Quietly ignore this metric.
      LOG_FIRST_N(INFO, 10) << "Not logging metric `"
                            << event_record->project_context()->FullMetricName(
                                   *event_record->metric())
                            << "` because its max_release_stage ("
                            << event_record->metric()->meta_data().max_release_stage()
                            << ") is lower than the device's current release_stage: "
                            << system_data_->release_stage();
      return kOK;
    }
  }

  int num_reports = event_record->metric()->reports_size();
  int report_index = 0;
  if (event_record->metric()->reports_size() == 0) {
    VLOG(1) << "Warning: An event was logged for a metric with no reports "
               "defined: "
            << event_record->project_context()->FullMetricName(*event_record->metric());
  }

  // Store the trace before attempting to log the event. This way, if parts of
  // the event are moved out of the object, the resulting trace will still have
  // useful information.
  auto trace = TraceEvent(*event_record);

  Status status;
  if (IsOnePointOne()) {
    const cobalt::util::Status cobalt_status = local_aggregation()->AddEvent(*event_record);
    status = FromStatus(cobalt_status);
    if (!cobalt_status.ok()) {
      LOG(ERROR) << "Error occurred while locally aggregating event: "
                 << cobalt_status.error_message();
      TraceLogFailure(status, *event_record, trace, event_record->metric()->reports(0));
      return status;
    }
  } else {
    for (const auto& report : event_record->metric()->reports()) {
      status = MaybeUpdateLocalAggregation(report, *event_record);
      if (status != kOK) {
        TraceLogFailure(status, *event_record, trace, report);
        return status;
      }

      // If we are processing the final report, then we set may_invalidate
      // to true in order to allow data to be moved out of |event_record|
      // instead of being copied. One example where this is useful is when
      // creating an immediate Observation of type Histogram. In that case
      // we can move the histogram from the Event to the Observation and
      // avoid copying. Since the |event_record| is invalidated, any other
      // operation on the |event_record| must be performed before this for
      // loop.
      bool may_invalidate = ++report_index == num_reports;
      status = MaybeGenerateImmediateObservation(report, may_invalidate, event_record.get());
      if (status != kOK) {
        TraceLogFailure(status, *event_record, trace, report);
        return status;
      }
    }
  }

  TraceLogSuccess(*event_record, trace);
  return kOK;
}

Status EventLogger::PrepareAndValidateEvent(uint32_t metric_id,
                                            MetricDefinition::MetricType expected_type,
                                            EventRecord* event_record) {
  if (event_record->metric() == nullptr) {
    LOG(ERROR) << "There is no metric with ID '" << metric_id << "' registered "
               << "in project '" << event_record->project_context()->FullyQualifiedName() << "'.";
    return kInvalidArguments;
  }
  if (event_record->metric()->metric_type() != expected_type) {
    LOG(ERROR) << "Metric "
               << event_record->project_context()->FullMetricName(*event_record->metric())
               << " is not of type " << expected_type << " instead it is of type "
               << event_record->metric()->metric_type() << ".";
    return kInvalidArguments;
  }
  return ValidateEvent(*event_record);
}

void EventLogger::FinalizeEvent(EventRecord* event_record,
                                const std::chrono::system_clock::time_point& event_timestamp) {
  // Compute the day_index and hour index.
  auto now = std::chrono::system_clock::to_time_t(event_timestamp);
  event_record->event()->set_day_index(
      TimeToDayIndex(now, event_record->metric()->time_zone_policy()));
  event_record->event()->set_hour_id(TimeToHourId(now, event_record->metric()->time_zone_policy()));
}

Status EventLogger::ValidateEvent(const EventRecord& /*event_record*/) { return kOK; }

Status EventLogger::ValidateEventCodes(const MetricDefinition& metric,
                                       const RepeatedField<uint32_t>& event_codes,
                                       const std::string& full_metric_name) {
  // Special case: Users of the version of the Log*() method that takes
  // a single event code as opposed to a vector of event codes use the
  // convention of passing a zero value for the single event code in the
  // case that the metric does not have any metric dimensions defined. We have
  // no way of distinguishing here that case from the case in which the user
  // invoked the other version of the method and explicitly passed a vector of
  // length one containing a single zero event code. Therefore we must accept
  // a single 0 event code when there are no metric dimensions defined.
  // The packing of multiple event codes into a single integer field in an
  // Observation (see config/packed_event_codes.h) does not distinguish
  // between a single event code with value 0 and an empty list of event codes.
  // Therefore the server also cannot tell the difference between these two
  // cases just by looking at an Observation and relies on the metric definition
  // to distinguish them. Consequently there is no harm in us passing the
  // single zero value to the Encoder: It will produce the same Observation
  // whether or not we do.
  if (metric.metric_dimensions_size() == 0 && event_codes.size() == 1 && event_codes.Get(0) == 0) {
    return kOK;
  }
  // When new dimensions are added to a metric, they can only be appended, not deleted or inserted.
  // Because of this, and because metric definitions may change before the matching code does, we
  // want to accept events where fewer than the expected number of event_codes have been provided.
  if (event_codes.size() > metric.metric_dimensions_size()) {
    LOG(ERROR) << "The number of event_codes given, " << event_codes.size()
               << ", is more than the number of metric_dimensions, "
               << metric.metric_dimensions_size() << ", for metric " << full_metric_name << ".";
    return kInvalidArguments;
  }
  for (int i = 0; i < event_codes.size(); i++) {
    const auto& dim = metric.metric_dimensions(i);
    auto code = event_codes.Get(i);

    // This verifies the two possible validation modes for a metric_dimension.
    //
    // 1. If it has a max_event_code, then all we do is verify that the supplied
    //    code is <= that value
    //
    // 2. If no max_event_code is specified, we verify that the supplied code
    //    maps to one of the values in the event_code map.
    if (dim.max_event_code() > 0) {
      if (code > dim.max_event_code()) {
        LOG(ERROR) << "The event_code given for dimension " << i << ", " << code
                   << ", exceeds the max_event_code for that dimension, " << dim.max_event_code()
                   << ", for metric " << full_metric_name;
        return kInvalidArguments;
      }
    } else {
      bool valid = false;
      for (const auto& event_code : dim.event_codes()) {
        if (event_code.first == code) {
          valid = true;
          break;
        }
      }

      if (!valid) {
        LOG(ERROR) << "The event_code given for dimension " << i << ", " << code
                   << ", is not a valid event code for that dimension."
                   << ". You must either define this event code in"
                      " the metric_dimension, or set max_event_code >= "
                   << code << ", for metric " << full_metric_name;
        return kInvalidArguments;
      }
    }
  }
  return kOK;
}

// The default implementation of MaybeUpdateLocalAggregation does nothing
// and returns OK.
Status EventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& /*report*/,
                                                const EventRecord& /*event_record*/) {
  // In Cobalt 1.1 calling MaybeUpdateLocalAggregation is considered an error.
  if (IsOnePointOne()) {
    return kOther;
  }
  return kOK;
}

Status EventLogger::MaybeGenerateImmediateObservation(const ReportDefinition& report,
                                                      bool may_invalidate,
                                                      EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "EventLogger::MaybeGenerateImmediateObservation");
  // In Cobalt 1.1 calling MaybeGenerateImmediateObservation is considered an error.
  if (IsOnePointOne()) {
    return kOther;
  }

  auto encoder_result = MaybeEncodeImmediateObservation(report, may_invalidate, event_record);
  if (encoder_result.status != kOK) {
    return encoder_result.status;
  }
  if (encoder_result.observation == nullptr) {
    return kOK;
  }
  return observation_writer_->WriteObservation(encoder_result.observation,
                                               std::move(encoder_result.metadata), false);
}

// The default implementation of MaybeEncodeImmediateObservation does
// nothing and returns OK.
Encoder::Result EventLogger::MaybeEncodeImmediateObservation(const ReportDefinition& /*report*/,
                                                             bool /*may_invalidate*/,
                                                             EventRecord* /*event_record*/) {
  TRACE_DURATION("cobalt_core", "EventLogger::MaybeEncodeImmediateObservation");
  Encoder::Result result;
  result.status = kOK;
  result.observation = nullptr;
  return result;
}

Encoder::Result EventLogger::BadReportType(const std::string& full_metric_name,
                                           const ReportDefinition& report) {
  LOG(ERROR) << "Invalid Cobalt config: Report " << report.report_name() << " for metric "
             << full_metric_name << " is not of an appropriate type for the metric type.";
  Encoder::Result encoder_result;
  encoder_result.status = kInvalidConfig;
  return encoder_result;
}

/////////////// EventOccurredEventLogger method implementations ///////////////////

Status EventOccurredEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.event()->has_event_occurred_event());
  if (event_record.metric()->metric_dimensions_size() != 1) {
    LOG(ERROR) << "The Metric "
               << event_record.project_context()->FullMetricName(*event_record.metric())
               << " has the wrong number of metric_dimensions. A metric of "
                  "type EVENT_OCCURRED must have exactly one metric_dimension.";
    return kInvalidConfig;
  }

  const auto& event_occurred_event = event_record.event()->event_occurred_event();
  if (event_occurred_event.event_code() >
      event_record.metric()->metric_dimensions(0).max_event_code()) {
    LOG(ERROR) << "The event_code " << event_occurred_event.event_code() << " exceeds "
               << event_record.metric()->metric_dimensions(0).max_event_code()
               << ", the max_event_code for Metric "
               << event_record.project_context()->FullMetricName(*event_record.metric()) << ".";
    return kInvalidArguments;
  }
  return kOK;
}

Encoder::Result EventOccurredEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool /*may_invalidate*/, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "EventOccurredEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_event_occurred_event());
  const auto& event_occurred_event = event.event_occurred_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::SIMPLE_OCCURRENCE_COUNT: {
      return encoder()->EncodeBasicRapporObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          event_occurred_event.event_code(), RapporConfigHelper::BasicRapporNumCategories(metric));
    }
      // Report type UNIQUE_N_DAY_ACTIVES is valid but should not result in
      // generation of an immediate observation.
    case ReportDefinition::UNIQUE_N_DAY_ACTIVES: {
      Encoder::Result result;
      result.status = kOK;
      result.observation = nullptr;
      result.metadata = nullptr;
      return result;
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

Status EventOccurredEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                             const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::UNIQUE_N_DAY_ACTIVES: {
      return event_aggregator()->AddUniqueActivesEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

///////////// EventCountEventLogger method implementations //////////////////////////

Status EventCountEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->event_count_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Encoder::Result EventCountEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool /*may_invalidate*/, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "EventCountEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_event_count_event());
  auto* event_count_event = event_record->event()->mutable_event_count_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate observations.
    case ReportDefinition::EVENT_COMPONENT_OCCURRENCE_COUNT:
    case ReportDefinition::INT_RANGE_HISTOGRAM:
    case ReportDefinition::NUMERIC_AGGREGATION: {
      return encoder()->EncodeIntegerEventObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          event_count_event->event_code(), event_count_event->component(),
          event_count_event->count());
    }
    // Report type PER_DEVICE_NUMERIC_STATS and PER_DEVICE_HISTOGRAM are valid but should not result
    // in generation of an immediate observation.
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      Encoder::Result result;
      result.status = kOK;
      result.observation = nullptr;
      result.metadata = nullptr;
      return result;
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

Status EventCountEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                          const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddEventCountEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

///////////// IntegerPerformanceEventLogger method implementations /////////////

Encoder::Result IntegerPerformanceEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool /*may_invalidate*/, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "IntegerPerformanceEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::NUMERIC_AGGREGATION:
    case ReportDefinition::INT_RANGE_HISTOGRAM: {
      return encoder()->EncodeIntegerEventObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          EventCodes(event), Component(event), IntValue(event));
      break;
    }
    // Report type PER_DEVICE_NUMERIC_STATS and PER_DEVICE_HISTOGRAM are valid but should not result
    // in generation of an immediate observation.
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      Encoder::Result result;
      result.status = kOK;
      result.observation = nullptr;
      result.metadata = nullptr;
      return result;
    }
    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

////////////// ElapsedTimeEventLogger method implementations ///////////////////

const RepeatedField<uint32_t>& ElapsedTimeEventLogger::EventCodes(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  return event.elapsed_time_event().event_code();
}

std::string ElapsedTimeEventLogger::Component(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  return event.elapsed_time_event().component();
}

int64_t ElapsedTimeEventLogger::IntValue(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  return event.elapsed_time_event().elapsed_micros();
}

Status ElapsedTimeEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->elapsed_time_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status ElapsedTimeEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                           const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddElapsedTimeEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

//////////////// FrameRateEventLogger method implementations ///////////////////

const RepeatedField<uint32_t>& FrameRateEventLogger::EventCodes(const Event& event) {
  CHECK(event.has_frame_rate_event());
  return event.frame_rate_event().event_code();
}

std::string FrameRateEventLogger::Component(const Event& event) {
  CHECK(event.has_frame_rate_event());
  return event.frame_rate_event().component();
}

int64_t FrameRateEventLogger::IntValue(const Event& event) {
  CHECK(event.has_frame_rate_event());
  return event.frame_rate_event().frames_per_1000_seconds();
}

Status FrameRateEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->frame_rate_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status FrameRateEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                         const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddFrameRateEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

////////////// MemoryUsageEventLogger method implementations ///////////////////
const RepeatedField<uint32_t>& MemoryUsageEventLogger::EventCodes(const Event& event) {
  CHECK(event.has_memory_usage_event());
  return event.memory_usage_event().event_code();
}

std::string MemoryUsageEventLogger::Component(const Event& event) {
  CHECK(event.has_memory_usage_event());
  return event.memory_usage_event().component();
}

int64_t MemoryUsageEventLogger::IntValue(const Event& event) {
  CHECK(event.has_memory_usage_event());
  return event.memory_usage_event().bytes();
}

Status MemoryUsageEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->memory_usage_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status MemoryUsageEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                           const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddMemoryUsageEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

///////////// IntHistogramEventLogger method implementations ///////////////////

Status IntHistogramEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.event()->has_int_histogram_event());
  const auto& int_histogram_event = event_record.event()->int_histogram_event();
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());

  auto status = ValidateEventCodes(metric, int_histogram_event.event_code(),
                                   event_record.project_context()->FullMetricName(metric));
  if (status != kOK) {
    return status;
  }

  if (!metric.has_int_buckets()) {
    LOG(ERROR) << "Invalid Cobalt config: Metric "
               << event_record.project_context()->FullMetricName(metric)
               << " does not have an |int_buckets| field set.";
    return kInvalidConfig;
  }
  const auto& int_buckets = metric.int_buckets();
  uint32_t num_valid_buckets;
  switch (int_buckets.buckets_case()) {
    case IntegerBuckets::kExponential:
      num_valid_buckets = int_buckets.exponential().num_buckets();
      break;
    case IntegerBuckets::kLinear:
      num_valid_buckets = int_buckets.linear().num_buckets();
      break;
    case IntegerBuckets::BUCKETS_NOT_SET:
      LOG(ERROR) << "Invalid Cobalt config: Metric "
                 << event_record.project_context()->FullMetricName(metric)
                 << " has an invalid |int_buckets| field. Either exponential "
                    "or linear buckets must be specified.";
      return kInvalidConfig;
  }

  // In addition to the specified num_buckets, there are the underflow and
  // overflow buckets.
  num_valid_buckets += 2;

  size_t num_provided_buckets = int_histogram_event.buckets_size();
  for (auto i = 0u; i < num_provided_buckets; i++) {
    if (int_histogram_event.buckets(i).index() >= num_valid_buckets) {
      LOG(ERROR) << "The provided histogram is invalid. The index value of "
                 << int_histogram_event.buckets(i).index() << " in position " << i
                 << " is out of bounds for Metric "
                 << event_record.project_context()->FullMetricName(metric) << ".";
      return kInvalidArguments;
    }
  }

  return kOK;
}

Encoder::Result IntHistogramEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "IntHistogramEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_int_histogram_event());
  auto* int_histogram_event = event_record->event()->mutable_int_histogram_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::INT_RANGE_HISTOGRAM: {
      HistogramPtr histogram = std::make_unique<RepeatedPtrField<HistogramBucket>>();
      if (may_invalidate) {
        // We move the buckets out of |int_histogram_event| thereby
        // invalidating that variable.
        histogram->Swap(int_histogram_event->mutable_buckets());
      } else {
        histogram->CopyFrom(int_histogram_event->buckets());
      }
      return encoder()->EncodeHistogramObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          int_histogram_event->event_code(), int_histogram_event->component(),
          std::move(histogram));
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

///////////// OccurrenceEventLogger method implementations //////////////////////////

Status OccurrenceEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_occurrence_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "OccurrenceEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->occurrence_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

///////////// IntegerEventLogger method implementations //////////////////////////

Status IntegerEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_integer_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "IntegerEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->integer_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

///////////// IntegerHistogramEventLogger method implementations //////////////////////////

Status IntegerHistogramEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_integer_histogram_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "IntegerHistogramEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  const IntegerHistogramEvent& integer_histogram_event =
      event_record.event()->integer_histogram_event();
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());

  auto status = ValidateEventCodes(metric, integer_histogram_event.event_code(),
                                   event_record.project_context()->FullMetricName(metric));
  if (status != kOK) {
    return status;
  }

  if (!metric.has_int_buckets()) {
    LOG(ERROR) << "Invalid Cobalt config: Metric "
               << event_record.project_context()->FullMetricName(metric)
               << " does not have an |int_buckets| field set.";
    return kInvalidConfig;
  }
  const IntegerBuckets& int_buckets = metric.int_buckets();
  uint32_t num_valid_buckets;
  switch (int_buckets.buckets_case()) {
    case IntegerBuckets::kExponential:
      num_valid_buckets = int_buckets.exponential().num_buckets();
      break;
    case IntegerBuckets::kLinear:
      num_valid_buckets = int_buckets.linear().num_buckets();
      break;
    case IntegerBuckets::BUCKETS_NOT_SET:
      LOG(ERROR) << "Invalid Cobalt config: Metric "
                 << event_record.project_context()->FullMetricName(metric)
                 << " has an invalid |int_buckets| field. Either exponential "
                    "or linear buckets must be specified.";
      return kInvalidConfig;
  }

  // In addition to the specified num_buckets, there are the underflow and
  // overflow buckets.
  num_valid_buckets += 2;

  size_t num_provided_buckets = integer_histogram_event.buckets_size();
  for (auto i = 0u; i < num_provided_buckets; ++i) {
    if (integer_histogram_event.buckets(i).index() >= num_valid_buckets) {
      LOG(ERROR) << "The provided histogram is invalid. The index value of "
                 << integer_histogram_event.buckets(i).index() << " in position " << i
                 << " is out of bounds for Metric "
                 << event_record.project_context()->FullMetricName(metric) << ".";
      return kInvalidArguments;
    }
  }

  return kOK;
}

///////////// StringEventLogger method implementations //////////////////////////

Status StringEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_string_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "StringEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->string_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

/////////////// CustomEventLogger method implementations ///////////////////////

Status CustomEventLogger::ValidateEvent(const EventRecord& /*event_record*/) {
  // TODO(ninai) Add proto validation.
  return kOK;
}

Encoder::Result CustomEventLogger::MaybeEncodeImmediateObservation(const ReportDefinition& report,
                                                                   bool may_invalidate,
                                                                   EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "CustomEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_custom_event());
  auto* custom_event = event_record->event()->mutable_custom_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::CUSTOM_RAW_DUMP: {
      if (!custom_event->serialized_proto().empty()) {
        auto serialized_proto = std::make_unique<std::string>();
        if (may_invalidate) {
          serialized_proto->swap(*(custom_event->mutable_serialized_proto()));
        } else {
          *serialized_proto = custom_event->serialized_proto();
        }
        return encoder()->EncodeSerializedCustomObservation(
            event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
            std::move(serialized_proto));
      }
      EventValuesPtr event_values =
          std::make_unique<google::protobuf::Map<std::string, CustomDimensionValue>>();
      if (may_invalidate) {
        // We move the contents out of |custom_event| thereby invalidating
        // that variable.
        event_values->swap(*(custom_event->mutable_values()));
      } else {
        event_values = std::make_unique<google::protobuf::Map<std::string, CustomDimensionValue>>(
            custom_event->values());
      }
      return encoder()->EncodeCustomObservation(event_record->project_context()->RefMetric(&metric),
                                                &report, event.day_index(),
                                                std::move(event_values));
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

}  // namespace cobalt::logger::internal
