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