blob: af681770b3a743ba047cf26f27f95ebe290a367f [file] [edit]
#ifndef THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SEL_COLLECTOR_H_
#define THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SEL_COLLECTOR_H_
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <memory>
#include <ostream>
#include <string>
#include <vector>
#include "absl/base/thread_annotations.h"
#include "absl/container/btree_map.h"
#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/synchronization/mutex.h"
#include "time/clock.h"
#include "gbmc_sel_sub.h"
#include "nlohmann/json.hpp"
#include "tlbmc/collector/collector.h"
#include "sel_config.pb.h"
#include "tlbmc/scheduler/scheduler.h"
namespace milotic_tlbmc {
struct SelThreadManager {
explicit SelThreadManager(ecclesia::Clock* clock)
: task_scheduler(std::make_unique<TaskScheduler>(clock)) {}
std::unique_ptr<TaskScheduler> task_scheduler;
std::vector<int> task_ids;
};
// SelCollector is a collector that collects SEL events from the gbmc SEL
// framework and writes them to a file. The file is a jsonl file that contains a
// list of json objects. The file is rotated every chunk_size events or when the
// file is full. The file is named sel_<start_id>.<suffix> where start_id is
// the id of the first event in the file and suffix is the suffix of the file.
// The file is stored in the sel_save_path directory. The collector will recover
// existing SEL files from the directory on creation.
class SelCollector : public Collector {
public:
struct Params {
ecclesia::Clock* clock = ecclesia::Clock::RealClock();
SelConfig config;
};
// Creates a SelCollector with the default subscriber.
static absl::StatusOr<std::unique_ptr<SelCollector>> Create(
const Params& params);
// Creates a SelCollector with a provided subscriber.
static absl::StatusOr<std::unique_ptr<SelCollector>> Create(
const Params& params,
std::unique_ptr<gbmc_sel_framework::GbmcSelSubscriber> subscriber);
~SelCollector() override;
// Starts the default subscriber to collect SEL events. Returns error if the
// subscriber fails to start or recover existing SEL files fails.
virtual absl::Status StartDefaultSubscriber();
void Stop();
// Returns a list of SEL entries in the forward direction starting from the
// given ID. The list is sorted by ID in ascending order.
virtual std::vector<nlohmann::json> GetSelEntriesForward(
uint64_t start_id, size_t max_count) const;
// Returns a list of SEL entries in the backward direction starting from the
// given ID. The list is sorted by ID in descending order.
virtual std::vector<nlohmann::json> GetSelEntriesBackward(
uint64_t start_id, size_t max_count) const;
// Returns a list of up to max_count SEL entries in the backward direction
// starting from the latest ID. The list is sorted by ID in descending order.
virtual std::vector<nlohmann::json> GetLatestSelEntries(
size_t max_count) const;
// Dumps SEL entries starting from the given ID to the output stream.
// The output is in the same context as the SEL files.
virtual void DumpSelEntriesRaw(uint64_t start_id, std::ostream& os) const;
nlohmann::json ToJson() const override;
nlohmann::json GetSchedulerStats() const override;
protected:
SelCollector() = default;
private:
SelCollector(
const SelConfig& config, std::unique_ptr<SelThreadManager> thread_manager,
std::unique_ptr<gbmc_sel_framework::GbmcSelSubscriber> subscriber);
void DefaultSubscriberTask();
absl::Status RecoverExistingSelFiles();
void RotateSelFile();
void WriteSelToFile(
const absl::flat_hash_map<std::string, std::string>& event);
SelConfig config_;
std::unique_ptr<SelThreadManager> thread_manager_;
// The default subscriber is used to collect SEL events from the gbmc SEL
// framework, with subscribing all SEL events in this boot without history.
// It is created by default when the SelCollector is created.
std::unique_ptr<gbmc_sel_framework::GbmcSelSubscriber> default_subscriber_;
std::ofstream current_sel_file_;
// The number of SEL events written to the current SEL file.
int current_sel_file_count_ = 0;
// The ID of the first SEL event in the current SEL file.
uint64_t current_sel_file_start_id_ = 0;
mutable absl::Mutex mutex_;
// Map of SEL file start ID to file path.
// Use btree_map to keep file IDs in order. This allows quickly finding
// the file containing a specific SEL ID via binary search (e.g., given an ID,
// find the file with the greatest start_id less than or equal to it), and
// deleting the oldest files when rotating.
absl::btree_map<uint64_t, std::string> existing_sel_files_
ABSL_GUARDED_BY(mutex_);
};
class EmptySelCollector final : public SelCollector {
public:
static std::unique_ptr<EmptySelCollector> Create();
absl::Status StartDefaultSubscriber() override;
std::vector<nlohmann::json> GetSelEntriesForward(
uint64_t start_id, size_t max_count) const override;
std::vector<nlohmann::json> GetSelEntriesBackward(
uint64_t start_id, size_t max_count) const override;
std::vector<nlohmann::json> GetLatestSelEntries(
size_t max_count) const override;
void DumpSelEntriesRaw(uint64_t start_id, std::ostream& os) const override;
nlohmann::json ToJson() const override;
nlohmann::json GetSchedulerStats() const override;
};
} // namespace milotic_tlbmc
#endif // THIRD_PARTY_MILOTIC_EXTERNAL_CC_TLBMC_COLLECTOR_SEL_COLLECTOR_H_