100 lines
2.7 KiB
C++
100 lines
2.7 KiB
C++
#pragma once
|
|
|
|
#include <chrono>
|
|
#include <cstddef>
|
|
#include <deque>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <mutex>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
namespace rk3588 {
|
|
|
|
enum class LogLevel { Debug, Info, Warn, Error };
|
|
|
|
class Logger {
|
|
public:
|
|
static Logger& Instance() {
|
|
static Logger inst;
|
|
return inst;
|
|
}
|
|
|
|
void SetMaxLines(size_t n) {
|
|
std::lock_guard<std::mutex> lock(mu_);
|
|
max_lines_ = (n == 0) ? 1 : n;
|
|
TrimLocked();
|
|
}
|
|
|
|
void Log(LogLevel lvl, const std::string& msg) {
|
|
const std::string line = FormatLine(lvl, msg);
|
|
{
|
|
std::lock_guard<std::mutex> lock(mu_);
|
|
lines_.push_back(line);
|
|
TrimLocked();
|
|
}
|
|
|
|
// Keep existing stdout/stderr logging style for easy board-side debugging.
|
|
if (lvl == LogLevel::Warn || lvl == LogLevel::Error) {
|
|
std::cerr << line << "\n";
|
|
} else {
|
|
std::cout << line << "\n";
|
|
}
|
|
}
|
|
|
|
std::vector<std::string> RecentLines(size_t limit) const {
|
|
std::lock_guard<std::mutex> lock(mu_);
|
|
if (limit == 0) return {};
|
|
if (limit > lines_.size()) limit = lines_.size();
|
|
std::vector<std::string> out;
|
|
out.reserve(limit);
|
|
const size_t start = lines_.size() - limit;
|
|
for (size_t i = start; i < lines_.size(); ++i) {
|
|
out.push_back(lines_[i]);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
private:
|
|
Logger() = default;
|
|
|
|
static const char* LevelText(LogLevel lvl) {
|
|
switch (lvl) {
|
|
case LogLevel::Debug: return "D";
|
|
case LogLevel::Info: return "I";
|
|
case LogLevel::Warn: return "W";
|
|
case LogLevel::Error: return "E";
|
|
}
|
|
return "I";
|
|
}
|
|
|
|
static std::string FormatLine(LogLevel lvl, const std::string& msg) {
|
|
using namespace std::chrono;
|
|
const auto now = system_clock::now();
|
|
const auto ms = duration_cast<milliseconds>(now.time_since_epoch()).count();
|
|
std::ostringstream oss;
|
|
oss << "[" << ms << "]";
|
|
oss << "[" << LevelText(lvl) << "] ";
|
|
oss << msg;
|
|
return oss.str();
|
|
}
|
|
|
|
void TrimLocked() {
|
|
while (lines_.size() > max_lines_) {
|
|
lines_.pop_front();
|
|
}
|
|
}
|
|
|
|
mutable std::mutex mu_;
|
|
std::deque<std::string> lines_;
|
|
size_t max_lines_ = 2000;
|
|
};
|
|
|
|
inline void LogDebug(const std::string& msg) { Logger::Instance().Log(LogLevel::Debug, msg); }
|
|
inline void LogInfo(const std::string& msg) { Logger::Instance().Log(LogLevel::Info, msg); }
|
|
inline void LogWarn(const std::string& msg) { Logger::Instance().Log(LogLevel::Warn, msg); }
|
|
inline void LogError(const std::string& msg) { Logger::Instance().Log(LogLevel::Error, msg); }
|
|
|
|
} // namespace rk3588
|