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