MiniOB 1
MiniOB is one mini database, helping developers to learn how database works.
载入中...
搜索中...
未找到
log.h
1/* Copyright (c) 2021 OceanBase and/or its affiliates. All rights reserved.
2miniob is licensed under Mulan PSL v2.
3You can use this software according to the terms and conditions of the Mulan PSL v2.
4You may obtain a copy of Mulan PSL v2 at:
5 http://license.coscl.org.cn/MulanPSL2
6THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
7EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
8MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
9See the Mulan PSL v2 for more details. */
10
11//
12// Created by Longda on 2010
13//
14
15#pragma once
16
17#include <assert.h>
18#include <errno.h>
19#include <pthread.h>
20#include <string.h>
21#include <sys/time.h>
22
23#include "common/defs.h"
24#include "common/lang/string.h"
25#include "common/lang/map.h"
26#include "common/lang/set.h"
27#include "common/lang/functional.h"
28#include "common/lang/iostream.h"
29#include "common/lang/fstream.h"
30
31namespace common {
32
33const unsigned int ONE_KILO = 1024;
34const unsigned int FILENAME_LENGTH_MAX = 256; // the max filename length
35
36const int LOG_STATUS_OK = 0;
37const int LOG_STATUS_ERR = 1;
38const int LOG_MAX_LINE = 100000;
39
40typedef enum
41{
42 LOG_LEVEL_PANIC = 0,
43 LOG_LEVEL_ERR = 1,
44 LOG_LEVEL_WARN = 2,
45 LOG_LEVEL_INFO = 3,
46 LOG_LEVEL_DEBUG = 4,
47 LOG_LEVEL_TRACE = 5,
48 LOG_LEVEL_LAST
49} LOG_LEVEL;
50
51typedef enum
52{
53 LOG_ROTATE_BYDAY = 0,
54 LOG_ROTATE_BYSIZE,
55 LOG_ROTATE_LAST
56} LOG_ROTATE;
57
58class Log
59{
60public:
61 Log(const string &log_name, const LOG_LEVEL log_level = LOG_LEVEL_INFO,
62 const LOG_LEVEL console_level = LOG_LEVEL_WARN);
63 ~Log(void);
64
65 static int init(const string &log_file);
66
74 template <class T>
75 Log &operator<<(T message);
76
77 template <class T>
78 int panic(T message);
79
80 template <class T>
81 int error(T message);
82
83 template <class T>
84 int warnning(T message);
85
86 template <class T>
87 int info(T message);
88
89 template <class T>
90 int debug(T message);
91
92 template <class T>
93 int trace(T message);
94
95 int output(const LOG_LEVEL level, const char *module, const char *prefix, const char *f, ...);
96
97 int set_console_level(const LOG_LEVEL console_level);
98 LOG_LEVEL get_console_level();
99
100 int set_log_level(const LOG_LEVEL log_level);
101 LOG_LEVEL get_log_level();
102
103 int set_rotate_type(LOG_ROTATE rotate_type);
104 LOG_ROTATE get_rotate_type();
105
106 const char *prefix_msg(const LOG_LEVEL level);
107
113 void set_default_module(const string &modules);
114 bool check_output(const LOG_LEVEL log_level, const char *module);
115
116 int rotate(const int year = 0, const int month = 0, const int day = 0);
117
123 void set_context_getter(function<intptr_t()> context_getter);
124 intptr_t context_id();
125
126private:
127 void check_param_valid();
128
129 int rotate_by_size();
130 int rename_old_logs();
131 int rotate_by_day(const int year, const int month, const int day);
132
133 template <class T>
134 int out(const LOG_LEVEL console_level, const LOG_LEVEL log_level, T &message);
135
136private:
137 pthread_mutex_t lock_;
138 ofstream ofs_;
139 string log_name_;
140 LOG_LEVEL log_level_;
141 LOG_LEVEL console_level_;
142
143 typedef struct _LogDate
144 {
145 int year_;
146 int mon_;
147 int day_;
148 } LogDate;
149 LogDate log_date_;
150 int log_line_;
151 int log_max_line_;
152 LOG_ROTATE rotate_type_;
153
154 typedef map<LOG_LEVEL, string> LogPrefixMap;
155 LogPrefixMap prefix_map_;
156
157 typedef set<string> DefaultSet;
158 DefaultSet default_set_;
159
160 function<intptr_t()> context_getter_;
161};
162
164{
165public:
167 virtual ~LoggerFactory();
168
169 static int init(const string &log_file, Log **logger, LOG_LEVEL log_level = LOG_LEVEL_INFO,
170 LOG_LEVEL console_level = LOG_LEVEL_WARN, LOG_ROTATE rotate_type = LOG_ROTATE_BYDAY);
171
172 static int init_default(const string &log_file, LOG_LEVEL log_level = LOG_LEVEL_INFO,
173 LOG_LEVEL console_level = LOG_LEVEL_WARN, LOG_ROTATE rotate_type = LOG_ROTATE_BYDAY);
174};
175
176extern Log *g_log;
177
178#ifndef __FILE_NAME__
179#define __FILE_NAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
180#endif
181
182#define LOG_HEAD_SIZE 128
183
184#define LOG_HEAD(prefix, level) \
185 if (common::g_log) { \
186 struct timeval tv; \
187 gettimeofday(&tv, NULL); \
188 struct tm curr_time; \
189 struct tm *p = localtime_r(&tv.tv_sec, &curr_time); \
190 \
191 char sz_head[LOG_HEAD_SIZE] = {0}; \
192 if (p) { \
193 int usec = (int)tv.tv_usec; \
194 snprintf(sz_head, \
195 LOG_HEAD_SIZE, \
196 "%04d-%02d-%02d %02d:%02d:%02u.%06d pid:%u tid:%llx ctx:%lx", \
197 p->tm_year + 1900, \
198 p->tm_mon + 1, \
199 p->tm_mday, \
200 p->tm_hour, \
201 p->tm_min, \
202 p->tm_sec, \
203 usec, \
204 (int32_t)getpid(), \
205 gettid(), \
206 common::g_log->context_id()); \
207 common::g_log->rotate(p->tm_year + 1900, p->tm_mon + 1, p->tm_mday); \
208 } \
209 snprintf(prefix, \
210 sizeof(prefix), \
211 "[%s %s %s@%s:%u] >> ", \
212 sz_head, \
213 (common::g_log)->prefix_msg(level), \
214 __FUNCTION__, \
215 __FILE_NAME__, \
216 (int32_t)__LINE__); \
217 }
218
219#define LOG_OUTPUT(level, fmt, ...) \
220 do { \
221 using namespace common; \
222 if (g_log && g_log->check_output(level, __FILE_NAME__)) { \
223 char prefix[ONE_KILO] = {0}; \
224 LOG_HEAD(prefix, level); \
225 g_log->output(level, __FILE_NAME__, prefix, fmt, ##__VA_ARGS__); \
226 } \
227 } while (0)
228
229#define LOG_DEFAULT(fmt, ...) LOG_OUTPUT(common::g_log->get_log_level(), fmt, ##__VA_ARGS__)
230#define LOG_PANIC(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_PANIC, fmt, ##__VA_ARGS__)
231#define LOG_ERROR(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_ERR, fmt, ##__VA_ARGS__)
232#define LOG_WARN(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
233#define LOG_INFO(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
234#define LOG_DEBUG(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
235#define LOG_TRACE(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
236
237template <class T>
239{
240 // at this time, the input level is the default log level
241 out(console_level_, log_level_, msg);
242 return *this;
243}
244
245template <class T>
246int Log::panic(T message)
247{
248 return out(LOG_LEVEL_PANIC, LOG_LEVEL_PANIC, message);
249}
250
251template <class T>
252int Log::error(T message)
253{
254 return out(LOG_LEVEL_ERR, LOG_LEVEL_ERR, message);
255}
256
257template <class T>
258int Log::warnning(T message)
259{
260 return out(LOG_LEVEL_WARN, LOG_LEVEL_WARN, message);
261}
262
263template <class T>
264int Log::info(T message)
265{
266 return out(LOG_LEVEL_INFO, LOG_LEVEL_INFO, message);
267}
268
269template <class T>
270int Log::debug(T message)
271{
272 return out(LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG, message);
273}
274
275template <class T>
276int Log::trace(T message)
277{
278 return out(LOG_LEVEL_TRACE, LOG_LEVEL_TRACE, message);
279}
280
281template <class T>
282int Log::out(const LOG_LEVEL console_level, const LOG_LEVEL log_level, T &msg)
283{
284 bool locked = false;
285 if (console_level < LOG_LEVEL_PANIC || console_level > console_level_ || log_level < LOG_LEVEL_PANIC ||
286 log_level > log_level_) {
287 return LOG_STATUS_OK;
288 }
289 try {
290 char prefix[ONE_KILO] = {0};
291 LOG_HEAD(prefix, log_level);
292 if (LOG_LEVEL_PANIC <= console_level && console_level <= console_level_) {
293 cout << prefix_map_[console_level] << msg;
294 }
295
296 if (LOG_LEVEL_PANIC <= log_level && log_level <= log_level_) {
297 pthread_mutex_lock(&lock_);
298 locked = true;
299 ofs_ << prefix;
300 ofs_ << msg;
301 ofs_.flush();
302 log_line_++;
303 pthread_mutex_unlock(&lock_);
304 locked = false;
305 }
306 } catch (exception &e) {
307 if (locked) {
308 pthread_mutex_unlock(&lock_);
309 }
310 cerr << e.what() << endl;
311 return LOG_STATUS_ERR;
312 }
313
314 return LOG_STATUS_OK;
315}
316
317#ifndef ASSERT
318#ifdef DEBUG
319#define ASSERT(expression, description, ...) \
320 do { \
321 if (!(expression)) { \
322 LOG_PANIC(description, ##__VA_ARGS__); \
323 LOG_PANIC("%s", lbt()); \
324 assert(expression); \
325 } \
326 } while (0)
327
328#else // DEBUG
329#define ASSERT(expression, description, ...) \
330 do { \
331 (void)(expression); \
332 } while (0)
333#endif // DEBUG
334
335#endif // ASSERT
336
337#ifndef TRACE
338#ifdef DEBUG
339#define TRACE(format, ...) LOG_TRACE(format, ##__VA_ARGS__)
340#else // DEBUG
341#define TRACE(...)
342#endif // DEBUG
343
344#endif // TRACE
345
346#define SYS_OUTPUT_FILE_POS ", File:" << __FILE__ << ", line:" << __LINE__ << ",function:" << __FUNCTION__
347#define SYS_OUTPUT_ERROR ",error:" << errno << ":" << strerror(errno)
348
355const char *lbt();
356
357} // namespace common
Definition: log.h:59
void set_context_getter(function< intptr_t()> context_getter)
设置一个在日志中打印当前上下文信息的回调函数
Definition: log.cpp:307
void set_default_module(const string &modules)
Definition: log.cpp:172
Log & operator<<(T message)
Definition: log.h:238
Definition: log.h:164
Definition: log.h:144