26#include <fmt/format.h>
27#include <fmt/compile.h>
36#include <condition_variable>
49#include <sys/syscall.h>
54#define APP_NAME "libjami"
58#define END_COLOR "\033[0m"
61#define RED "\033[22;31m"
62#define YELLOW "\033[01;33m"
63#define CYAN "\033[22;36m"
65#define FOREGROUND_WHITE 0x000f
66#define RED FOREGROUND_RED + 0x0008
67#define YELLOW FOREGROUND_RED + FOREGROUND_GREEN + 0x0008
68#define CYAN FOREGROUND_BLUE + FOREGROUND_GREEN + 0x0008
69#define LIGHT_GREEN FOREGROUND_GREEN + 0x0008
76static constexpr auto ENDL =
'\n';
87 return "unknown (too big to display)";
90 return "unknown (invalid error number)";
113static constexpr std::string_view
117 size_t pos = path.find_last_of(
"/\\");
118 if (
pos != std::string_view::npos)
119 return path.substr(
pos + 1);
130 auto tid = std::this_thread::get_id();
144 return fmt::format(
FMT_COMPILE(
"[{: >3d}.{:0<3d}|{: >4}|{: <24s}:{: <4d}] "),
171 if ((
size_t) size >=
ret.size()) {
172 ret.resize(size + 1);
187 Msg(
int level, std::string_view file,
unsigned line,
bool linefeed, std::string_view tag, std::string&& message)
197 Msg(
int level, std::string_view file,
unsigned line,
bool linefeed, std::string_view tag,
const char* fmt, va_list ap)
264 switch (
msg.level_) {
286 if (!
msg.tag_.empty())
305 switch (
msg.level_) {
323 if (!
msg.tag_.empty())
362 (
int)
msg.tag_.size(),
364 (
int)
msg.payload_.size(),
365 msg.payload_.data());
377 auto message =
msg.header_ +
msg.payload_;
389 std::lock_guard
lk(mtx_);
393 if (
not path.empty()) {
394 file_.open(path, std::ofstream::out | std::ofstream::app);
406 std::lock_guard
lk(mtx_);
407 if (file_.is_open()) {
408 file_ <<
msg.header_ <<
msg.tag_ <<
msg.payload_;
432 std::lock_guard
lk(mtx_);
435 if (!recycleQueue_.empty()) {
436 msgQueue_.splice(msgQueue_.end(), recycleQueue_, recycleQueue_.begin());
437 msgQueue_.back() = std::move(
msg);
439 msgQueue_.emplace_back(std::move(
msg));
448 std::lock_guard
lk(mtx_);
454 if (thread_.joinable())
456 recycleQueue_.splice(recycleQueue_.end(), std::move(msgQueue_));
521 std::lock_guard
lk(mtx_);
522 if (
en && !running_) {
524 thread_ = std::thread(&LogDispatcher::loop,
this);
525 }
else if (!
en && running_) {
527 t = std::move(thread_);
533 std::lock_guard
lk(mtx_);
534 recycleQueue_.splice(recycleQueue_.end(), std::move(msgQueue_));
540 std::unique_lock
lk(mtx_);
542 cv_.wait(
lk, [
this] {
return not msgQueue_.empty()
or not running_; });
543 auto local = std::move(msgQueue_);
559 if (recycleQueue_.size() < 128)
560 recycleQueue_.splice(recycleQueue_.end(),
local);
565 std::condition_variable cv_;
566 std::list<Logger::Msg> msgQueue_;
567 std::list<Logger::Msg> recycleQueue_;
568 bool running_ {
false};
573Logger::setConsoleLog(
bool en)
579Logger::setSysLog(
bool en)
585Logger::setMonitorLog(
bool en)
591Logger::setFileLog(
const std::string& path)
608Logger::setDebugMode(
bool enable)
614Logger::debugEnabled()
654 Logger::setConsoleLog(
false);
void consume(const Logger::Msg &msg) override
void printLogImpl(const Logger::Msg &msg, bool with_color)
void consume(const Logger::Msg &msg) override
void setFile(const std::string &path)
static LogDispatcher & instance()
void enableConsoleLog(bool en)
void enableSysLog(bool en)
void enableMonitorLog(bool en)
void log(Logger::Msg &&msg)
void enableFileLog(const std::string &path)
std::atomic_bool enabled_
virtual ~Handler()=default
virtual void consume(const Msg &msg)=0
virtual void enable(bool en)
static LIBJAMI_PUBLIC void static LIBJAMI_PUBLIC void vlog(int level, const char *file, unsigned line, bool linefeed, const char *fmt, va_list)
Printf fashion logging (using va_list parameters)
void consume(const Logger::Msg &msg) override
void consume(const Logger::Msg &msg) override
static std::atomic_bool debugEnabled_
static std::string formatPrintfArgs(const char *format, va_list ap)
void emitSignal(Args... args)
void strErr()
Thread-safe function to print the stringified contents of errno.
static const char * check_error(int result, char *buffer)
static constexpr auto ENDL
static constexpr std::string_view stripDirName(std::string_view path)
static std::string formatHeader(std::string_view file, unsigned line)
Msg(int level, std::string_view file, unsigned line, bool linefeed, std::string_view tag, const char *fmt, va_list ap)
Msg & operator=(Msg &&other)=default
Msg(int level, std::string_view file, unsigned line, bool linefeed, std::string_view tag, std::string &&message)
#define strerror_r(errno, buf, len)
void syslog(int, const char *,...)
void openlog(const char *, int, int)