[Base] Add support for multiple log sinks in Logger
This commit is contained in:
parent
36466231d0
commit
42b10209fe
|
@ -66,30 +66,30 @@ struct LogLine {
|
||||||
|
|
||||||
thread_local char thread_log_buffer_[64 * 1024];
|
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 {
|
class Logger {
|
||||||
public:
|
public:
|
||||||
explicit Logger(const std::string_view app_name)
|
explicit Logger(const std::string_view app_name)
|
||||||
: file_(nullptr),
|
:
|
||||||
running_(true),
|
|
||||||
wait_strategy_(),
|
wait_strategy_(),
|
||||||
claim_strategy_(kBlockCount, wait_strategy_),
|
claim_strategy_(kBlockCount, wait_strategy_),
|
||||||
consumed_(wait_strategy_) {
|
consumed_(wait_strategy_),
|
||||||
|
running_(true) {
|
||||||
claim_strategy_.add_claim_barrier(consumed_);
|
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_ =
|
write_thread_ =
|
||||||
xe::threading::Thread::Create({}, [this]() { WriteThread(); });
|
xe::threading::Thread::Create({}, [this]() { WriteThread(); });
|
||||||
|
@ -99,8 +99,10 @@ class Logger {
|
||||||
~Logger() {
|
~Logger() {
|
||||||
running_ = false;
|
running_ = false;
|
||||||
xe::threading::Wait(write_thread_.get(), true);
|
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:
|
private:
|
||||||
|
@ -126,14 +128,14 @@ class Logger {
|
||||||
dp::multi_threaded_claim_strategy<dp::spin_wait_strategy> claim_strategy_;
|
dp::multi_threaded_claim_strategy<dp::spin_wait_strategy> claim_strategy_;
|
||||||
dp::sequence_barrier<dp::spin_wait_strategy> consumed_;
|
dp::sequence_barrier<dp::spin_wait_strategy> consumed_;
|
||||||
|
|
||||||
FILE* file_;
|
std::vector<std::unique_ptr<LogSink>> sinks_;
|
||||||
|
|
||||||
std::atomic<bool> running_;
|
std::atomic<bool> running_;
|
||||||
std::unique_ptr<xe::threading::Thread> write_thread_;
|
std::unique_ptr<xe::threading::Thread> write_thread_;
|
||||||
|
|
||||||
void Write(const char* buf, size_t size) {
|
void Write(const char* buf, size_t size) {
|
||||||
if (file_) {
|
for (const auto& sink : sinks_) {
|
||||||
fwrite(buf, 1, size, file_);
|
sink->Write(buf, size);
|
||||||
}
|
}
|
||||||
if (cvars::log_to_debugprint) {
|
if (cvars::log_to_debugprint) {
|
||||||
debugging::DebugPrint("{}", std::string_view(buf, size));
|
debugging::DebugPrint("{}", std::string_view(buf, size));
|
||||||
|
@ -246,7 +248,9 @@ class Logger {
|
||||||
desired_count = 1;
|
desired_count = 1;
|
||||||
|
|
||||||
if (cvars::flush_log) {
|
if (cvars::flush_log) {
|
||||||
fflush(file_);
|
for (const auto& sink : sinks_) {
|
||||||
|
sink->Flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idle_loops = 0;
|
idle_loops = 0;
|
||||||
|
@ -291,6 +295,26 @@ class Logger {
|
||||||
void InitializeLogging(const std::string_view app_name) {
|
void InitializeLogging(const std::string_view app_name) {
|
||||||
auto mem = memory::AlignedAlloc<Logger>(0x10);
|
auto mem = memory::AlignedAlloc<Logger>(0x10);
|
||||||
logger_ = new (mem) Logger(app_name);
|
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() {
|
void ShutdownLogging() {
|
||||||
|
|
|
@ -34,6 +34,31 @@ enum class LogLevel {
|
||||||
Trace,
|
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.
|
// Initializes the logging system and any outputs requested.
|
||||||
// Must be called on startup.
|
// Must be called on startup.
|
||||||
void InitializeLogging(const std::string_view app_name);
|
void InitializeLogging(const std::string_view app_name);
|
||||||
|
|
Loading…
Reference in New Issue