blob: 97aad8461d2dac45f26193cf5366f7a8bbefb437 [file] [log] [blame]
#pragma once
#include "config.h"
#include <cstdint>
#include <fstream>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <vector>
namespace boot_time_monitor
{
const std::string kBTMonitorDir = bootTimeDataDir;
const std::string kCheckpointFile = "checkpoints.csv";
const std::string kDurationFile = "durations.csv";
const std::string kCompletedSuffix = ".completed";
struct Checkpoint
{
std::string name;
int64_t wallTime;
int64_t monoTime;
Checkpoint(std::string name, int64_t wallTime, int64_t monoTime) :
name(std::move(name)), wallTime(wallTime), monoTime(monoTime)
{}
};
struct Duration
{
std::string name;
int64_t duration;
Duration(std::string name, int64_t duration) :
name(std::move(name)), duration(duration)
{}
};
/**
* An interface class for the Util APIs
*/
class UtilIface
{
public:
virtual ~UtilIface() = default;
/**
* Read uptime from `/proc/uptime`
*
* @return Current uptime in milliseconds
*/
virtual std::optional<int64_t> getUpTimeInMs() = 0;
/**
* Get system time and covert it to the epoch time in milliseconds
*
* @return Current epoch time in milliseconds
*/
virtual int64_t getWallTimeInMs() = 0;
/**
* Check if the input name is valid. This can be used to check both
* checkpoint name and duration name
*
* @return true if the input name is valid
*/
virtual bool isValidName(std::string_view name) = 0;
/**
* Get full file path of checkpoint record for a specific node
*
* @param[in] nodeName - Node name
* @param[in] wantCompleted - Want `kCompletedSuffix` in the file path or
* not
* @return Full file path
*/
virtual std::string getCPPath(std::string_view nodeName,
bool wantCompleted) = 0;
/**
* Get full file path of duration record for a specific node
*
* @param[in] nodeName - Node name
* @param[in] wantCompleted - Want `kCompletedSuffix` in the file path or
* not
* @return Full file path
*/
virtual std::string getDurPath(std::string_view nodeName,
bool wantCompleted) = 0;
/**
* Read 4 bytes data from target address
*
* @param[in] target - Target address
* @return 4 bytes data from the target address or std::nullopt if any error
* happens during `readMem4Bytes`
*/
virtual std::optional<uint32_t> readMem4Bytes(uint32_t target) = 0;
};
/**
* Utility implementation class
*/
class Util : public UtilIface
{
public:
std::optional<int64_t> getUpTimeInMs() override;
int64_t getWallTimeInMs() override;
bool isValidName(std::string_view name) override;
std::string getCPPath(std::string_view nodeName,
bool wantCompleted) override;
std::string getDurPath(std::string_view nodeName,
bool wantCompleted) override;
std::optional<uint32_t> readMem4Bytes(uint32_t target) override;
};
/**
* An interface class for the FileUtil APIs
*/
class FileUtilIface
{
public:
virtual ~FileUtilIface() = default;
/**
* Add a new checkpoint record in file
*
* @param[in] name - Checkpoint name
* @param[in] wallTimeInMs - Current epoch time in milliseconds
* @param[in] monoTimeInMs - Current monotonic time in milliseconds
* (Typically it's from `/proc/uptime`)
*/
virtual void addCheckpoint(std::string_view name, int64_t wallTimeInMs,
int64_t monoTimeInMs) = 0;
/**
* Add a new duration record in file
*
* @param[in] name - Duration name
* @param[in] durationInMs - Duration in milliseconds
*/
virtual void addDuration(std::string_view name, int64_t durationInMs) = 0;
/**
* Close current file and rename it with suffix `kCompletedSuffix`
*/
virtual void completeCurrent() = 0;
/**
* Load checkpoints from file
*
* @param[in] loadCompleted - Load file with `kCompletedSuffix` or not
* @return Smart pointer of vector of checkpoints
*/
virtual std::unique_ptr<std::vector<Checkpoint>>
loadCheckpoints(bool loadCompleted) = 0;
/**
* Load durations from file
*
* @param[in] loadCompleted - Load file with `kCompletedSuffix` or not
* @return Smart pointer of vector of durations
*/
virtual std::unique_ptr<std::vector<Duration>>
loadDurations(bool loadCompleted) = 0;
/**
* Is current file empty
*
* @return true if file is empty
*/
virtual bool isEmpty() = 0;
};
/**
* FileUtil implementation class
*/
class FileUtil : public FileUtilIface
{
public:
explicit FileUtil(std::string_view filename);
void addCheckpoint(std::string_view name, int64_t wallTimeInMs,
int64_t monoTimeInMs) override;
void addDuration(std::string_view name, int64_t durationInMs) override;
void completeCurrent() override;
std::unique_ptr<std::vector<Checkpoint>>
loadCheckpoints(bool loadCompleted) override;
std::unique_ptr<std::vector<Duration>>
loadDurations(bool loadCompleted) override;
bool isEmpty() override;
protected:
std::string filename;
std::unique_ptr<std::ofstream> ofs;
};
} // namespace boot_time_monitor