• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 <map>
21 #include <memory>
22 #include <mutex>
23 #include <stdio.h>
24 #include <string>
25 #include <unistd.h>
26 #include <gtest/gtest_prod.h>
27 #include "get_thread_id.h"
28 
29 namespace OHOS {
30 namespace Developtools {
31 namespace NativeDaemon {
32 #ifdef HIPERF_DEBUG
33 #if is_ohos || is_double_framework
34 const std::string DEFAULT_LOG_PATH = "/data/local/tmp/hiperf_log.txt";
35 #elif is_mingw
36 const std::string DEFAULT_LOG_PATH = ".\\hiperf_log.txt";
37 #elif is_linux
38 const std::string DEFAULT_LOG_PATH = "hiperf_log.txt";
39 #else
40 #error unkow os
41 #endif
42 
43 #define HILOG_BASE_TAG "HILOG"
44 #ifndef HILOG_TAG
45 #define HILOG_TAG      ""
46 #define HILOG_TAG_NAME HILOG_BASE_TAG
47 #else
48 #define HILOG_TAG_NAME HILOG_BASE_TAG "_" HILOG_TAG
49 #endif
50 
51 #define SHORT_FILENAME                                                                             \
52     (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
53 
54 enum DebugLevel {
55     LEVEL_MUCH = 1,
56     LEVEL_VERBOSE,
57     LEVEL_DEBUG,
58     LEVEL_INFO,
59     LEVEL_WARNING,
60     LEVEL_ERROR,
61     LEVEL_FATAL,
62     LEVEL_STDOUT, // printf
63     LEVEL_MAX,    // max
64 };
65 
66 const std::map<DebugLevel, const std::string> DebugLevelMap = {
67     {LEVEL_MUCH, "M"},
68     {LEVEL_VERBOSE, "V"},
69     {LEVEL_DEBUG, "D"},
70     {LEVEL_INFO, "I"},
71     {LEVEL_WARNING, "W"},
72     {LEVEL_ERROR, "E"},
73     {LEVEL_FATAL, "F"},
74 };
75 constexpr const int LOG_BUFFER_SIZE = 4 * 1024 * 1024;
76 
77 class DebugLogger {
78 public:
79     DebugLogger();
80     ~DebugLogger();
81 
82     static DebugLogger *GetInstance();
83     DebugLevel SetLogLevel(DebugLevel debugLevel);
84     bool SetMixLogOutput(bool enable);
85     bool SetLogPath(const std::string &logPath);
86     void SetLogTags(const std::string &tags);
87 
88     int Log(DebugLevel level, const std::string &logTag, const char *fmt, ...) const
89         __attribute__((format(printf, 4, 5)));
90     // for class, pointer need add 1 offset (first one is *this)
91 
92     bool EnableHiLog(bool = true);
GetLogLevel()93     DebugLevel GetLogLevel() const
94     {
95         return debugLevel_;
96     };
97 
98     void Disable(bool disable = true);
99     static bool logDisabled_;
100 
101 #ifdef HIPERF_DEBUG_TIME
102     mutable size_t logCount_ = 0;
103     mutable std::chrono::microseconds logTimes_ = std::chrono::microseconds::zero();
104     mutable std::chrono::microseconds logWriteTimes_ = std::chrono::microseconds::zero();
105     mutable std::chrono::microseconds logSprintfTimes_ = std::chrono::microseconds::zero();
106 #endif
107 
108 private:
109     bool ShouldLog(DebugLevel debugLevel, const std::string &logTag) const;
110     DebugLevel GetLogLevelByName(const std::string &) const;
111     DebugLevel GetLogLevelByTag(const std::string &) const;
112     const std::string GetLogLevelName(DebugLevel) const;
113 
114     int HiLog(std::string &buffer) const;
115 
116     static std::unique_ptr<DebugLogger> logInstance_;
117     std::string logFileBuffer_;
118 
119     mutable std::mutex logMutex_;
120     static DebugLevel debugLevel_;
121     const std::chrono::steady_clock::time_point timeStamp_;
122     bool OpenLog();
123     FILE *file_ = nullptr;
124     bool mixLogOutput_ = false; // log mix to std
125     bool enableHilog_ = false;
126     bool exitOnFatal_ = true;
127     std::string logPath_;
128     std::map<std::string, DebugLevel> logTagLevelmap_;
129 
130     friend class OptionDebugTest;
131     friend class DebugLoggerTest;
132     FRIEND_TEST(DebugLoggerTest, SetLogTags);
133     FRIEND_TEST(DebugLoggerTest, Disable);
134 };
135 
136 #ifdef HIPERF_DEBUG_PRINTF
137 #ifndef printf
138 #define printf(format, ...)                                                                        \
139     do {                                                                                           \
140         std::printf(format, ##__VA_ARGS__);                                                        \
141         DebugLogger::GetInstance()->Log(LEVEL_STDOUT, HILOG_TAG, format, ##__VA_ARGS__);           \
142     } while (0)
143 #endif
144 
145 #ifndef perror
146 #define perror(format, ...)                                                                        \
147     do {                                                                                           \
148         std::perror(format);                                                                       \
149         DebugLogger::GetInstance()->Log(LEVEL_STDOUT, HILOG_TAG, format "<%d:%s>\n",               \
150             ##__VA_ARGS__, errno, strerror(errno));                                                \
151     } while (0)
152 #endif
153 #endif
154 
155 class ScopeDebugLevel {
156 public:
157     ScopeDebugLevel(DebugLevel level, bool mix = false);
158     ~ScopeDebugLevel();
159 
160 private:
161     DebugLevel savedDebugLevel_;
162     bool savedMixOutput_ = false; // log mix to std
163 };
164 #define TempMixLogLevel(level) ScopeDebugLevel tempLogLevel(level, true)
165 
166 #else
167 #error not impl
168 #endif
169 
170 #define LOG_LEVEL(LEVEL)  LOG_##LEVEL
171 #define LOG_LEVEL_MUCH    "M:"
172 #define LOG_LEVEL_VERBOSE "V:"
173 #define LOG_LEVEL_DEBUG   "D:"
174 #define LOG_LEVEL_INFO    "I:"
175 #define LOG_LEVEL_WARNING "W:"
176 #define LOG_LEVEL_ERROR   "E:"
177 #define LOG_LEVEL_FATAL   "F:"
178 
179 #define LOG_LEVEL_END ""
180 
181 #ifndef HLOG
182 #define HLOG(level, format, ...)                                                                   \
183     do {                                                                                           \
184         if (!DebugLogger::logDisabled_) {                                                          \
185             DebugLogger::GetInstance()->Log(level, HILOG_TAG,                                      \
186                 HILOG_TAG_NAME "/" LOG_LEVEL(level) "<%ld>[%s:%d]%s:" format LOG_LEVEL_END "\n",   \
187                 get_thread_id(), SHORT_FILENAME, __LINE__, __FUNCTION__, ##__VA_ARGS__);                  \
188         }                                                                                          \
189     } while (0)
190 #endif
191 
192 // only log first n times
193 #ifndef HLOGV_FIRST
194 #define HLOGV_FIRST(first, format, ...)                                                            \
195     do {                                                                                           \
196         static int limit = first;                                                                  \
197         if (limit > 0) {                                                                           \
198             HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__);                                            \
199             if (--limit == 0) {                                                                    \
200                 HLOG(LEVEL_VERBOSE, " nexttime log will be suppressed...");                        \
201             }                                                                                      \
202         }                                                                                          \
203     } while (0)
204 #endif
205 
206 #ifndef HLOGV_FIRST_LOCAL
207 #define HLOGV_FIRST_LOCAL(local_limit, format, ...)                                                \
208     {                                                                                              \
209         if (local_limit != 0) {                                                                    \
210             HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__);                                            \
211             if (local_limit > 0 && --local_limit == 0) {                                           \
212                 HLOG(LEVEL_VERBOSE, " nexttime log will be suppressed...");                        \
213             }                                                                                      \
214         }                                                                                          \
215     }
216 #endif
217 
218 #ifndef HLOGV
219 #define HLOGV_IF(condition, format, ...)                                                           \
220     if (condition) {                                                                               \
221         HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__)                                                 \
222     }
223 #define HLOGVVV HLOGV
224 #endif
225 
226 #ifndef HLOGDUMMY
227 #define HLOGDUMMY(format, ...) while (0)
228 #endif
229 
230 #ifndef HLOGM
231 #define HLOGM(format, ...) HLOG(LEVEL_MUCH, format, ##__VA_ARGS__)
232 #define HLOGMMM            HLOGM
233 #endif
234 
235 #ifndef HLOGV
236 #define HLOGV(format, ...) HLOG(LEVEL_VERBOSE, format, ##__VA_ARGS__)
237 #endif
238 
239 #ifndef HLOGD
240 #define HLOGD(format, ...) HLOG(LEVEL_DEBUG, format, ##__VA_ARGS__)
241 #define HLOGDDD            HLOGM
242 #endif
243 
244 #ifndef HLOGI
245 #define HLOGI(format, ...) HLOG(LEVEL_INFO, format, ##__VA_ARGS__)
246 #endif
247 
248 #ifndef HLOGW
249 #define HLOGW(format, ...) HLOG(LEVEL_WARNING, format, ##__VA_ARGS__)
250 #endif
251 
252 #ifndef HLOGE
253 #define HLOGE(format, ...) HLOG(LEVEL_ERROR, format, ##__VA_ARGS__)
254 #endif
255 
256 #ifndef HLOGEP
257 #define HLOGEP(format, ...)                                                                        \
258     HLOG(LEVEL_ERROR, format "(errno %d:%s)", ##__VA_ARGS__, errno, strerror(errno))
259 #endif
260 
261 #ifndef HLOGF
262 #define HLOGF(format, ...)                                                                         \
263     HLOG(LEVEL_FATAL, "FATAL error at %s:%d " format, __FILE__, __LINE__, ##__VA_ARGS__)
264 #endif
265 
266 #ifndef HLOG_ASSERT_MESSAGE
267 #define HLOG_ASSERT_MESSAGE(condition, format, ...)                                                \
268     if (!(condition)) {                                                                            \
269         HLOG(LEVEL_FATAL, " assert failed: '%s' " format, #condition, ##__VA_ARGS__);              \
270     }
271 #endif
272 
273 #ifndef HLOG_ASSERT
274 #define HLOG_ASSERT(condition) HLOG_ASSERT_MESSAGE(condition, "")
275 #endif
276 
277 #undef assert
278 } // namespace NativeDaemon
279 } // namespace Developtools
280 } // namespace OHOS
281 #endif // _HIPERF_DEBUG_H_