OrangePi3588Media/include/utils/logger.h
2025-12-31 11:00:08 +08:00

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