1/* 2 * Copyright (c) 2023 Huawei Device Co., Ltd. 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#include "texgine/utils/logger.h" 17 18#include <fstream> 19#include <iomanip> 20#include <iostream> 21#include <unistd.h> 22 23#ifdef BUILD_NON_SDK_VER 24#include <sys/syscall.h> 25#define GET_TID() syscall(__NR_gettid) 26#else 27#ifdef _WIN32 28#include <windows.h> 29#define GET_TID GetCurrentThreadId 30#endif 31 32#if defined(BUILD_SDK_MAC) || defined(BUILD_SDK_IOS) 33#include <stdlib.h> 34#include <sys/syscall.h> 35#define GET_TID() syscall(SYS_thread_selfid) 36#elif defined(BUILD_SDK_ANDROID) 37#define GET_TID() gettid() 38#else 39#ifdef __gnu_linux__ 40#include <sys/types.h> 41#include <sys/syscall.h> 42#define GET_TID() syscall(SYS_gettid) 43#endif 44#endif 45 46#ifdef __APPLE__ 47#define getpid getpid 48#endif 49 50#ifdef ERROR 51#undef ERROR 52#endif 53#endif 54 55#ifdef LOGGER_NO_COLOR 56#define IF_COLOR(x) 57#else 58#define IF_COLOR(x) x 59#endif 60 61namespace OHOS { 62namespace Rosen { 63namespace TextEngine { 64namespace { 65const char *GetLevelStr(enum Logger::LOG_LEVEL level) 66{ 67 switch (level) { 68 case Logger::LOG_LEVEL::DEBUG: 69 return IF_COLOR("\033[37m") "D" IF_COLOR("\033[0m"); 70 case Logger::LOG_LEVEL::INFO: 71 return IF_COLOR("\033[36m") "I" IF_COLOR("\033[0m"); 72 case Logger::LOG_LEVEL::WARN: 73 return IF_COLOR("\033[33m") "W" IF_COLOR("\033[0m"); 74 case Logger::LOG_LEVEL::ERROR: 75 return IF_COLOR("\033[31m") "E" IF_COLOR("\033[0m"); 76 case Logger::LOG_LEVEL::FATAL: 77 return IF_COLOR("\033[4;31m") "F" IF_COLOR("\033[0m"); 78 } 79 return "?"; 80} 81} // namespace 82 83void Logger::SetToNoReturn(Logger &logger, enum LOG_PHASE phase) 84{ 85 logger.return_ = false; 86} 87 88void Logger::SetToContinue(Logger &logger, enum LOG_PHASE phase) 89{ 90 logger.continue_ = true; 91} 92 93void Logger::OutputByStdout(Logger &logger, enum LOG_PHASE phase) 94{ 95 if (phase == LOG_PHASE::BEGIN) { 96 return; 97 } 98 99 // LOG_PHASE::END 100 if (logger.continue_ == false) { 101 std::cout << GetLevelStr(logger.GetLevel()) << " "; 102 } 103 104 std::cout << logger.str(); 105 if (logger.return_) { 106 std::cout << std::endl; 107 } 108} 109 110void Logger::OutputByStderr(Logger &logger, enum LOG_PHASE phase) 111{ 112 if (phase == LOG_PHASE::BEGIN) { 113 return; 114 } 115 116 // LOG_PHASE::END 117 if (logger.continue_ == false) { 118 std::cerr << GetLevelStr(logger.GetLevel()) << " "; 119 } 120 121 std::cerr << logger.str(); 122 if (logger.return_) { 123 std::cerr << std::endl; 124 } 125} 126 127void Logger::OutputByFileLog(Logger &logger, enum LOG_PHASE phase) 128{ 129 struct FileLogData { 130 const char *filename; 131 }; 132 auto data = logger.GetData<struct FileLogData>(); 133 if (phase == LOG_PHASE::BEGIN) { 134 auto filename = va_arg(logger.GetVariousArgument(), const char *); 135 data->filename = filename; 136 return; 137 } 138 139 // LOG_PHASE::END 140 std::ofstream ofs(data->filename, std::ofstream::out | std::ofstream::app); 141 if (!ofs) { 142 // open failed, errno 143 return; 144 } 145 146 if (logger.continue_ == false) { 147 ofs << GetLevelStr(logger.GetLevel()) << " "; 148 } 149 150 ofs << logger.str(); 151 if (logger.return_) { 152 ofs << std::endl; 153 } 154 ofs.close(); 155} 156 157void Logger::AppendFunc(Logger &logger, enum LOG_PHASE phase) 158{ 159 if (phase == LOG_PHASE::BEGIN) { 160 logger << IF_COLOR("\033[34m"); 161 logger.AlignFunc(); 162 logger << logger.GetFunc() << IF_COLOR("\033[0m") " "; 163 } 164} 165 166void Logger::AppendFuncLine(Logger &logger, enum LOG_PHASE phase) 167{ 168 if (phase == LOG_PHASE::BEGIN) { 169 logger << IF_COLOR("\033[34m"); 170 logger.AlignFunc(); 171 logger << logger.GetFunc() << " "; 172 logger.AlignLine(); 173 logger << IF_COLOR("\033[35m") "+" << logger.GetLine() << IF_COLOR("\033[0m") " "; 174 } 175} 176 177void Logger::AppendFileLine(Logger &logger, enum LOG_PHASE phase) 178{ 179 if (phase == LOG_PHASE::BEGIN) { 180 logger << IF_COLOR("\033[34m") << logger.GetFile() << " "; 181 logger.AlignLine(); 182 logger << IF_COLOR("\033[35m") "+" << logger.GetLine() << IF_COLOR("\033[0m") " "; 183 } 184} 185 186void Logger::AppendFileFuncLine(Logger &logger, enum LOG_PHASE phase) 187{ 188 if (phase == LOG_PHASE::BEGIN) { 189 logger << IF_COLOR("\033[34m") << logger.GetFile() << " "; 190 logger.AlignLine(); 191 logger << IF_COLOR("\033[35m") "+" << logger.GetLine() << " "; 192 logger.AlignFunc(); 193 logger << logger.GetFunc() << IF_COLOR("\033[0m") " "; 194 } 195} 196 197void Logger::AppendPidTid(Logger &logger, enum LOG_PHASE phase) 198{ 199 if (phase == LOG_PHASE::BEGIN) { 200 logger << getpid() << ":" << GET_TID() << " "; 201 } 202} 203 204void Logger::SetScopeParam(int func, int line) 205{ 206 alignFunc = func; 207 alignLine = line; 208} 209 210void Logger::EnterScope() 211{ 212 std::lock_guard<std::mutex> lock(scopeMutex_); 213 scope_++; 214} 215 216void Logger::ExitScope() 217{ 218 std::lock_guard<std::mutex> lock(scopeMutex_); 219 scope_--; 220} 221 222Logger::Logger(const std::string &file, const std::string &func, int line, enum LOG_LEVEL level, ...) 223{ 224 *this << std::boolalpha; 225 file_ = file; 226 func_ = func; 227 line_ = line; 228 level_ = level; 229 va_start(vl_, level); 230 231 while (true) { 232 LoggerWrapperFunc f = va_arg(vl_, LoggerWrapperFunc); 233 if (f == nullptr) { 234 break; 235 } 236 237 f(*this, LOG_PHASE::BEGIN); 238 wrappers_.push_back(f); 239 } 240 241#ifdef LOGGER_ENABLE_SCOPE 242 { 243 std::lock_guard<std::mutex> lock(scopeMutex_); 244 // The number of space if enable scope 245 Align(scope_ * 2); // 2 means multiple 246 } 247#endif 248} 249 250Logger::Logger(const Logger &logger) 251{ 252 file_ = logger.file_; 253 func_ = logger.func_; 254 line_ = logger.line_; 255 level_ = logger.level_; 256 data_ = logger.data_; 257 wrappers_ = logger.wrappers_; 258 *this << logger.str(); 259} 260 261Logger::Logger(Logger &&logger) 262{ 263 file_ = logger.file_; 264 func_ = logger.func_; 265 line_ = logger.line_; 266 level_ = logger.level_; 267 data_ = logger.data_; 268 wrappers_ = logger.wrappers_; 269 *this << logger.str(); 270 271 logger.wrappers_.clear(); 272} 273 274Logger::~Logger() 275{ 276 for (const auto &wrapper : wrappers_) { 277 wrapper(*this, LOG_PHASE::END); 278 } 279} 280 281const std::string &Logger::GetFile() const 282{ 283 return file_; 284} 285 286const std::string &Logger::GetFunc() const 287{ 288 return func_; 289} 290 291int Logger::GetLine() const 292{ 293 return line_; 294} 295 296enum Logger::LOG_LEVEL Logger::GetLevel() const 297{ 298 return level_; 299} 300 301va_list &Logger::GetVariousArgument() 302{ 303 return vl_; 304} 305 306void Logger::Align(int num) 307{ 308 if (continue_) { 309 return; 310 } 311 312 for (int32_t i = 0; i < num; i++) { 313 *this << " "; 314 } 315} 316 317void Logger::AlignLine() 318{ 319 if (alignLine) { 320 auto line = GetLine(); 321 auto num = line == 0 ? 1 : 0; 322 while (line) { 323 // 10 is to calculate the number of bits in the row where the function is located 324 line /= 10; 325 num++; 326 } 327 Align(alignLine - num); 328 } 329} 330 331void Logger::AlignFunc() 332{ 333 if (alignFunc) { 334 Align(alignFunc - GetFunc().size()); 335 } 336} 337 338ScopedLogger::ScopedLogger(NoLogger &&logger) 339{ 340} 341 342ScopedLogger::ScopedLogger(NoLogger &&logger, const std::string &name) 343{ 344} 345 346ScopedLogger::ScopedLogger(Logger &&logger) 347 : ScopedLogger(std::move(logger), "") 348{ 349} 350 351ScopedLogger::ScopedLogger(Logger &&logger, const std::string &name) 352{ 353#ifdef LOGGER_ENABLE_SCOPE 354 logger_ = new Logger(logger); 355 *logger_ << "} " << name; 356 logger << "{ "; 357#endif 358 logger << name; 359 Logger::EnterScope(); 360} 361 362ScopedLogger::~ScopedLogger() 363{ 364 Finish(); 365} 366 367void ScopedLogger::Finish() 368{ 369 if (logger_) { 370 Logger::ExitScope(); 371 delete logger_; 372 logger_ = nullptr; 373 } 374} 375} // namespace TextEngine 376} // namespace Rosen 377} // namespace OHOS 378