blob: a7b8ae9ca626a03df798acf2bbd8363b4ced4b41 [file] [log] [blame]
// Copyright 2019 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_UNDATED_EVENT_MANAGER_H_
#define COBALT_SRC_LOGGER_UNDATED_EVENT_MANAGER_H_
#include <queue>
#include <string>
#include "src/lib/util/clock.h"
#include "src/local_aggregation/event_aggregator.h"
#include "src/local_aggregation_1_1/local_aggregation.h"
#include "src/logger/encoder.h"
#include "src/logger/internal_metrics.h"
#include "src/logger/logger_interface.h"
#include "src/logger/observation_writer.h"
#include "src/logger/project_context.h"
namespace cobalt::logger {
// A container for an EventRecord and the time/context when it was logged.
struct SavedEventRecord {
// The steady clock time when the event occurred.
const std::chrono::steady_clock::time_point monotonic_time;
// The event that occurred.
std::unique_ptr<EventRecord> event_record;
};
constexpr int32_t kDefaultMaxSavedEvents = 10000;
// UndatedEventManager manages events without timestamps while the clock is inaccurate.
//
// While the system clock is unreliable, Cobalt Loggers will pass incoming Events to the
// UndatedEventManager for interim storage. No locally aggregated observations will be generated
// during this time. Buffered events will be stored in memory with the monotonic (steady) time they
// occurred at, and dropped if a reboot occurs before a clock sync or if a storage quota is reached.
//
// When the UndatedEventManager is notified that the system clock is reliable, it will use the
// current offset between the (now accurate) system clock and the monotonic (steady) clock to assign
// a date to each buffered event. The events will then moved back into the main logging path, to be
// either aggregated on-device or formed into observations.
//
// There should be one instance of UndatedEventManager across all Loggers.
class UndatedEventManager {
public:
// Constructor
//
// The non-optional parameters are needed to be able to construct EventLoggers.
// See the EventLogger constructor for their use.
//
// |max_saved_events| The maximum number of saved events. When this limit is reached, old events
// are dropped to make room for new events.
UndatedEventManager(const Encoder& encoder, local_aggregation::EventAggregator& event_aggregator,
local_aggregation::LocalAggregation* local_aggregation,
ObservationWriter* observation_writer,
system_data::SystemDataInterface* system_data,
util::CivilTimeConverterInterface* civil_time_converter,
int32_t max_saved_events = kDefaultMaxSavedEvents);
// Saves the fact that an event has occurred.
//
// |event_record| The event that occurred.
Status Save(std::unique_ptr<EventRecord> event_record);
// Flush all the saved events now that the system clock is accurate.
//
// |system_clock| The system clock that can now be used to log events.
// |internal_metrics| A (possible nullptr) instance of InternalMetrics.
Status Flush(util::SystemClockInterface* system_clock, InternalMetrics* internal_metrics);
// Get the current number of events that are being saved.
int NumSavedEvents() const;
private:
friend class UndatedEventManagerTest; // for testing
void SetSteadyClock(util::SteadyClockInterface* steady_clock) {
steady_clock_.reset(steady_clock);
}
Status FlushSavedRecord(std::unique_ptr<SavedEventRecord> saved_record,
const std::chrono::system_clock::time_point& reference_system_time,
const std::chrono::steady_clock::time_point& reference_monotonic_time);
// Used only to construct EventLogger instances.
const Encoder& encoder_;
local_aggregation::EventAggregator& event_aggregator_;
local_aggregation::LocalAggregation* local_aggregation_;
const ObservationWriter* observation_writer_;
const system_data::SystemDataInterface* system_data_;
util::CivilTimeConverterInterface* civil_time_converter_;
size_t max_saved_events_;
// A monotonic (steady) clock for tracking event time when the system clock is inaccurate.
std::unique_ptr<util::SteadyClockInterface> steady_clock_;
// Guards access to saved_records_ and the other related fields.
struct SavedRecordsFields {
// FIFO queue of SavedEventRecords to process once the clock is accurate.
std::deque<std::unique_ptr<SavedEventRecord>> saved_records_;
// Mapping of identifiers of ProjectContexts to the stats for them.
std::map<std::pair<uint32_t, uint32_t>, int64_t> num_events_cached_;
std::map<std::pair<uint32_t, uint32_t>, int64_t> num_events_dropped_;
// Whether Flush() has already been called on this object.
bool flushed = false;
// If |flushed_| is true, these will contain the reference clock values at the time of the
// flush.
std::chrono::system_clock::time_point reference_system_time_;
std::chrono::steady_clock::time_point reference_monotonic_time_;
};
util::RWProtectedFields<SavedRecordsFields> protected_saved_records_fields_;
};
} // namespace cobalt::logger
#endif // COBALT_SRC_LOGGER_UNDATED_EVENT_MANAGER_H_