• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 #ifndef HIPERF_DEBUG_H
17 #define HIPERF_DEBUG_H
18 
19 #include <chrono>
20 #include <cstdio>
21 #include <cstring>
22 #include <map>
23 #include <memory>
24 #include <mutex>
25 #include <sstream>
26 #include <string>
27 #include <unistd.h>
28 #if !is_mingw
29 #include <sys/syscall.h>
30 #undef gettid
31 #define gettid() syscall(SYS_gettid)
32 #else
33 #include "windows.h"
gettid()34 inline long gettid()
35 {
36     return GetCurrentThreadId();
37 }
38 #endif // !is_mingw
39 
40 namespace OHOS {
41 namespace Developtools {
42 namespace HiPerf {
43 enum DebugLevel {
44     LEVEL_MUCH = 1,
45     LEVEL_VERBOSE,
46     LEVEL_DEBUG,
47     LEVEL_INFO,
48     LEVEL_WARNING,
49     LEVEL_ERROR,
50     LEVEL_FATAL,
51     LEVEL_STDOUT, // printf
52     LEVEL_MAX,    // max
53 };
54 
55 #ifdef HIPERF_DEBUG
56 #if is_ohos || is_double_framework
57 const std::string DEFAULT_UT_LOG_DIR = "/data/local/tmp/";
58 const std::string DEFAULT_LOG_PATH = "/data/local/tmp/hiperf_log.txt";
59 #elif is_mingw
60 const std::string DEFAULT_LOG_PATH = ".\\hiperf_log.txt";
61 #elif is_linux
62 const std::string DEFAULT_UT_LOG_DIR = "./";
63 const std::string DEFAULT_LOG_PATH = "hiperf_log.txt";
64 #else
65 #error unkow os
66 #endif
67 
68 #define HILOG_BASE_TAG "HILOG"
69 #ifndef HILOG_TAG
70 #define HILOG_TAG      ""
71 #define HILOG_TAG_NAME HILOG_BASE_TAG
72 #else
73 #define HILOG_TAG_NAME HILOG_BASE_TAG "_" HILOG_TAG
74 #endif
75 
76 const std::map<DebugLevel, const std::string> DebugLevelMap = {
77     {LEVEL_MUCH, "M"},    {LEVEL_VERBOSE, "V"}, {LEVEL_DEBUG, "D"}, {LEVEL_INFO, "I"},
78     {LEVEL_WARNING, "W"}, {LEVEL_ERROR, "E"},   {LEVEL_FATAL, "F"},
79 };
80 constexpr const int LOG_BUFFER_SIZE = 4 * 1024 * 1024;
81 
82 class DebugLogger {
83 public:
84     DebugLogger();
85     ~DebugLogger();
86 
87     static DebugLogger *GetInstance();
88     DebugLevel SetLogLevel(DebugLevel debugLevel);
89     bool SetMixLogOutput(bool enable);
90     bool SetLogPath(const std::string &logPath);
91     void SetLogTags(const std::string &tags);
92 
93     int Log(DebugLevel level, const std::string &logTag, const char *fmt, ...) const
94         __attribute__((format(printf, 4, 5)));
95     // for class, pointer need add 1 offset (first one is *this)
96 
97     bool EnableHiLog(bool enable = true);
GetLogLevel()98     DebugLevel GetLogLevel() const
99     {
100         return debugLevel_;
101     };
102 
103     void Disable(bool disable = true);
104     static bool logDisabled_;
105 
106 #ifdef HIPERF_DEBUG_TIME
107     mutable size_t logCount_ = 0;
108     mutable std::chrono::microseconds logTimes_ = std::chrono::microseconds::zero();
109     mutable std::chrono::microseconds logWriteTimes_ = std::chrono::microseconds::zero();
110     mutable std::chrono::microseconds logSprintfTimes_ = std::chrono::microseconds::zero();
111 #endif
112 
113     // used in UT
114     bool OpenLog(const std::string &tempLogPath = "", const std::string &flags = "w");
115     bool RestoreLog();
116     void Reset();
117 
118 private:
119     bool ShouldLog(DebugLevel level, const std::string &logtag) const;
120     DebugLevel GetLogLevelByName(const std::string &) const;
121     DebugLevel GetLogLevelByTag(const std::string &) const;
122     const std::string GetLogLevelName(DebugLevel) const;
123 
124     int HiLog(std::string &buffer) const;
125 
126     static std::unique_ptr<DebugLogger> logInstance_;
127 
128     mutable std::recursive_mutex logMutex_;
129     static DebugLevel debugLevel_;
130     const std::chrono::steady_clock::time_point timeStamp_;
131     FILE *file_ = nullptr;
132     bool mixLogOutput_ = false; // log mix to std
133     bool enableHilog_ = false;
134     bool exitOnFatal_ = true;
135     std::string logPath_;
136     std::map<std::string, DebugLevel> logTagLevelmap_;
137 };
138 
139 #ifdef HIPERF_DEBUG_PRINTF
140 #ifndef printf
141 #define printf(format, ...)                                                                        \
142     do {                                                                                           \
143         std::printf(format, ##__VA_ARGS__);                                                        \
144         DebugLogger::GetInstance()->Log(LEVEL_STDOUT, HILOG_TAG, format, ##__VA_ARGS__);           \
145     } while (0)
146 #endif
147 
148 #ifndef perror
149 #define perror(format, ...)                                                                        \
150     do {                                                                                           \
151         std::perror(format);                                                                       \
152         DebugLogger::GetInstance()->Log(LEVEL_STDOUT, HILOG_TAG, format "<%d>\n",                  \
153                                         ##__VA_ARGS__, errno);                                     \
154     } while (0)
155 #endif
156 #endif
157 
158 class ScopeDebugLevel {
159 public:
160     explicit ScopeDebugLevel(DebugLevel level, bool mix = false);
161     ~ScopeDebugLevel();
162 
163 private:
164     DebugLevel savedDebugLevel_;
165     bool savedMixOutput_ = false; // log mix to std
166 };
167 
168 #define LOG_LEVEL(LEVEL)  LOG_##LEVEL
169 #define LOG_LEVEL_MUCH    "M:"
170 #define LOG_LEVEL_VERBOSE "V:"
171 #define LOG_LEVEL_DEBUG   "D:"
172 #define LOG_LEVEL_INFO    "I:"
173 #define LOG_LEVEL_WARNING "W:"
174 #define LOG_LEVEL_ERROR   "E:"
175 #define LOG_LEVEL_FATAL   "F:"
176 
177 #ifndef HLOG
178 #ifdef IS_RELEASE_VERSION
179 #define HLOG(level, format, ...)                                                                   \
180     do {                                                                                           \
181         if (__builtin_expect(!DebugLogger::logDisabled_, false)) {                                 \
182             DebugLogger::GetInstance()->Log(                                                       \
183                 level, HILOG_TAG,                                                                  \
184                 HILOG_TAG_NAME "/" LOG_LEVEL(level) "<%ld>%s:" format "\n", gettid(),              \
185                 __FUNCTION__, ##__VA_ARGS__);                                                      \
186         }                                                                                          \
187     } while (0)
188 #else
189 #define HLOG(level, format, ...)                                                                   \
190     do {                                                                                           \
191         if (__builtin_expect(!DebugLogger::logDisabled_, false)) {                                 \
192             DebugLogger::GetInstance()->Log(                                                       \
193                 level, HILOG_TAG,                                                                  \
194                 HILOG_TAG_NAME "/" LOG_LEVEL(level) "<%ld>[%s:%d]%s:" format "\n", gettid(),       \
195                 __FILE_NAME__, __LINE__, __FUNCTION__, ##__VA_ARGS__);                            \
196         }                                                                                          \
197     } while (0)
198 #endif
199 #endif
200 
201 // only log first n times
202 #ifndef HLOGV_FIRST
203 #define HLOGV_FIRST(first, format, ...)                                                            \
204     do {                                                                                           \
205         static int limit = first;                                                                  \
206         if (limit > 0) {                                                                           \
207             HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__);                                            \
208             if (--limit == 0) {                                                                    \
209                 HLOG(LEVEL_VERBOSE, " nexttime log will be suppressed...");                        \
210             }                                                                                      \
211         }                                                                                          \
212     } while (0)
213 #endif
214 
215 #ifndef HLOGV_FIRST_LOCAL
216 #define HLOGV_FIRST_LOCAL(local_limit, format, ...)                                                \
217     {                                                                                              \
218         if (local_limit != 0) {                                                                    \
219             HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__);                                            \
220             if (local_limit > 0 && --local_limit == 0) {                                           \
221                 HLOG(LEVEL_VERBOSE, " nexttime log will be suppressed...");                        \
222             }                                                                                      \
223         }                                                                                          \
224     }
225 #endif
226 
227 #ifndef HLOGV
228 #define HLOGV_IF(condition, format, ...)                                                           \
229     if (condition) {                                                                               \
230         HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__)                                                 \
231     }
232 #define HLOGVVV HLOGV
233 #endif
234 
235 #ifndef HLOGDUMMY
236 #define HLOGDUMMY(format, ...) while (0)
237 #endif
238 
239 #ifndef HLOGM
240 #define HLOGM(format, ...) HLOG(LEVEL_MUCH, format, ##__VA_ARGS__)
241 #define HLOGMMM            HLOGM
242 #endif
243 
244 #ifndef HLOGV
245 #define HLOGV(format, ...) HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__)
246 #endif
247 
248 #ifndef HLOGD
249 #define HLOGD(format, ...) HLOG(LEVEL_DEBUG, format, ##__VA_ARGS__)
250 #define HLOGDDD            HLOGM
251 #endif
252 
253 #ifndef HLOGI
254 #define HLOGI(format, ...) HLOG(LEVEL_INFO, format, ##__VA_ARGS__)
255 #endif
256 
257 #ifndef HLOGW
258 #define HLOGW(format, ...) HLOG(LEVEL_WARNING, format, ##__VA_ARGS__)
259 #endif
260 
261 #ifndef HLOGE
262 #define HLOGE(format, ...) HLOG(LEVEL_ERROR, format, ##__VA_ARGS__)
263 #endif
264 
265 #ifndef HLOGEP
266 #define HLOGEP(format, ...)                                                                        \
267     HLOG(LEVEL_ERROR, format "(errno %d)", ##__VA_ARGS__, errno)
268 #endif
269 
270 #ifndef HLOGF
271 #ifdef IS_RELEASE_VERSION
272 #define HLOGF(format, ...) HLOG(LEVEL_FATAL, "FATAL error occured, " format, ##__VA_ARGS__)
273 #else
274 #define HLOGF(format, ...)                                                                         \
275     HLOG(LEVEL_FATAL, "FATAL error at %s:%d " format, __FILE_NAME__, __LINE__, ##__VA_ARGS__)
276 #endif
277 #endif
278 
279 #ifndef HLOG_ASSERT_MESSAGE
280 #define HLOG_ASSERT_MESSAGE(condition, format, ...)                                                \
281     if (!(condition)) {                                                                            \
282         HLOG(LEVEL_FATAL, " assert failed: '%s' " format, #condition, ##__VA_ARGS__);              \
283     }
284 #endif
285 
286 #ifndef HLOG_ASSERT
287 #define HLOG_ASSERT(condition) HLOG_ASSERT_MESSAGE(condition, "")
288 #endif
289 
290 #ifndef HIPERF_ASSERT
291 #define HIPERF_ASSERT(condition, format, ...)                                                      \
292     if (!(condition)) [[unlikely]] {                                                               \
293         printf(format, ##__VA_ARGS__);                                                             \
294         exit(-1);                                                                                  \
295     }
296 #endif
297 
298 #undef assert
299 #else
300 #define HLOGDUMMY(...)                                                                             \
301     do {                                                                                           \
302     } while (0)
303 #define HLOGEP(...)                                                                                \
304     do {                                                                                           \
305     } while (0)
306 #define HLOGM(...)                                                                                 \
307     do {                                                                                           \
308     } while (0)
309 #define HLOGMMM(...)                                                                               \
310     do {                                                                                           \
311     } while (0)
312 #define HLOGV(...)                                                                                 \
313     do {                                                                                           \
314     } while (0)
315 #define HLOGVVV(...)                                                                               \
316     do {                                                                                           \
317     } while (0)
318 #define HLOGD(...)                                                                                 \
319     do {                                                                                           \
320     } while (0)
321 #define HLOGDDD(...)                                                                               \
322     do {                                                                                           \
323     } while (0)
324 #define HLOGI(...)                                                                                 \
325     do {                                                                                           \
326     } while (0)
327 #define HLOGW(...)                                                                                 \
328     do {                                                                                           \
329     } while (0)
330 #define HLOGE(...)                                                                                 \
331     do {                                                                                           \
332     } while (0)
333 #define HLOGF(...)                                                                                 \
334     do {                                                                                           \
335     } while (0)
336 #define HLOG_ASSERT_MESSAGE(...)                                                                   \
337     do {                                                                                           \
338     } while (0)
339 #define HLOG_ASSERT(...)                                                                           \
340     do {                                                                                           \
341     } while (0)
342 
343 class ScopeDebugLevel {
344 public:
345     ScopeDebugLevel(DebugLevel level, bool mix = false) {}
346 };
347 #endif
348 } // namespace HiPerf
349 } // namespace Developtools
350 } // namespace OHOS
351 #endif // _HIPERF_DEBUG_H_
352