1 /* 2 +----------------------------------------------------------------------+ 3 | Swoole | 4 +----------------------------------------------------------------------+ 5 | This source file is subject to version 2.0 of the Apache license, | 6 | that is bundled with this package in the file LICENSE, and is | 7 | available through the world-wide-web at the following url: | 8 | http://www.apache.org/licenses/LICENSE-2.0.html | 9 | If you did not receive a copy of the Apache2.0 license and are unable| 10 | to obtain it through the world-wide-web, please send a note to | 11 | license@swoole.com so we can mail you a copy immediately. | 12 +----------------------------------------------------------------------+ 13 | Author: Tianfeng Han <mikan.tenny@gmail.com> | 14 +----------------------------------------------------------------------+ 15 */ 16 17 #pragma once 18 19 #include <stddef.h> 20 #include <stdint.h> 21 #include <string> 22 #include <unistd.h> 23 24 #define SW_LOG_BUFFER_SIZE (SW_ERROR_MSG_SIZE + 256) 25 #define SW_LOG_DATE_STRLEN 128 26 #define SW_LOG_DEFAULT_DATE_FORMAT "%F %T" 27 28 enum swLogLevel { 29 SW_LOG_DEBUG = 0, 30 SW_LOG_TRACE, 31 SW_LOG_INFO, 32 SW_LOG_NOTICE, 33 SW_LOG_WARNING, 34 SW_LOG_ERROR, 35 SW_LOG_NONE, 36 }; 37 38 enum swLogRotationType { 39 SW_LOG_ROTATION_SINGLE = 0, 40 SW_LOG_ROTATION_MONTHLY, 41 SW_LOG_ROTATION_DAILY, 42 SW_LOG_ROTATION_HOURLY, 43 SW_LOG_ROTATION_EVERY_MINUTE, 44 }; 45 46 namespace swoole { 47 class Logger { 48 private: 49 bool opened = false; 50 // Redirect stdin and stdout to log_fd 51 bool redirected = false; 52 bool display_backtrace_ = false; 53 int stdout_fd = -1; 54 int stderr_fd = -1; 55 int log_fd = STDOUT_FILENO; 56 int log_level = SW_LOG_INFO; 57 bool date_with_microseconds = false; 58 std::string date_format = SW_LOG_DEFAULT_DATE_FORMAT; 59 std::string log_file = ""; 60 std::string log_real_file; 61 int log_rotation = SW_LOG_ROTATION_SINGLE; 62 63 public: 64 bool open(const char *logfile); 65 void put(int level, const char *content, size_t length); 66 void reopen(); 67 void close(void); 68 void reset(); 69 void set_level(int lv); 70 int get_level(); 71 bool set_date_format(const char *format); 72 void set_rotation(int rotation); 73 const char *get_real_file(); 74 const char *get_file(); 75 bool is_opened(); 76 bool redirect_stdout_and_stderr(int enable); 77 void set_date_with_microseconds(bool enable); 78 std::string gen_real_file(const std::string &file); 79 static std::string get_pretty_name(const std::string &prettyFunction, bool strip = true); 80 display_backtrace()81 void display_backtrace() { 82 display_backtrace_ = true; 83 } 84 }; 85 } // namespace swoole 86 87 swoole::Logger *sw_logger(); 88 #define __SW_FUNC__ (swoole::Logger::get_pretty_name(__PRETTY_FUNCTION__).c_str()) 89 90 #define swoole_info(str, ...) \ 91 if (SW_LOG_INFO >= sw_logger()->get_level()) { \ 92 size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ 93 sw_logger()->put(SW_LOG_INFO, sw_error, _sw_error_len); \ 94 } 95 96 #define swoole_notice(str, ...) \ 97 if (SW_LOG_NOTICE >= sw_logger()->get_level()) { \ 98 size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ 99 sw_logger()->put(SW_LOG_NOTICE, sw_error, _sw_error_len); \ 100 } 101 102 #define swoole_sys_notice(str, ...) \ 103 do { \ 104 swoole_set_last_error(errno); \ 105 if (SW_LOG_ERROR >= sw_logger()->get_level()) { \ 106 size_t _sw_error_len = sw_snprintf(sw_error, \ 107 SW_ERROR_MSG_SIZE, \ 108 "%s(:%d): " str ", Error: %s[%d]", \ 109 __SW_FUNC__, \ 110 __LINE__, \ 111 ##__VA_ARGS__, \ 112 swoole_strerror(errno), \ 113 errno); \ 114 sw_logger()->put(SW_LOG_NOTICE, sw_error, _sw_error_len); \ 115 } \ 116 } while (0) 117 118 #define swoole_warning(str, ...) \ 119 do { \ 120 if (SW_LOG_WARNING >= sw_logger()->get_level()) { \ 121 size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(): " str, __SW_FUNC__, ##__VA_ARGS__); \ 122 sw_logger()->put(SW_LOG_WARNING, sw_error, _sw_error_len); \ 123 } \ 124 } while (0) 125 126 #define swoole_sys_warning(str, ...) \ 127 do { \ 128 swoole_set_last_error(errno); \ 129 if (SW_LOG_ERROR >= sw_logger()->get_level()) { \ 130 size_t _sw_error_len = sw_snprintf(sw_error, \ 131 SW_ERROR_MSG_SIZE, \ 132 "%s(): " str ", Error: %s[%d]", \ 133 __SW_FUNC__, \ 134 ##__VA_ARGS__, \ 135 swoole_strerror(errno), \ 136 errno); \ 137 sw_logger()->put(SW_LOG_WARNING, sw_error, _sw_error_len); \ 138 } \ 139 } while (0) 140 141 #define swoole_error(str, ...) \ 142 do { \ 143 size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \ 144 sw_logger()->put(SW_LOG_ERROR, sw_error, _sw_error_len); \ 145 exit(1); \ 146 } while (0) 147 148 #define swoole_sys_error(str, ...) \ 149 do { \ 150 size_t _sw_error_len = sw_snprintf(sw_error, \ 151 SW_ERROR_MSG_SIZE, \ 152 "%s(): " str ", Error: %s[%d]", \ 153 __SW_FUNC__, \ 154 ##__VA_ARGS__, \ 155 swoole_strerror(errno), \ 156 errno); \ 157 sw_logger()->put(SW_LOG_ERROR, sw_error, _sw_error_len); \ 158 exit(1); \ 159 } while (0) 160 161 #define swoole_fatal_error(code, str, ...) \ 162 do { \ 163 SwooleG.fatal_error(code, str, ##__VA_ARGS__); \ 164 exit(255); \ 165 } while (0) 166 167 #define swoole_error_log(level, error, str, ...) \ 168 do { \ 169 swoole_set_last_error(error); \ 170 if (level >= sw_logger()->get_level() && !swoole_is_ignored_error(error)) { \ 171 size_t _sw_error_len = \ 172 sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s() (ERRNO %d): " str, __SW_FUNC__, error, ##__VA_ARGS__); \ 173 sw_logger()->put(level, sw_error, _sw_error_len); \ 174 } \ 175 } while (0) 176 177 #ifdef SW_DEBUG 178 #define swoole_debug(str, ...) \ 179 if (SW_LOG_DEBUG >= sw_logger()->get_level()) { \ 180 size_t _sw_error_len = \ 181 sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \ 182 sw_logger()->put(SW_LOG_DEBUG, sw_error, _sw_error_len); \ 183 } 184 185 #define swoole_hex_dump(data, length) \ 186 do { \ 187 const char *__data = (data); \ 188 size_t __length = (length); \ 189 swoole_debug("+----------+------------+-----------+-----------+------------+------------------+"); \ 190 for (size_t of = 0; of < __length; of += 16) { \ 191 char hex[16 * 3 + 1]; \ 192 char str[16 + 1]; \ 193 size_t i, hof = 0, sof = 0; \ 194 for (i = of; i < of + 16 && i < __length; i++) { \ 195 hof += sprintf(hex + hof, "%02x ", (__data)[i] & 0xff); \ 196 sof += sprintf(str + sof, "%c", isprint((int) (__data)[i]) ? (__data)[i] : '.'); \ 197 } \ 198 swoole_debug("| %08x | %-48s| %-16s |", of, hex, str); \ 199 } \ 200 swoole_debug("+----------+------------+-----------+-----------+------------+------------------+"); \ 201 } while (0) 202 #else 203 #define swoole_debug(str, ...) 204 #define swoole_hex_dump(data, length) 205 #endif 206 207 enum swTrace_type { 208 /** 209 * Server 210 */ 211 SW_TRACE_SERVER = 1u << 1, 212 SW_TRACE_CLIENT = 1u << 2, 213 SW_TRACE_BUFFER = 1u << 3, 214 SW_TRACE_CONN = 1u << 4, 215 SW_TRACE_EVENT = 1u << 5, 216 SW_TRACE_WORKER = 1u << 6, 217 SW_TRACE_MEMORY = 1u << 7, 218 SW_TRACE_REACTOR = 1u << 8, 219 SW_TRACE_PHP = 1u << 9, 220 SW_TRACE_HTTP = 1u << 10, 221 SW_TRACE_HTTP2 = 1u << 11, 222 SW_TRACE_EOF_PROTOCOL = 1u << 12, 223 SW_TRACE_LENGTH_PROTOCOL = 1u << 13, 224 SW_TRACE_CLOSE = 1u << 14, 225 SW_TRACE_WEBSOCKET = 1u << 15, 226 /** 227 * Client 228 */ 229 SW_TRACE_REDIS_CLIENT = 1u << 16, 230 SW_TRACE_MYSQL_CLIENT = 1u << 17, 231 SW_TRACE_HTTP_CLIENT = 1u << 18, 232 SW_TRACE_AIO = 1u << 19, 233 SW_TRACE_SSL = 1u << 20, 234 SW_TRACE_NORMAL = 1u << 21, 235 /** 236 * Coroutine 237 */ 238 SW_TRACE_CHANNEL = 1u << 22, 239 SW_TRACE_TIMER = 1u << 23, 240 SW_TRACE_SOCKET = 1u << 24, 241 SW_TRACE_COROUTINE = 1u << 25, 242 SW_TRACE_CONTEXT = 1u << 26, 243 SW_TRACE_CO_HTTP_SERVER = 1u << 27, 244 SW_TRACE_TABLE = 1u << 28, 245 SW_TRACE_CO_CURL = 1u << 29, 246 SW_TRACE_CARES = 1u << 30, 247 248 SW_TRACE_ALL = 0x7fffffffffffffff 249 }; 250 251 #ifdef SW_LOG_TRACE_OPEN 252 #define swoole_trace_log(what, str, ...) \ 253 if (SW_LOG_TRACE >= sw_logger()->get_level() && (what & SwooleG.trace_flags)) { \ 254 size_t _sw_error_len = \ 255 sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \ 256 sw_logger()->put(SW_LOG_TRACE, sw_error, _sw_error_len); \ 257 } 258 #else 259 #define swoole_trace_log(what, str, ...) 260 #endif 261 262 #define swoole_trace(str, ...) swoole_trace_log(SW_TRACE_NORMAL, str, ##__VA_ARGS__) 263