/*** Copyright (C) 2022 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: SysLog.Unix.cpp Date: 2022-8-2 Author: Reece ***/ #include #include "SysLog.Unix.hpp" #include namespace Aurora::Logging::Sinks { SysLogSink::SysLogSink(const AuString &value) { ::openlog(value.c_str(), LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); } SysLogSink::~SysLogSink() { ::closelog(); } bool SysLogSink::OnMessageNonblocking(AuUInt8 level, const ConsoleMessage &msg) { return true; } void SysLogSink::OnMessageBlocking(AuUInt8 level, const ConsoleMessage &msg) { AuUInt type {}; AU_LOCK_GUARD(this->spinLock_); switch (level) { case (AuUInt8)ELogLevel::eInfo: type = LOG_INFO; break; case (AuUInt8)ELogLevel::eError: type = LOG_CRIT; break; case (AuUInt8)ELogLevel::eDebug: type = LOG_DEBUG; break; case (AuUInt8)ELogLevel::eVerbose: type = LOG_NOTICE; break; case (AuUInt8)ELogLevel::eWarn: type = LOG_WARNING; break; default: type = LOG_INFO; break; } if (this->sysCurrentType_ != type) { FlushStrings(); this->sysCurrentType_ = type; } auto a = msg.ToPersistentString(); if (this->sysStrBuffer_.size() + a.size() + 2 >= 32 * 1000) { FlushStrings(); } this->sysStrBuffer_.insert(this->sysStrBuffer_.end(), a.begin(), a.end()); this->sysStrBuffer_.insert(this->sysStrBuffer_.end(), L"\n", L"\n" + 1); } void SysLogSink::FlushStrings() { if (this->sysStrBuffer_.empty()) { return; } this->sysCompleteLineBuffer_.push_back(AuMakeTuple(this->sysCurrentType_, AuMove(this->sysStrBuffer_))); this->sysStrBuffer_.clear(); this->sysStrBuffer_.reserve(15 * 1024); } void SysLogSink::OnFlush() { AU_LOCK_GUARD(this->spinLock_); FlushStrings(); for (auto &[level, message] : this->sysCompleteLineBuffer_) { ::syslog(level, "%s", message.c_str()); } this->sysCompleteLineBuffer_.clear(); } IBasicSink *NewOSNamedEventDirectorySinkNew(const AuString &name) { try { return _new SysLogSink(name); } catch (...) { return {}; } } void NewOSNamedEventDirectorySinkRelease(IBasicSink *sink) { AuSafeDelete(sink); } }