blob: c0433db1759f3551567efd51f1557ff498aa376f [file] [log] [blame]
// 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.
#ifndef COBALT_SRC_LOGGER_EVENT_LOGGERS_H_
#define COBALT_SRC_LOGGER_EVENT_LOGGERS_H_
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "src/local_aggregation/event_aggregator.h"
#include "src/local_aggregation_1_1/local_aggregation.h"
#include "src/logger/encoder.h"
#include "src/logger/event_record.h"
#include "src/logger/observation_writer.h"
#include "src/logger/project_context.h"
#include "src/logger/status.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 ::google::protobuf::RepeatedField;
// 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:
EventLogger(const Encoder* encoder, local_aggregation::EventAggregator* event_aggregator,
local_aggregation::LocalAggregation* local_aggregation,
const ObservationWriter* observation_writer,
const system_data::SystemDataInterface* system_data)
: encoder_(encoder),
event_aggregator_(event_aggregator),
local_aggregation_(local_aggregation),
observation_writer_(observation_writer),
system_data_(system_data) {}
virtual ~EventLogger() = default;
// Factory for creating an appropriate EventLogger subclass for the type of metric being logged.
//
// |metric_type| is the type of metric to be logged with the created event logger.
//
// The remaining parameters are passed to the EventLogger constructor.
static std::unique_ptr<EventLogger> Create(MetricDefinition::MetricType metric_type,
const Encoder* encoder,
local_aggregation::EventAggregator* event_aggregator,
local_aggregation::LocalAggregation* local_aggregation,
const ObservationWriter* observation_writer,
const system_data::SystemDataInterface* system_data);
// 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.
// The |event_timestamp| is recorded as the time the event occurred at.
Status Log(std::unique_ptr<EventRecord> event_record,
const std::chrono::system_clock::time_point& event_timestamp);
// Prepare an event for logging, and validate that it is suitable.
Status PrepareAndValidateEvent(uint32_t metric_id, MetricDefinition::MetricType expected_type,
EventRecord* event_record);
protected:
const Encoder* encoder() { return encoder_; }
local_aggregation::EventAggregator* event_aggregator() { return event_aggregator_; }
local_aggregation::LocalAggregation* local_aggregation() { return local_aggregation_; }
static Encoder::Result BadReportType(const std::string& full_metric_name,
const ReportDefinition& report);
// Validates the supplied event_codes against the defined metric dimensions
// in the MetricDefinition.
virtual Status ValidateEventCodes(const MetricDefinition& metric,
const RepeatedField<uint32_t>& event_codes,
const std::string& full_metric_name);
private:
friend class EventLoggersAddEventTest;
friend class EventLoggersLocalAggregationTest;
// Validate that the event is suitable for logging.
//
// Most of the event validation should be done here, as this occurs at the time
// the event occurs.
virtual Status ValidateEvent(const EventRecord& event_record);
// Finishes setting up the event using |event_timestamp| as the time the event occurred at,
// and then performs any final validation of the |event_record|.
static void FinalizeEvent(EventRecord* event_record,
const std::chrono::system_clock::time_point& event_timestamp);
// 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,
const 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);
[[nodiscard]] virtual bool IsOnePointOne() const { return false; };
// Traces an |event_record| into a string if the metric is tagged with
// also_log_locally. If not, it will return the empty string.
static std::string TraceEvent(const EventRecord& event_record);
// Logs a trace of an |event_record| that failed to be logged to Cobalt.
//
// |status| The status code reported to the user.
// |event_record| The event_record associated with the event.
// |trace| The string output from TraceEvent().
// |report| Information about the report for which the logging failed.
static void TraceLogFailure(const Status& status, const EventRecord& event_record,
const std::string& trace, const ReportDefinition& report);
// Logs a trace of an |event_record| that successfully logged to Cobalt.
//
// |event_record| The event_record associated with the event.
// |trace| The string output from TraceEvent().
static void TraceLogSuccess(const EventRecord& event_record, const std::string& trace);
const Encoder* encoder_;
local_aggregation::EventAggregator* event_aggregator_;
local_aggregation::LocalAggregation* local_aggregation_;
const ObservationWriter* observation_writer_;
const system_data::SystemDataInterface* system_data_;
};
// Implementation of EventLogger for metrics of type EVENT_OCCURRED.
class EventOccurredEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~EventOccurredEventLogger() override = 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,
const EventRecord& event_record) override;
};
// Implementation of EventLogger for metrics of type EVENT_COUNT.
class EventCountEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~EventCountEventLogger() override = 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,
const 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:
using EventLogger::EventLogger;
~IntegerPerformanceEventLogger() override = default;
private:
Encoder::Result MaybeEncodeImmediateObservation(const ReportDefinition& report,
bool may_invalidate,
EventRecord* event_record) override;
virtual const RepeatedField<uint32_t>& EventCodes(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:
using IntegerPerformanceEventLogger::IntegerPerformanceEventLogger;
~ElapsedTimeEventLogger() override = default;
private:
const RepeatedField<uint32_t>& EventCodes(const Event& event) override;
std::string Component(const Event& event) override;
int64_t IntValue(const Event& event) override;
Status ValidateEvent(const EventRecord& event_record) override;
Status MaybeUpdateLocalAggregation(const ReportDefinition& report,
const EventRecord& event_record) override;
};
// Implementation of EventLogger for metrics of type FRAME_RATE.
class FrameRateEventLogger : public IntegerPerformanceEventLogger {
public:
using IntegerPerformanceEventLogger::IntegerPerformanceEventLogger;
~FrameRateEventLogger() override = default;
private:
const RepeatedField<uint32_t>& EventCodes(const Event& event) override;
std::string Component(const Event& event) override;
int64_t IntValue(const Event& event) override;
Status ValidateEvent(const EventRecord& event_record) override;
Status MaybeUpdateLocalAggregation(const ReportDefinition& report,
const EventRecord& event_record) override;
};
// Implementation of EventLogger for metrics of type MEMORY_USAGE.
class MemoryUsageEventLogger : public IntegerPerformanceEventLogger {
public:
using IntegerPerformanceEventLogger::IntegerPerformanceEventLogger;
~MemoryUsageEventLogger() override = default;
private:
const RepeatedField<uint32_t>& EventCodes(const Event& event) override;
std::string Component(const Event& event) override;
int64_t IntValue(const Event& event) override;
Status ValidateEvent(const EventRecord& event_record) override;
Status MaybeUpdateLocalAggregation(const ReportDefinition& report,
const EventRecord& event_record) override;
};
// Implementation of EventLogger for metrics of type INT_HISTOGRAM.
class IntHistogramEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~IntHistogramEventLogger() override = 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 OCCURRENCE.
class OccurrenceEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~OccurrenceEventLogger() override = default;
private:
Status ValidateEvent(const EventRecord& event_record) override;
[[nodiscard]] bool IsOnePointOne() const override { return true; };
};
// Implementation of EventLogger for metrics of type INTEGER.
class IntegerEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~IntegerEventLogger() override = default;
private:
Status ValidateEvent(const EventRecord& event_record) override;
[[nodiscard]] bool IsOnePointOne() const override { return true; };
};
// Implementation of EventLogger for metrics of type INTEGER_HISTOGRAM.
class IntegerHistogramEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~IntegerHistogramEventLogger() override = default;
private:
Status ValidateEvent(const EventRecord& event_record) override;
[[nodiscard]] bool IsOnePointOne() const override { return true; };
};
// Implementation of EventLogger for metrics of type STRING.
class StringEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~StringEventLogger() override = default;
private:
Status ValidateEvent(const EventRecord& event_record) override;
[[nodiscard]] bool IsOnePointOne() const override { return true; };
};
// Implementation of EventLogger for metrics of type CUSTOM.
class CustomEventLogger : public EventLogger {
public:
using EventLogger::EventLogger;
~CustomEventLogger() override = default;
private:
Status ValidateEvent(const EventRecord& event_record) override;
Encoder::Result MaybeEncodeImmediateObservation(const ReportDefinition& report,
bool may_invalidate,
EventRecord* event_record) override;
};
} // namespace cobalt::logger::internal
#endif // COBALT_SRC_LOGGER_EVENT_LOGGERS_H_