Add foundation logging facade
This commit is contained in:
93
src/foundation/log.cpp
Normal file
93
src/foundation/log.cpp
Normal file
@@ -0,0 +1,93 @@
|
||||
#include "foundation/log.h"
|
||||
|
||||
namespace pp::foundation {
|
||||
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] bool should_write(LogLevel level, LogLevel min_level) noexcept
|
||||
{
|
||||
return static_cast<std::uint8_t>(level) >= static_cast<std::uint8_t>(min_level);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Logger::Logger(ILogSink& sink) noexcept
|
||||
: sink_(&sink)
|
||||
{
|
||||
}
|
||||
|
||||
void Logger::set_min_level(LogLevel level) noexcept
|
||||
{
|
||||
min_level_ = level;
|
||||
}
|
||||
|
||||
LogLevel Logger::min_level() const noexcept
|
||||
{
|
||||
return min_level_;
|
||||
}
|
||||
|
||||
Status Logger::write(
|
||||
LogLevel level,
|
||||
std::string_view component,
|
||||
std::string_view message,
|
||||
std::uint64_t frame_id,
|
||||
std::uint64_t stroke_id,
|
||||
std::uint64_t thread_id) noexcept
|
||||
{
|
||||
if (component.empty()) {
|
||||
return Status::invalid_argument("log component must not be empty");
|
||||
}
|
||||
|
||||
if (message.empty()) {
|
||||
return Status::invalid_argument("log message must not be empty");
|
||||
}
|
||||
|
||||
if (!should_write(level, min_level_)) {
|
||||
return Status::success();
|
||||
}
|
||||
|
||||
sink_->write(LogRecord {
|
||||
.level = level,
|
||||
.component = std::string(component),
|
||||
.message = std::string(message),
|
||||
.frame_id = frame_id,
|
||||
.stroke_id = stroke_id,
|
||||
.thread_id = thread_id,
|
||||
});
|
||||
return Status::success();
|
||||
}
|
||||
|
||||
void MemoryLogSink::write(const LogRecord& record) noexcept
|
||||
{
|
||||
records_.push_back(record);
|
||||
}
|
||||
|
||||
const std::vector<LogRecord>& MemoryLogSink::records() const noexcept
|
||||
{
|
||||
return records_;
|
||||
}
|
||||
|
||||
void MemoryLogSink::clear() noexcept
|
||||
{
|
||||
records_.clear();
|
||||
}
|
||||
|
||||
const char* log_level_name(LogLevel level) noexcept
|
||||
{
|
||||
switch (level) {
|
||||
case LogLevel::trace:
|
||||
return "trace";
|
||||
case LogLevel::debug:
|
||||
return "debug";
|
||||
case LogLevel::info:
|
||||
return "info";
|
||||
case LogLevel::warning:
|
||||
return "warning";
|
||||
case LogLevel::error:
|
||||
return "error";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
}
|
||||
67
src/foundation/log.h
Normal file
67
src/foundation/log.h
Normal file
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include "foundation/result.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
namespace pp::foundation {
|
||||
|
||||
enum class LogLevel : std::uint8_t {
|
||||
trace,
|
||||
debug,
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
};
|
||||
|
||||
struct LogRecord {
|
||||
LogLevel level = LogLevel::info;
|
||||
std::string component;
|
||||
std::string message;
|
||||
std::uint64_t frame_id = 0;
|
||||
std::uint64_t stroke_id = 0;
|
||||
std::uint64_t thread_id = 0;
|
||||
};
|
||||
|
||||
class ILogSink {
|
||||
public:
|
||||
virtual ~ILogSink() = default;
|
||||
virtual void write(const LogRecord& record) noexcept = 0;
|
||||
};
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
explicit Logger(ILogSink& sink) noexcept;
|
||||
|
||||
void set_min_level(LogLevel level) noexcept;
|
||||
[[nodiscard]] LogLevel min_level() const noexcept;
|
||||
|
||||
[[nodiscard]] Status write(
|
||||
LogLevel level,
|
||||
std::string_view component,
|
||||
std::string_view message,
|
||||
std::uint64_t frame_id = 0,
|
||||
std::uint64_t stroke_id = 0,
|
||||
std::uint64_t thread_id = 0) noexcept;
|
||||
|
||||
private:
|
||||
ILogSink* sink_ = nullptr;
|
||||
LogLevel min_level_ = LogLevel::trace;
|
||||
};
|
||||
|
||||
class MemoryLogSink final : public ILogSink {
|
||||
public:
|
||||
void write(const LogRecord& record) noexcept override;
|
||||
[[nodiscard]] const std::vector<LogRecord>& records() const noexcept;
|
||||
void clear() noexcept;
|
||||
|
||||
private:
|
||||
std::vector<LogRecord> records_;
|
||||
};
|
||||
|
||||
[[nodiscard]] const char* log_level_name(LogLevel level) noexcept;
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user