1 #pragma once 2 3 #include <cstdio> 4 #include <map> 5 #include <string> 6 #include <thread> 7 #include <utility> 8 9 #include "common.hpp" 10 #include "settings.hpp" 11 12 #ifndef STDOUT_FILENO 13 #define STDOUT_FILENO 1 14 #endif 15 #ifndef STDERR_FILENO 16 #define STDERR_FILENO 2 17 #endif 18 19 POLYBAR_NS 20 21 enum class loglevel { 22 NONE = 0, 23 ERROR, 24 WARNING, 25 NOTICE, 26 INFO, 27 TRACE, 28 }; 29 30 class logger { 31 public: 32 using make_type = const logger&; 33 static make_type make(loglevel level = loglevel::NONE); 34 35 explicit logger(loglevel level); 36 37 static loglevel parse_verbosity(const string& name, loglevel fallback = loglevel::NONE); 38 39 void verbosity(loglevel level); 40 41 #ifdef DEBUG_LOGGER // {{{ 42 template <typename... Args> trace(const string & message,Args &&...args) const43 void trace(const string& message, Args&&... args) const { 44 output(loglevel::TRACE, message, std::forward<Args>(args)...); 45 } 46 #ifdef DEBUG_LOGGER_VERBOSE 47 template <typename... Args> trace_x(const string & message,Args &&...args) const48 void trace_x(const string& message, Args&&... args) const { 49 output(loglevel::TRACE, message, std::forward<Args>(args)...); 50 } 51 #else 52 template <typename... Args> trace_x(Args &&...) const53 void trace_x(Args&&...) const {} 54 #endif 55 #else 56 template <typename... Args> trace(Args &&...) const57 void trace(Args&&...) const {} 58 template <typename... Args> trace_x(Args &&...) const59 void trace_x(Args&&...) const {} 60 #endif // }}} 61 62 /** 63 * Output an info message 64 */ 65 template <typename... Args> info(const string & message,Args &&...args) const66 void info(const string& message, Args&&... args) const { 67 output(loglevel::INFO, message, std::forward<Args>(args)...); 68 } 69 70 /** 71 * Output a notice 72 */ 73 template <typename... Args> notice(const string & message,Args &&...args) const74 void notice(const string& message, Args&&... args) const { 75 output(loglevel::NOTICE, message, std::forward<Args>(args)...); 76 } 77 78 /** 79 * Output a warning message 80 */ 81 template <typename... Args> warn(const string & message,Args &&...args) const82 void warn(const string& message, Args&&... args) const { 83 output(loglevel::WARNING, message, std::forward<Args>(args)...); 84 } 85 86 /** 87 * Output an error message 88 */ 89 template <typename... Args> err(const string & message,Args &&...args) const90 void err(const string& message, Args&&... args) const { 91 output(loglevel::ERROR, message, std::forward<Args>(args)...); 92 } 93 94 protected: 95 template <typename T> convert(T && arg) const96 decltype(auto) convert(T&& arg) const { 97 return forward<T>(arg); 98 } 99 100 /** 101 * Convert string 102 */ 103 const char* convert(string& arg) const; 104 const char* convert(const string& arg) const; 105 106 /** 107 * Convert thread id 108 */ 109 size_t convert(std::thread::id arg) const; 110 111 /** 112 * Write the log message to the output channel 113 * if the defined verbosity level allows it 114 */ 115 template <typename... Args> output(loglevel level,const string & format,Args &&...values) const116 void output(loglevel level, const string& format, Args&&... values) const { 117 if (level > m_level) { 118 return; 119 } 120 121 #if defined(__clang__) // {{{ 122 #pragma clang diagnostic push 123 #pragma clang diagnostic ignored "-Wformat-security" 124 #elif defined(__GNUC__) 125 #pragma GCC diagnostic push 126 #pragma GCC diagnostic ignored "-Wformat-security" 127 #endif // }}} 128 129 dprintf(m_fd, (m_prefixes.at(level) + format + m_suffixes.at(level) + "\n").c_str(), convert(values)...); 130 131 #if defined(__clang__) // {{{ 132 #pragma clang diagnostic pop 133 #elif defined(__GNUC__) 134 #pragma GCC diagnostic pop 135 #endif // }}} 136 } 137 138 private: 139 /** 140 * Logger verbosity level 141 */ 142 loglevel m_level{loglevel::TRACE}; 143 144 /** 145 * File descriptor used when writing the log messages 146 */ 147 int m_fd{STDERR_FILENO}; 148 149 /** 150 * Loglevel specific prefixes 151 */ 152 std::map<loglevel, string> m_prefixes; 153 154 /** 155 * Loglevel specific suffixes 156 */ 157 std::map<loglevel, string> m_suffixes; 158 }; 159 160 POLYBAR_NS_END 161