blob: f60940bf68a6de4edc33f8e043ccbf4e63e1d0c4 [file] [edit]
// 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 <deque>
#include "src/local_aggregation/local_aggregation.h"
#include "src/logger/internal_metrics.h"
#include "src/logger/observation_writer.h"
#include "src/public/lib/clock_interfaces.h"
#include "src/public/lib/compat/clock.h"
namespace cobalt::logger {
// A container for an EventRecord and the time/context when it was logged.
struct SavedEventRecord {
// The boot time when the event occurred.
const util::compat::boot_clock::time_point boot_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 boot 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 boot 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(local_aggregation::LocalAggregation& local_aggregation,
ObservationWriter& observation_writer,
system_data::SystemDataInterface& system_data,
util::CivilTimeConverterInterface& civil_time_converter,
std::unique_ptr<util::BootClockInterface> boot_clock,
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
Status FlushSavedRecord(std::unique_ptr<SavedEventRecord> saved_record,
const std::chrono::system_clock::time_point& reference_system_time,
const util::compat::boot_clock::time_point& reference_boot_time);
// Used only to construct EventLogger instances.
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 boot clock for tracking event time when the system clock is inaccurate.
std::unique_ptr<util::BootClockInterface> boot_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_;
util::compat::boot_clock::time_point reference_boot_time_;
};
util::RWProtectedFields<SavedRecordsFields> protected_saved_records_fields_;
};
} // namespace cobalt::logger
#endif // COBALT_SRC_LOGGER_UNDATED_EVENT_MANAGER_H_