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 OHOS_PROFILER_LOGGING_H
17 #define OHOS_PROFILER_LOGGING_H
18
19 #define EXPORT_API __attribute__((visibility("default")))
20
21 #undef NDEBUG
22
23 #ifndef LOG_TAG
24 #define LOG_TAG "Hiprofiler"
25 #endif
26
27 #define PROFILER_SUBSYSTEM 0xD002D0C
28 #ifndef LOG_DOMAIN
29 #define LOG_DOMAIN PROFILER_SUBSYSTEM
30 #endif
31
32 #ifndef UNUSED_PARAMETER
33 #define UNUSED_PARAMETER(x) ((void)(x))
34 #endif
35
36 #ifdef HAVE_HILOG
37 #include "hilog/log.h"
38 #include <string>
39 #else // HAVE_HILOG
40 #include <mutex>
41 #include <string>
42 #include <securec.h>
43 #include <stdarg.h>
44 #if !is_mingw
45 #include <sys/syscall.h>
46 #undef getsystid
47 #define getsystid() syscall(SYS_gettid)
48 #else
49 #include "windows.h"
getsystid()50 inline long getsystid()
51 {
52 return GetCurrentThreadId();
53 }
54 #endif
55 #include <time.h>
56 #include <unistd.h>
57 #include <vector>
58
GetTid(void)59 static inline long GetTid(void)
60 {
61 return getsystid();
62 }
63
64 enum {
65 LOG_UNKNOWN = 0,
66 LOG_DEFAULT,
67 LOG_VERBOSE,
68 LOG_DEBUG,
69 LOG_INFO,
70 LOG_WARN,
71 LOG_ERROR,
72 LOG_FATAL,
73 LOG_SILENT,
74 };
75
76 namespace {
77 constexpr int NS_PER_MS_LOG = 1000 * 1000;
78 }
79
80 static inline std::string GetTimeStr();
81
82 typedef const char* ConstCharPtr;
83
HiLogPrintArgs(int prio,int domain,ConstCharPtr tag,ConstCharPtr fmt,va_list vargs)84 static inline int HiLogPrintArgs(int prio, int domain, ConstCharPtr tag, ConstCharPtr fmt, va_list vargs)
85 {
86 static std::mutex mtx;
87 static std::vector<std::string> prioNames = {"U", " ", "V", "D", "I", "W", "E", "F", "S"};
88 std::unique_lock<std::mutex> lock(mtx);
89 int count = fprintf(stderr, "%04x %s %7d %7ld %5s %s ", domain, GetTimeStr().c_str(), getpid(), GetTid(),
90 prioNames[prio].c_str(), tag);
91 if (count < 0) {
92 return 0;
93 }
94 count = count + vfprintf(stderr, fmt, vargs) + fprintf(stderr, "\n");
95 fflush(stderr);
96 return count;
97 }
98
HiLogPrint(int type,int prio,int domain,ConstCharPtr tag,ConstCharPtr fmt,...)99 static inline int HiLogPrint(int type, int prio, int domain, ConstCharPtr tag, ConstCharPtr fmt, ...)
100 {
101 va_list vargs;
102 UNUSED_PARAMETER(type);
103 va_start(vargs, fmt);
104 int count = HiLogPrintArgs(prio, domain, tag, fmt, vargs);
105 va_end(vargs);
106 return count;
107 }
108
109 #ifndef LOG_CORE
110 #define LOG_CORE 0
111 #endif
112
113 #define HILOG_DEBUG(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_DEBUG, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
114 #define HILOG_INFO(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_INFO, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
115 #define HILOG_WARN(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_WARN, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
116 #define HILOG_ERROR(LOG_CORE, fmt, ...) HiLogPrint(LOG_CORE, LOG_ERROR, LOG_DOMAIN, LOG_TAG, fmt, ##__VA_ARGS__)
117
118 #endif // HAVE_HILOG
119
120 #ifndef NDEBUG
121 #include <securec.h>
122 namespace logging {
StringReplace(std::string & str,const std::string & oldStr,const std::string & newStr)123 inline void StringReplace(std::string& str, const std::string& oldStr, const std::string& newStr)
124 {
125 std::string::size_type pos = 0u;
126 while ((pos = str.find(oldStr, pos)) != std::string::npos) {
127 str.replace(pos, oldStr.length(), newStr);
128 pos += newStr.length();
129 }
130 }
131
132 // let compiler check format string and variable arguments
133 static inline std::string StringFormat(const char* fmt, ...) __attribute__((format(printf, 1, 2)));
134
StringFormat(const char * fmt,...)135 static inline std::string StringFormat(const char* fmt, ...)
136 {
137 va_list vargs;
138 char buf[1024] = {0};
139
140 if (fmt == nullptr) {
141 return "";
142 }
143 std::string format(fmt);
144 StringReplace(format, "%{public}", "%");
145
146 va_start(vargs, fmt);
147 if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, format.c_str(), vargs) < 0) {
148 va_end(vargs);
149 return "";
150 }
151
152 va_end(vargs);
153 return buf;
154 }
155 } // logging
156
157 #ifdef HILOG_DEBUG
158 #undef HILOG_DEBUG
159 #endif
160
161 #ifdef HILOG_INFO
162 #undef HILOG_INFO
163 #endif
164
165 #ifdef HILOG_WARN
166 #undef HILOG_WARN
167 #endif
168
169 #ifdef HILOG_ERROR
170 #undef HILOG_ERROR
171 #endif
172
173 #ifdef HILOG_PRINT
174 #undef HILOG_PRINT
175 #endif
176
177 #ifdef HAVE_HILOG
178 #define HILOG_PRINT(type, level, fmt, ...) \
179 HiLogPrint(type, level, LOG_DOMAIN, LOG_TAG, "%{public}s", logging::StringFormat(fmt, ##__VA_ARGS__).c_str())
180 #else
181 #define HILOG_PRINT(type, level, fmt, ...) \
182 HiLogPrint(type, level, LOG_DOMAIN, LOG_TAG, "%s", logging::StringFormat(fmt, ##__VA_ARGS__).c_str())
183 #endif
184
185 #define HILOG_DEBUG(type, fmt, ...) HILOG_PRINT(type, LOG_DEBUG, fmt, ##__VA_ARGS__)
186 #define HILOG_INFO(type, fmt, ...) HILOG_PRINT(type, LOG_INFO, fmt, ##__VA_ARGS__)
187 #define HILOG_WARN(type, fmt, ...) HILOG_PRINT(type, LOG_WARN, fmt, ##__VA_ARGS__)
188 #define HILOG_ERROR(type, fmt, ...) HILOG_PRINT(type, LOG_ERROR, fmt, ##__VA_ARGS__)
189 #endif // NDEBUG
190
191 #define STD_PTR(K, T) std::K##_ptr<T>
192
193 #define NO_RETVAL /* retval */
194
195 #define CHECK_NOTNULL(ptr, retval, fmt, ...) \
196 do { \
197 if (ptr == nullptr) { \
198 HILOG_WARN(LOG_CORE, "CHECK_NOTNULL(%s) in %s:%d FAILED, " fmt, #ptr, __func__, \
199 __LINE__, ##__VA_ARGS__); \
200 return retval; \
201 } \
202 } while (0)
203
204 #ifndef FUZZ_TEST
205 #define CHECK_TRUE(expr, retval, fmt, ...) \
206 do { \
207 if (!(expr)) { \
208 HILOG_WARN(LOG_CORE, "CHECK_TRUE(%s) in %s:%d FAILED, " fmt, #expr, __func__, __LINE__, ##__VA_ARGS__); \
209 return retval; \
210 } \
211 } while (0)
212 #else
213 #define CHECK_TRUE(expr, retval, fmt, ...) \
214 do { \
215 if (!(expr)) { \
216 return retval; \
217 } \
218 } while (0)
219 #endif // FUZZ_TEST
220
221 #define RETURN_IF(expr, retval, fmt, ...) \
222 do { \
223 if ((expr)) { \
224 HILOG_WARN(LOG_CORE, fmt, ##__VA_ARGS__); \
225 return retval; \
226 } \
227 } while (0)
228
229 #ifndef HAVE_HILOG
GetTimeStr()230 static std::string GetTimeStr()
231 {
232 char timeStr[64];
233 struct timespec ts;
234 struct tm tmStruct;
235 clock_gettime(CLOCK_REALTIME, &ts);
236 #if !is_mingw
237 localtime_r(&ts.tv_sec, &tmStruct);
238 #else
239 CHECK_TRUE(localtime_s(&tmStruct, &ts.tv_sec) == 0, "", "localtime_s FAILED!");
240 #endif
241 size_t used = strftime(timeStr, sizeof(timeStr), "%m-%d %H:%M:%S", &tmStruct);
242 snprintf_s(&timeStr[used], sizeof(timeStr) - used, sizeof(timeStr) - used - 1, ".%03ld",
243 ts.tv_nsec / NS_PER_MS_LOG);
244 return timeStr;
245 }
246 #endif // !HAVE_HILOG
247 #endif // OHOS_PROFILER_LOGGING_H
248