• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2022. 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 _HHLOG_H
17 #define _HHLOG_H
18 
19 #include <atomic>
20 #include <cstdio>
21 #include <cstring>
22 #include <ctime>
23 #include <iostream>
24 #include <memory>
25 #include <sstream>
26 #include <string>
27 #include <strstream>
28 #include <thread>
29 
30 #include <fcntl.h>
31 #include <securec.h>
32 #include <stdarg.h>
33 #include <unistd.h>
34 #include <sys/time.h>
35 
36 #include "ringbuffer.h"
37 
38 enum HHLOG_LEVEL:int {
39     HHLOG_DEBUG = 0,
40     HHLOG_INFO = 1,
41     HHLOG_WARN = 2,
42     HHLOG_ERROR = 3,
43     HHLOG_FATAL = 4,
44     HHLOG_NONE = 5,
45 };
46 
47 class HHLogger {
48 public:
49     ~HHLogger();
GetInstance()50     static inline HHLogger& GetInstance()
51     {
52         static HHLogger logger {};
53         return logger;
54     }
55 
56     int Start(const int logLevel = HHLOG_DEBUG, const std::string& logFile = "./hhlog.txt");
57 
PutLog(const char * format,...)58     inline int PutLog(const char* format, ...)
59     {
60         va_list args;
61         va_start(args, format);
62         auto ftime = GetFormatTime();
63         std::size_t nbytes = ftime.length();
64         if (nbytes == 0 or nbytes >= MAX_HHLOG_SIZE) {
65             return -1;
66         }
67         char buffer[MAX_HHLOG_SIZE];
68         if (memcpy_s(buffer, sizeof(buffer), ftime.c_str(), nbytes) != EOK) {
69             return -1;
70         }
71         int ret = vsnprintf_s(buffer + nbytes, sizeof(buffer) - nbytes,
72                               sizeof(buffer) - nbytes - 1, format, args);
73         va_end(args);
74         if (ret < 0) {
75             return -1;
76         }
77         nbytes += static_cast<std::size_t>(ret);
78         if (nbytes >= MAX_HHLOG_SIZE) {
79             return -1;
80         }
81         buffer[nbytes++] = '\n';
82         return buf_->Put(buffer, nbytes);
83     }
84 
GetLogLevel()85     inline int GetLogLevel() const
86     {
87         return logLevel_;
88     }
89 
IsStopped()90     inline bool IsStopped()
91     {
92         return stop_.load();
93     }
94 
LogSaver()95     inline void LogSaver()
96     {
97         if (logLevel_ == HHLOG_NONE) {
98             return;
99         }
100         logSaver_ = std::thread(&HHLogger::SaveLog, this);
101     }
102 
103     enum SizeConsts:std::size_t {
104         RING_BUF_SIZE = 4096,
105         MAX_FORMAT_SIZE = 512,
106         MAX_HHLOG_SIZE = 1024,
107     };
108 
109 private:
110     HHLogger() = default;
111     std::string GetLogFileName() const;
112     std::string GetFormatTime() const;
113     int SaveLog();
114     int InitLogger(const int logLevel, const std::string& logFile);
115     int UpdateTimer();
116 
117     int fd_ {-1};
118     int logLevel_ {HHLOG_NONE};
119     std::atomic<bool> stop_ {false};
120     std::atomic<struct timeval> timer_;
121     std::unique_ptr<RingBuffer> buf_ {nullptr};
122     std::thread logSaver_;
123 };
124 
125 #define HHLOG(level, expression, format, ...) {                           \
126     if ((expression) and                                                    \
127         (!HHLogger::GetInstance().IsStopped()) and                          \
128         (HHLogger::GetInstance().GetLogLevel() <= HHLOG_##level)) {         \
129         const char prefix[] {" [" #level "] %s %d %s: %s"};                 \
130         char buffer[HHLogger::MAX_FORMAT_SIZE];                             \
131         (void)snprintf_s(buffer, sizeof(buffer), sizeof(buffer) -1,         \
132                          prefix, __FILE__, __LINE__, __FUNCTION__, format);  \
133         HHLogger::GetInstance().PutLog(buffer, ##__VA_ARGS__);              \
134     }                                                                       \
135 }
136 
137 #if defined(HH_LOGGER_DEBUG)
138 
139 #define HHLOGD(expression, format, ...) HHLOG(DEBUG, expression, format, ##__VA_ARGS__)
140 #define HHLOGI(expression, format, ...) HHLOG(INFO, expression, format, ##__VA_ARGS__)
141 #define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__)
142 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
143 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
144 
145 #elif defined(HH_LOGGER_INFO)
146 
147 #define HHLOGD(expression, format, ...) {}
148 #define HHLOGI(expression, format, ...) HHLOG(INFO, expression, format, ##__VA_ARGS__)
149 #define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__)
150 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
151 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
152 
153 #elif defined(HH_LOGGER_WARN)
154 
155 #define HHLOGD(expression, format, ...) {}
156 #define HHLOGI(expression, format, ...) {}
157 #define HHLOGW(expression, format, ...) HHLOG(WARN, expression, format, ##__VA_ARGS__)
158 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
159 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
160 
161 #elif defined(HH_LOGGER_ERROR)
162 
163 #define HHLOGD(expression, format, ...) {}
164 #define HHLOGI(expression, format, ...) {}
165 #define HHLOGW(expression, format, ...) {}
166 #define HHLOGE(expression, format, ...) HHLOG(ERROR, expression, format, ##__VA_ARGS__)
167 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
168 
169 #elif defined(HH_LOGGER_FATAL)
170 
171 #define HHLOGD(expression, format, ...) {}
172 #define HHLOGI(expression, format, ...) {}
173 #define HHLOGW(expression, format, ...) {}
174 #define HHLOGE(expression, format, ...) {}
175 #define HHLOGF(expression, format, ...) HHLOG(FATAL, expression, format, ##__VA_ARGS__)
176 
177 #else
178 
179 #define HHLOGD(expression, format, ...) {}
180 #define HHLOGI(expression, format, ...) {}
181 #define HHLOGW(expression, format, ...) {}
182 #define HHLOGE(expression, format, ...) {}
183 #define HHLOGF(expression, format, ...) {}
184 
185 #endif
186 
187 #define CHECK_NOTNULL(ptr, retval, fmt, ...)                                                                        \
188     do {                                                                                                            \
189         if (ptr == nullptr) {                                                                                       \
190             HHLOGE(true, "CHECK_NOTNULL(%s) in %s:%d FAILED, " fmt, #ptr, __func__, \
191                        __LINE__, ##__VA_ARGS__);                                                                    \
192             return retval;                                                                                          \
193         }                                                                                                           \
194     } while (0)
195 
196 #define CHECK_TRUE(expr, retval, fmt, ...)                                                                          \
197     do {                                                                                                            \
198         if (!(expr)) {                                                                                              \
199             HHLOGE(true, "CHECK_TRUE(%s) in %s:%d FAILED, " fmt, #expr, __func__, __LINE__, ##__VA_ARGS__);     \
200             return retval;                                                                                          \
201         }                                                                                                           \
202     } while (0)
203 
204 #endif  // HHLOG_H