// 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 "logger/logger.h"

#include <memory>
#include <string>

#include "./event.pb.h"
#include "./logging.h"
#include "./observation2.pb.h"
#include "algorithms/rappor/rappor_config_helper.h"
#include "config/encodings.pb.h"
#include "config/id.h"
#include "config/metric_definition.pb.h"
#include "config/report_definition.pb.h"
#include "logger/event_record.h"
#include "util/datetime_util.h"

namespace cobalt {
namespace logger {

using ::cobalt::rappor::RapporConfigHelper;
using ::cobalt::util::ClockInterface;
using ::cobalt::util::SystemClock;
using ::cobalt::util::TimeToDayIndex;
using ::google::protobuf::RepeatedPtrField;

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

// EventLogger is an abstract interface used internally in logger.cc to
// dispatch logging logic based on Metric type. Below we create subclasses
// of EventLogger for each of several Metric types.
class EventLogger {
 public:
  explicit EventLogger(Logger* logger) : logger_(logger) {}

  virtual ~EventLogger() = default;

  // Finds the Metric with the given ID. Expects that this has type
  // |expected_metric_type|. If not logs an error and returns.
  // If so then Logs the Event specified by |event_record| to Cobalt.
  Status Log(uint32_t metric_id,
             MetricDefinition::MetricType expected_metric_type,
             EventRecord* event_record);

 protected:
  const Encoder* encoder() { return logger_->encoder_; }
  EventAggregator* event_aggregator() { return logger_->event_aggregator_; }
  const ProjectContext* project_context() { return logger_->project_context_; }
  Encoder::Result BadReportType(const MetricDefinition& metric,
                                const ReportDefinition& report);

 private:
  // Finishes setting up and then validates |event_record|.
  Status FinalizeEvent(uint32_t metric_id,
                       MetricDefinition::MetricType expected_type,
                       EventRecord* event_record);

  virtual Status ValidateEvent(const EventRecord& event_record);

  // Given an EventRecord and a ReportDefinition, determines whether or not
  // the Event should be used to update a local aggregation and if so passes
  // the Event to the Local Aggregator.
  virtual Status MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                             EventRecord* event_record);

  // Given an EventRecord and a ReportDefinition, determines whether or not
  // the Event should be used to generate an immediate Observation and if so
  // does generate one and writes it to the Observation Store.
  //
  // |may_invalidate| indicates that the implementation is allowed to invalidate
  // |event_record|. This should be set true only when it is known that
  // |event_record| is no longer needed. Setting this true allows the data in
  // |event_record| to be moved rather than copied.
  Status MaybeGenerateImmediateObservation(const ReportDefinition& report,
                                           bool may_invalidate,
                                           EventRecord* event_record);

  // Given an EventRecord and a ReportDefinition, determines whether or not
  // the Event should be used to generate an immediate Observation and if so
  // does generate one. This method is invoked by
  // MaybeGenerateImmediateObservation().
  //
  // |may_invalidate| indicates that the implementation is allowed to invalidate
  // |event_record|. This should be set true only when it is known that
  // |event_record| is no longer needed. Setting this true allows the data in
  // |event_record| to be moved rather than copied.
  virtual Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record);

  std::string TraceEvent(Event* event);
  void TraceLogFailure(const Status& status, EventRecord* event_record,
                       const ReportDefinition& report);
  void TraceLogSuccess(EventRecord* event_record);

  Logger* logger_;
};

// Implementation of EventLogger for metrics of type EVENT_OCCURRED.
class OccurrenceEventLogger : public EventLogger {
 public:
  explicit OccurrenceEventLogger(Logger* logger) : EventLogger(logger) {}
  virtual ~OccurrenceEventLogger() = default;

 private:
  Status ValidateEvent(const EventRecord& event_record) override;
  Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record) override;
  Status MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                     EventRecord* event_record) override;
};

// Implementation of EventLogger for metrics of type EVENT_COUNT.
class CountEventLogger : public EventLogger {
 public:
  explicit CountEventLogger(Logger* logger) : EventLogger(logger) {}
  virtual ~CountEventLogger() = default;

 private:
  Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record) override;
};

// Implementation of EventLogger for all of the numerical performance metric
// types. This is an abstract class. There are subclasses below for each
// metric type.
class IntegerPerformanceEventLogger : public EventLogger {
 protected:
  explicit IntegerPerformanceEventLogger(Logger* logger)
      : EventLogger(logger) {}
  virtual ~IntegerPerformanceEventLogger() = default;

 private:
  Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record) override;
  virtual uint32_t EventCode(const Event& event) = 0;
  virtual std::string Component(const Event& event) = 0;
  virtual int64_t IntValue(const Event& event) = 0;
};

// Implementation of EventLogger for metrics of type ELAPSED_TIME.
class ElapsedTimeEventLogger : public IntegerPerformanceEventLogger {
 public:
  explicit ElapsedTimeEventLogger(Logger* logger)
      : IntegerPerformanceEventLogger(logger) {}
  virtual ~ElapsedTimeEventLogger() = default;

 private:
  uint32_t EventCode(const Event& event) override;
  std::string Component(const Event& event) override;
  int64_t IntValue(const Event& event) override;
};

// Implementation of EventLogger for metrics of type FRAME_RATE.
class FrameRateEventLogger : public IntegerPerformanceEventLogger {
 public:
  explicit FrameRateEventLogger(Logger* logger)
      : IntegerPerformanceEventLogger(logger) {}
  virtual ~FrameRateEventLogger() = default;

 private:
  uint32_t EventCode(const Event& event) override;
  std::string Component(const Event& event) override;
  int64_t IntValue(const Event& event) override;
};

// Implementation of EventLogger for metrics of type MEMORY_USAGE.
class MemoryUsageEventLogger : public IntegerPerformanceEventLogger {
 public:
  explicit MemoryUsageEventLogger(Logger* logger)
      : IntegerPerformanceEventLogger(logger) {}
  virtual ~MemoryUsageEventLogger() = default;

 private:
  uint32_t EventCode(const Event& event) override;
  std::string Component(const Event& event) override;
  int64_t IntValue(const Event& event) override;
};

// Implementation of EventLogger for metrics of type INT_HISTOGRAM.
class IntHistogramEventLogger : public EventLogger {
 public:
  explicit IntHistogramEventLogger(Logger* logger) : EventLogger(logger) {}
  virtual ~IntHistogramEventLogger() = default;

 private:
  Status ValidateEvent(const EventRecord& event_record) override;
  Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record) override;
};

// Implementation of EventLogger for metrics of type STRING_USED.
class StringUsedEventLogger : public EventLogger {
 public:
  explicit StringUsedEventLogger(Logger* logger) : EventLogger(logger) {}
  virtual ~StringUsedEventLogger() = default;

 private:
  Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record) override;
};

// Implementation of EventLogger for metrics of type CUSTOM.
class CustomEventLogger : public EventLogger {
 public:
  explicit CustomEventLogger(Logger* logger) : EventLogger(logger) {}
  virtual ~CustomEventLogger() = default;

 private:
  Status ValidateEvent(const EventRecord& event_record) override;
  Encoder::Result MaybeEncodeImmediateObservation(
      const ReportDefinition& report, bool may_invalidate,
      EventRecord* event_record) override;
};

//////////////////// Logger method implementations ////////////////////////

Logger::Logger(const Encoder* encoder, EventAggregator* event_aggregator,
               ObservationWriter* observation_writer,
               const ProjectContext* project, LoggerInterface* internal_logger)
    : encoder_(encoder),
      event_aggregator_(event_aggregator),
      observation_writer_(observation_writer),
      project_context_(project),
      clock_(new SystemClock()) {
  CHECK(project);

  if (internal_logger) {
    internal_metrics_.reset(new InternalMetricsImpl(internal_logger));
  } else {
    // We were not provided with a metrics logger. We must create one.
    internal_metrics_.reset(new NoOpInternalMetrics());
  }
  if (event_aggregator_->UpdateAggregationConfigs(*project_context_) != kOK) {
    LOG(ERROR) << "Failed to provide aggregation configurations to the "
                  "EventAggregator.";
  }
}

Logger::Logger(const Encoder* encoder, ObservationWriter* observation_writer,
               const ProjectContext* project, LoggerInterface* internal_logger)
    : encoder_(encoder),
      event_aggregator_(nullptr),
      observation_writer_(observation_writer),
      project_context_(project),
      clock_(new SystemClock()) {
  CHECK(project);

  if (internal_logger) {
    internal_metrics_.reset(new InternalMetricsImpl(internal_logger));
  } else {
    // We were not provided with a metrics logger. We must create one.
    internal_metrics_.reset(new NoOpInternalMetrics());
  }
}

Status Logger::LogEvent(uint32_t metric_id, uint32_t event_code) {
  VLOG(4) << "Logger::LogEvent(" << metric_id << ", " << event_code
          << ") project=" << project_context_->FullyQualifiedName();
  EventRecord event_record;
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogEvent);
  auto* occurrence_event = event_record.event->mutable_occurrence_event();
  occurrence_event->set_event_code(event_code);
  auto event_logger = std::make_unique<OccurrenceEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::EVENT_OCCURRED,
                           &event_record);
}

Status Logger::LogEventCount(uint32_t metric_id, uint32_t event_code,
                             const std::string& component,
                             int64_t period_duration_micros, uint32_t count) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogEventCount);
  EventRecord event_record;
  auto* count_event = event_record.event->mutable_count_event();
  count_event->add_event_code(event_code);
  count_event->set_component(component);
  count_event->set_period_duration_micros(period_duration_micros);
  count_event->set_count(count);
  auto event_logger = std::make_unique<CountEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::EVENT_COUNT,
                           &event_record);
}

Status Logger::LogElapsedTime(uint32_t metric_id, uint32_t event_code,
                              const std::string& component,
                              int64_t elapsed_micros) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogElapsedTime);
  EventRecord event_record;
  auto* elapsed_time_event = event_record.event->mutable_elapsed_time_event();
  elapsed_time_event->add_event_code(event_code);
  elapsed_time_event->set_component(component);
  elapsed_time_event->set_elapsed_micros(elapsed_micros);
  auto event_logger = std::make_unique<ElapsedTimeEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::ELAPSED_TIME,
                           &event_record);
}

Status Logger::LogFrameRate(uint32_t metric_id, uint32_t event_code,
                            const std::string& component, float fps) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogFrameRate);
  EventRecord event_record;
  auto* frame_rate_event = event_record.event->mutable_frame_rate_event();
  frame_rate_event->add_event_code(event_code);
  frame_rate_event->set_component(component);
  frame_rate_event->set_frames_per_1000_seconds(std::round(fps * 1000.0));
  auto event_logger = std::make_unique<FrameRateEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::FRAME_RATE,
                           &event_record);
}

Status Logger::LogMemoryUsage(uint32_t metric_id, uint32_t event_code,
                              const std::string& component, int64_t bytes) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogMemoryUsage);
  EventRecord event_record;
  auto* memory_usage_event = event_record.event->mutable_memory_usage_event();
  memory_usage_event->add_event_code(event_code);
  memory_usage_event->set_component(component);
  memory_usage_event->set_bytes(bytes);
  auto event_logger = std::make_unique<MemoryUsageEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::MEMORY_USAGE,
                           &event_record);
}

Status Logger::LogIntHistogram(uint32_t metric_id, uint32_t event_code,
                               const std::string& component,
                               HistogramPtr histogram) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogIntHistogram);
  EventRecord event_record;
  auto* int_histogram_event = event_record.event->mutable_int_histogram_event();
  int_histogram_event->add_event_code(event_code);
  int_histogram_event->set_component(component);
  int_histogram_event->mutable_buckets()->Swap(histogram.get());
  auto event_logger = std::make_unique<IntHistogramEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::INT_HISTOGRAM,
                           &event_record);
}

Status Logger::LogString(uint32_t metric_id, const std::string& str) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogString);
  EventRecord event_record;
  auto* string_used_event = event_record.event->mutable_string_used_event();
  string_used_event->set_str(str);
  auto event_logger = std::make_unique<StringUsedEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::STRING_USED,
                           &event_record);
}

Status Logger::LogCustomEvent(uint32_t metric_id, EventValuesPtr event_values) {
  internal_metrics_->LoggerCalled(LoggerCallsMadeEventCode::LogCustomEvent);
  EventRecord event_record;
  auto* custom_event = event_record.event->mutable_custom_event();
  custom_event->mutable_values()->swap(*event_values);
  auto event_logger = std::make_unique<CustomEventLogger>(this);
  return event_logger->Log(metric_id, MetricDefinition::CUSTOM, &event_record);
}

//////////////////// EventLogger method implementations ////////////////////////

std::string EventLogger::TraceEvent(Event* event) {
  std::stringstream ss;
  ss << "Day index: " << event->day_index() << std::endl;
  if (event->has_occurrence_event()) {
    auto e = event->occurrence_event();
    ss << "OccurrenceEvent: " << e.event_code() << std::endl;
  } else if (event->has_count_event()) {
    auto e = event->count_event();
    ss << "CountEvent:" << 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()) {
    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()) {
    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()) {
    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()) {
    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_string_used_event()) {
    auto e = event->string_used_event();
    ss << "StringUsedEvent: " << e.str() << std::endl;
  } else if (event->has_custom_event()) {
    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,
                                  EventRecord* event_record,
                                  const ReportDefinition& report) {
  if (!event_record->metric->meta_data().also_log_locally()) {
    return;
  }

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

void EventLogger::TraceLogSuccess(EventRecord* event_record) {
  if (!event_record->metric->meta_data().also_log_locally()) {
    return;
  }

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

Status EventLogger::Log(uint32_t metric_id,
                        MetricDefinition::MetricType expected_metric_type,
                        EventRecord* event_record) {
  // TODO(rudominer) Check the ReleaseStage of the Metric against the
  // ReleaseStage of the project.
  auto status = FinalizeEvent(metric_id, expected_metric_type, event_record);
  if (status != kOK) {
    return status;
  }

  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. Metric ["
            << MetricDebugString(*event_record->metric) << "] in project "
            << project_context()->DebugString() << ".";
  }

  for (const auto& report : event_record->metric->reports()) {
    status = MaybeUpdateLocalAggregation(report, event_record);
    if (status != kOK) {
      TraceLogFailure(status, event_record, 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);
    if (status != kOK) {
      TraceLogFailure(status, event_record, report);
      return status;
    }
  }

  TraceLogSuccess(event_record);
  return kOK;
}

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

  // Compute the day_index.
  event_record->event->set_day_index(TimeToDayIndex(
      std::chrono::system_clock::to_time_t(logger_->clock_->now()),
      event_record->metric->time_zone_policy()));

  return ValidateEvent(*event_record);
}

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

// The default implementation of MaybeUpdateLocalAggregation does nothing
// and returns OK.
Status EventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                EventRecord* event_record) {
  return kOK;
}

Status EventLogger::MaybeGenerateImmediateObservation(
    const ReportDefinition& report, bool may_invalidate,
    EventRecord* event_record) {
  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 logger_->observation_writer_->WriteObservation(
      *encoder_result.observation, std::move(encoder_result.metadata));
}

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

Encoder::Result EventLogger::BadReportType(const MetricDefinition& metric,
                                           const ReportDefinition& report) {
  LOG(ERROR) << "Invalid Cobalt config: Report " << report.report_name()
             << " for metric " << MetricDebugString(metric) << " in project "
             << project_context()->DebugString()
             << " is not of an appropriate type for the metric type.";
  Encoder::Result encoder_result;
  encoder_result.status = kInvalidConfig;
  return encoder_result;
}

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

Status OccurrenceEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.event->has_occurrence_event());
  const auto& occurrence_event = event_record.event->occurrence_event();
  if (occurrence_event.event_code() > event_record.metric->max_event_code()) {
    LOG(ERROR) << "The event_code " << occurrence_event.event_code()
               << " exceeds "
               << event_record.metric->metric_dimensions(0).max_event_code()
               << ", the max_event_code for Metric "
               << MetricDebugString(*event_record.metric) << " in project "
               << project_context()->DebugString() << ".";
    return kInvalidArguments;
  }
  return kOK;
}

Encoder::Result OccurrenceEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate,
    EventRecord* event_record) {
  const MetricDefinition& metric = *(event_record->metric);
  const Event& event = *(event_record->event);
  CHECK(event.has_occurrence_event());
  const auto& occurrence_event = event.occurrence_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::SIMPLE_OCCURRENCE_COUNT: {
      return encoder()->EncodeBasicRapporObservation(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          occurrence_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(metric, report);
  }
}

Status OccurrenceEventLogger::MaybeUpdateLocalAggregation(
    const ReportDefinition& report, EventRecord* event_record) {
  // If the Logger was constructed without an EventAggregator, do nothing and
  // return kOK.
  // TODO(pesk): remove this clause when the deprecated Logger constructor is
  // removed.
  if (event_aggregator() == nullptr) {
    return kOK;
  }
  switch (report.report_type()) {
    case ReportDefinition::UNIQUE_N_DAY_ACTIVES: {
      return event_aggregator()->LogUniqueActivesEvent(report.id(),
                                                       event_record);
    }
    default:
      return kOK;
  }
}

///////////// CountEventLogger method implementations //////////////////////////

Encoder::Result CountEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate,
    EventRecord* event_record) {
  const MetricDefinition& metric = *(event_record->metric);
  const Event& event = *(event_record->event);
  CHECK(event.has_count_event());
  const auto& count_event = event.count_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::EVENT_COMPONENT_OCCURRENCE_COUNT: {
      return encoder()->EncodeIntegerEventObservation(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          // TODO(zmbush): Pass all event_codes, not just the first.
          count_event.event_code(0), count_event.component(),
          count_event.count());
    }

    default:
      return BadReportType(metric, report);
  }
}

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

Encoder::Result IntegerPerformanceEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate,
    EventRecord* event_record) {
  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::NUMERIC_PERF_RAW_DUMP:
    case ReportDefinition::INT_RANGE_HISTOGRAM: {
      return encoder()->EncodeIntegerEventObservation(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          EventCode(event), Component(event), IntValue(event));
      break;
    }

    default:
      return BadReportType(metric, report);
  }
}

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

uint32_t ElapsedTimeEventLogger::EventCode(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  // TODO(zmbush): Pass all event_codes, not just the first.
  return event.elapsed_time_event().event_code(0);
}

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();
}

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

uint32_t FrameRateEventLogger::EventCode(const Event& event) {
  CHECK(event.has_frame_rate_event());
  // TODO(zmbush): Pass all event_codes, not just the first.
  return event.frame_rate_event().event_code(0);
}

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();
}

////////////// MemoryUsageEventLogger method implementations ///////////////////
uint32_t MemoryUsageEventLogger::EventCode(const Event& event) {
  CHECK(event.has_memory_usage_event());
  // TODO(zmbush): Pass all event_codes, not just the first.
  return event.memory_usage_event().event_code(0);
}

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();
}

/////////////// 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();
  const auto& metric = *(event_record.metric);
  if (!metric.has_int_buckets()) {
    LOG(ERROR) << "Invalid Cobalt config: Metric " << MetricDebugString(metric)
               << " in project " << project_context()->DebugString()
               << " 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 "
                 << MetricDebugString(metric) << " in project "
                 << project_context()->DebugString()
                 << " 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 "
                 << MetricDebugString(*event_record.metric) << " in project "
                 << project_context()->DebugString() << ".";
      return kInvalidArguments;
    }
  }

  return kOK;
}

Encoder::Result IntHistogramEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate,
    EventRecord* event_record) {
  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(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          // TODO(zmbush): Pass all event_codes, not just the first.
          int_histogram_event->event_code(0), int_histogram_event->component(),
          std::move(histogram));
    }

    default:
      return BadReportType(metric, report);
  }
}

/////////////// StringUsedEventLogger method implementations ///////////////////

Encoder::Result StringUsedEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate,
    EventRecord* event_record) {
  const MetricDefinition& metric = *(event_record->metric);
  const Event& event = *(event_record->event);
  CHECK(event.has_string_used_event());
  const auto& string_used_event = event_record->event->string_used_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::HIGH_FREQUENCY_STRING_COUNTS: {
      return encoder()->EncodeRapporObservation(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          string_used_event.str());
    }
    case ReportDefinition::STRING_COUNTS_WITH_THRESHOLD: {
      return encoder()->EncodeForculusObservation(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          string_used_event.str());
    }

    default:
      return BadReportType(metric, report);
  }
}

/////////////// 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) {
  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: {
      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(
          project_context()->RefMetric(&metric), &report, event.day_index(),
          std::move(event_values));
    }

    default:
      return BadReportType(metric, report);
  }
}

}  // namespace logger
}  // namespace cobalt
