[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];
|
||||
|
||||
|
||||
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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue