1 /* 2 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef _HHLOG_H 17 #define _HHLOG_H 18 19 #include <atomic> 20 #include <cstdio> 21 #include <cstring> 22 #include <ctime> 23 #include <iostream> 24 #include <memory> 25 #include <sstream> 26 #include <string> 27 #include <strstream> 28 #include <thread> 29 30 #include <fcntl.h> 31 #include <securec.h> 32 #include <stdarg.h> 33 #include <unistd.h> 34 #include <sys/time.h> 35 36 #include "ringbuffer.h" 37 38 enum HHLOG_LEVEL:int { 39 HHLOG_DEBUG = 0, 40 HHLOG_INFO = 1, 41 HHLOG_WARN = 2, 42 HHLOG_ERROR = 3, 43 HHLOG_FATAL = 4, 44 HHLOG_NONE = 5, 45 }; 46 47 class HHLogger { 48 public: 49 ~HHLogger(); GetInstance()50 static inline HHLogger& GetInstance() 51 { 52 static HHLogger logger {}; 53 return logger; 54 } 55 56 int Start(const int logLevel = HHLOG_DEBUG, const std::string& logFile = "./hhlog.txt"); 57 PutLog(const char * format,...)58 inline int PutLog(const char* format, ...) 59 { 60 va_list args; 61 va_start(args, format); 62 auto ftime = GetFormatTime(); 63 std::size_t nbytes = ftime.length(); 64 if (nbytes == 0 or nbytes >= MAX_HHLOG_SIZE) { 65 return -1; 66 } 67 char buffer[MAX_HHLOG_SIZE]; 68 if (memcpy_s(buffer, sizeof(buffer), ftime.c_str(), nbytes) != EOK) { 69 return -1; 70 } 71 int ret = vsnprintf_s(buffer + nbytes, sizeof(buffer) - nbytes, 72 sizeof(buffer) - nbytes - 1, format, args); 73 va_end(args); 74 if (ret < 0) { 75 return -1; 76 } 77 nbytes += static_cast<std::size_t>(ret); 78 if (nbytes >= MAX_HHLOG_SIZE) { 79 return -1; 80 } 81 buffer[nbytes++] = '\n'; 82 return buf_->Put(buffer, nbytes); 83 } 84 GetLogLevel()85 inline int GetLogLevel() const 86 { 87 return logLevel_; 88 } 89 IsStopped()90 inline bool IsStopped() 91 { 92 return stop_.load(); 93 } 94 LogSaver()95 inline void LogSaver() 96 { 97 if (logLevel_ == HHLOG_NONE) { 98 return; 99 } 100 logSaver_ = std::thread(&HHLogger::SaveLog, this); 101 } 102 103 enum SizeConsts:std::size_t { 104 RING_BUF_SIZE = 4096, 105 MAX_FORMAT_SIZE = 512, 106 MAX_HHLOG_SIZE = 1024, 107 }; 108 109 private: 110 HHLogger() = default; 111 std::string GetLogFileName() const; 112 std::string GetFormatTime() const; 113 int SaveLog(); 114 int InitLogger(const int logLevel, const std::string& logFile); 115 int UpdateTimer(); 116 117 int fd_ {-1}; 118 int logLevel_ {HHLOG_NONE}; 119 std::atomic<bool> stop_ {false}; 120 std::atomic<struct timeval> timer_; 121 std::unique_ptr<RingBuffer> buf_ {nullptr}; 122 std::thread logSaver_; 123 }; 124 125 #define HHLOG(level, expression, format, ...) { \ 126 if ((expression) and \ 127 (!HHLogger::GetInstance().IsStopped()) and \ 128 (HHLogger::GetInstance().GetLogLevel() <= HHLOG_##level)) { \ 129 const char prefix[] {" [" #level "] %s %d %s: %s"}; \ 130 char buffer[HHLogger::MAX_FORMAT_SIZE]; \ 131 (void)snprintf_s(buffer, sizeof(buffer), sizeof(buffer) -1, \ 132 prefix, __FILE__, __LINE__, __FUNCTION__, format); \ 133 HHLogger::GetInstance().PutLog(buffer, ##__VA_ARGS__); \ 134 } \ 135 } 136 137 #if defined(HH_LOGGER_DEBUG) 138 139 #define HHLOGD(expression, format, ...) HHLOG(DEBUG, expression, format, ##__VA_ARGS__) 140 #define HHLOGI(expression, format, ...) HHLOG(INFO, expression, format, ##__VA_ARGS__) 141 #define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__) 142 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__) 143 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__) 144 145 #elif defined(HH_LOGGER_INFO) 146 147 #define HHLOGD(expression, format, ...) {} 148 #define HHLOGI(expression, format, ...) HHLOG(INFO, expression, format, ##__VA_ARGS__) 149 #define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__) 150 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__) 151 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__) 152 153 #elif defined(HH_LOGGER_WARN) 154 155 #define HHLOGD(expression, format, ...) {} 156 #define HHLOGI(expression, format, ...) {} 157 #define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__) 158 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__) 159 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__) 160 161 #elif defined(HH_LOGGER_ERROR) 162 163 #define HHLOGD(expression, format, ...) {} 164 #define HHLOGI(expression, format, ...) {} 165 #define HHLOGW(expression, format, ...) {} 166 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__) 167 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__) 168 169 #elif defined(HH_LOGGER_FATAL) 170 171 #define HHLOGD(expression, format, ...) {} 172 #define HHLOGI(expression, format, ...) {} 173 #define HHLOGW(expression, format, ...) {} 174 #define HHLOGE(expression, format, ...) {} 175 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__) 176 177 #else 178 179 #define HHLOGD(expression, format, ...) {} 180 #define HHLOGI(expression, format, ...) {} 181 #define HHLOGW(expression, format, ...) {} 182 #define HHLOGE(expression, format, ...) {} 183 #define HHLOGF(expression, format, ...) {} 184 185 #endif 186 187 #define CHECK_NOTNULL(ptr, retval, fmt, ...) \ 188 do { \ 189 if (ptr == nullptr) { \ 190 HHLOGE(true, "CHECK_NOTNULL(%s) in %s:%d FAILED, " fmt, #ptr, __func__, \ 191 __LINE__, ##__VA_ARGS__); \ 192 return retval; \ 193 } \ 194 } while (0) 195 196 #define CHECK_TRUE(expr, retval, fmt, ...) \ 197 do { \ 198 if (!(expr)) { \ 199 HHLOGE(true, "CHECK_TRUE(%s) in %s:%d FAILED, " fmt, #expr, __func__, __LINE__, ##__VA_ARGS__); \ 200 return retval; \ 201 } \ 202 } while (0) 203 204 #endif // HHLOG_H