[Base] Add support for multiple log sinks in Logger

This commit is contained in:
Satori 2020-09-06 19:20:59 +01:00 committed by Rick Gibbed
parent 36466231d0
commit 42b10209fe
2 changed files with 72 additions and 23 deletions

View File

@ -66,30 +66,30 @@ struct LogLine {
thread_local char thread_log_buffer_[64 * 1024];
void FileLogSink::Write(const char* buf, size_t size) {
if (file_) {
fwrite(buf, 1, size, file_);
}
}
void FileLogSink::Flush() {
if (file_) {
fflush(file_);
}
}
class Logger {
public:
explicit Logger(const std::string_view app_name)
: file_(nullptr),
running_(true),
:
wait_strategy_(),
claim_strategy_(kBlockCount, wait_strategy_),
consumed_(wait_strategy_) {
consumed_(wait_strategy_),
running_(true) {
claim_strategy_.add_claim_barrier(consumed_);
if (cvars::log_file.empty()) {
// Default to app name.
auto file_name = fmt::format("{}.log", app_name);
auto file_path = std::filesystem::path(file_name);
xe::filesystem::CreateParentFolder(file_path);
file_ = xe::filesystem::OpenFile(file_path, "wt");
} else {
if (cvars::log_file == "stdout") {
file_ = stdout;
} else {
xe::filesystem::CreateParentFolder(cvars::log_file);
file_ = xe::filesystem::OpenFile(cvars::log_file, "wt");
}
}
write_thread_ =
xe::threading::Thread::Create({}, [this]() { WriteThread(); });
@ -99,8 +99,10 @@ class Logger {
~Logger() {
running_ = false;
xe::threading::Wait(write_thread_.get(), true);
fflush(file_);
fclose(file_);
}
void AddLogSink(std::unique_ptr<LogSink> sink) {
sinks_.push_back(std::move(sink));
}
private:
@ -126,14 +128,14 @@ class Logger {
dp::multi_threaded_claim_strategy<dp::spin_wait_strategy> claim_strategy_;
dp::sequence_barrier<dp::spin_wait_strategy> consumed_;
FILE* file_;
std::vector<std::unique_ptr<LogSink>> sinks_;
std::atomic<bool> running_;
std::unique_ptr<xe::threading::Thread> write_thread_;
void Write(const char* buf, size_t size) {
if (file_) {
fwrite(buf, 1, size, file_);
for (const auto& sink : sinks_) {
sink->Write(buf, size);
}
if (cvars::log_to_debugprint) {
debugging::DebugPrint("{}", std::string_view(buf, size));
@ -246,7 +248,9 @@ class Logger {
desired_count = 1;
if (cvars::flush_log) {
fflush(file_);
for (const auto& sink : sinks_) {
sink->Flush();
}
}
idle_loops = 0;
@ -291,6 +295,26 @@ class Logger {
void InitializeLogging(const std::string_view app_name) {
auto mem = memory::AlignedAlloc<Logger>(0x10);
logger_ = new (mem) Logger(app_name);
FILE* file = nullptr;
if (cvars::log_file.empty()) {
// Default to app name.
auto file_name = fmt::format("{}.log", app_name);
auto file_path = std::filesystem::path(file_name);
xe::filesystem::CreateParentFolder(file_path);
file = xe::filesystem::OpenFile(file_path, "wt");
} else {
if (cvars::log_file == "stdout") {
file = stdout;
} else {
xe::filesystem::CreateParentFolder(cvars::log_file);
file = xe::filesystem::OpenFile(cvars::log_file, "wt");
}
}
auto sink = std::make_unique<FileLogSink>(file);
logger_->AddLogSink(std::move(sink));
}
void ShutdownLogging() {

View File

@ -34,6 +34,31 @@ enum class LogLevel {
Trace,
};
class LogSink {
public:
virtual ~LogSink() = default;
virtual void Write(const char* buf, size_t size) = 0;
virtual void Flush() = 0;
};
class FileLogSink final : public LogSink {
public:
explicit FileLogSink(FILE* file) : file_(file) {}
virtual ~FileLogSink() {
if (file_) {
fflush(file_);
fclose(file_);
}
}
void Write(const char* buf, size_t size) override;
void Flush() override;
private:
FILE* file_;
};
// Initializes the logging system and any outputs requested.
// Must be called on startup.
void InitializeLogging(const std::string_view app_name);