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
73 template <class T>
74 Log &operator<<(T message);
75
76 template <class T>
77 int panic(T message);
78
79 template <class T>
80 int error(T message);
81
82 template <class T>
83 int warnning(T message);
84
85 template <class T>
86 int info(T message);
87
88 template <class T>
89 int debug(T message);
90
91 template <class T>
92 int trace(T message);
93
94 int output(const LOG_LEVEL level, const char *module, const char *prefix, const char *f, ...);
95
96 int set_console_level(const LOG_LEVEL console_level);
97 LOG_LEVEL get_console_level();
98
99 int set_log_level(const LOG_LEVEL log_level);
100 LOG_LEVEL get_log_level();
101
102 int set_rotate_type(LOG_ROTATE rotate_type);
103 LOG_ROTATE get_rotate_type();
104
105 const char *prefix_msg(const LOG_LEVEL level);
106
112 void set_default_module(const string &modules);
113 bool check_output(const LOG_LEVEL log_level, const char *module);
114
115 int rotate(const int year = 0, const int month = 0, const int day = 0);
116
122 void set_context_getter(function<intptr_t()> context_getter);
123 intptr_t context_id();
124
125private:
126 void check_param_valid();
127
128 int rotate_by_size();
129 int rename_old_logs();
130 int rotate_by_day(const int year, const int month, const int day);
131
132 template <class T>
133 int out(const LOG_LEVEL console_level, const LOG_LEVEL log_level, T &message);
134
135private:
136 pthread_mutex_t lock_;
137 ofstream ofs_;
138 string log_name_;
139 LOG_LEVEL log_level_;
140 LOG_LEVEL console_level_;
141
142 typedef struct _LogDate
143 {
144 int year_;
145 int mon_;
146 int day_;
147 } LogDate;
148 LogDate log_date_;
149 int log_line_;
150 int log_max_line_;
151 LOG_ROTATE rotate_type_;
152
153 typedef map<LOG_LEVEL, string> LogPrefixMap;
154 LogPrefixMap prefix_map_;
155
156 typedef set<string> DefaultSet;
157 DefaultSet default_set_;
158
159 function<intptr_t()> context_getter_;
160};
161
163{
164public:
166 virtual ~LoggerFactory();
167
168 static int init(const string &log_file, Log **logger, LOG_LEVEL log_level = LOG_LEVEL_INFO,
169 LOG_LEVEL console_level = LOG_LEVEL_WARN, LOG_ROTATE rotate_type = LOG_ROTATE_BYDAY);
170
171 static int init_default(const string &log_file, LOG_LEVEL log_level = LOG_LEVEL_INFO,
172 LOG_LEVEL console_level = LOG_LEVEL_WARN, LOG_ROTATE rotate_type = LOG_ROTATE_BYDAY);
173};
174
175extern Log *g_log;
176
177#ifndef __FILE_NAME__
178#define __FILE_NAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
179#endif
180
181#define LOG_HEAD_SIZE 128
182
183#define LOG_HEAD(prefix, level) \
184 if (common::g_log) { \
185 struct timeval tv; \
186 gettimeofday(&tv, NULL); \
187 struct tm curr_time; \
188 struct tm *p = localtime_r(&tv.tv_sec, &curr_time); \
189 \
190 char sz_head[LOG_HEAD_SIZE] = {0}; \
191 if (p) { \
192 int usec = (int)tv.tv_usec; \
193 snprintf(sz_head, \
194 LOG_HEAD_SIZE, \
195 "%04d-%02d-%02d %02d:%02d:%02u.%06d pid:%u tid:%llx ctx:%lx", \
196 p->tm_year + 1900, \
197 p->tm_mon + 1, \
198 p->tm_mday, \
199 p->tm_hour, \
200 p->tm_min, \
201 p->tm_sec, \
202 usec, \
203 (int32_t)getpid(), \
204 gettid(), \
205 common::g_log->context_id()); \
206 common::g_log->rotate(p->tm_year + 1900, p->tm_mon + 1, p->tm_mday); \
207 } \
208 snprintf(prefix, \
209 sizeof(prefix), \
210 "[%s %s %s@%s:%u] >> ", \
211 sz_head, \
212 (common::g_log)->prefix_msg(level), \
213 __FUNCTION__, \
214 __FILE_NAME__, \
215 (int32_t)__LINE__); \
216 }
217
218#define LOG_OUTPUT(level, fmt, ...) \
219 do { \
220 using namespace common; \
221 if (g_log && g_log->check_output(level, __FILE_NAME__)) { \
222 char prefix[ONE_KILO] = {0}; \
223 LOG_HEAD(prefix, level); \
224 g_log->output(level, __FILE_NAME__, prefix, fmt, ##__VA_ARGS__); \
225 } \
226 } while (0)
227
228#define LOG_DEFAULT(fmt, ...) LOG_OUTPUT(common::g_log->get_log_level(), fmt, ##__VA_ARGS__)
229#define LOG_PANIC(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_PANIC, fmt, ##__VA_ARGS__)
230#define LOG_ERROR(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_ERR, fmt, ##__VA_ARGS__)
231#define LOG_WARN(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_WARN, fmt, ##__VA_ARGS__)
232#define LOG_INFO(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_INFO, fmt, ##__VA_ARGS__)
233#define LOG_DEBUG(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)
234#define LOG_TRACE(fmt, ...) LOG_OUTPUT(common::LOG_LEVEL_TRACE, fmt, ##__VA_ARGS__)
235
236template <class T>
238{
239 // at this time, the input level is the default log level
240 out(console_level_, log_level_, msg);
241 return *this;
242}
243
244template <class T>
245int Log::panic(T message)
246{
247 return out(LOG_LEVEL_PANIC, LOG_LEVEL_PANIC, message);
248}
249
250template <class T>
251int Log::error(T message)
252{
253 return out(LOG_LEVEL_ERR, LOG_LEVEL_ERR, message);
254}
255
256template <class T>
257int Log::warnning(T message)
258{
259 return out(LOG_LEVEL_WARN, LOG_LEVEL_WARN, message);
260}
261
262template <class T>
263int Log::info(T message)
264{
265 return out(LOG_LEVEL_INFO, LOG_LEVEL_INFO, message);
266}
267
268template <class T>
269int Log::debug(T message)
270{
271 return out(LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG, message);
272}
273
274template <class T>
275int Log::trace(T message)
276{
277 return out(LOG_LEVEL_TRACE, LOG_LEVEL_TRACE, message);
278}
279
280template <class T>
281int Log::out(const LOG_LEVEL console_level, const LOG_LEVEL log_level, T &msg)
282{
283 bool locked = false;
284 if (console_level < LOG_LEVEL_PANIC || console_level > console_level_ || log_level < LOG_LEVEL_PANIC ||
285 log_level > log_level_) {
286 return LOG_STATUS_OK;
287 }
288 try {
289 char prefix[ONE_KILO] = {0};
290 LOG_HEAD(prefix, log_level);
291 if (LOG_LEVEL_PANIC <= console_level && console_level <= console_level_) {
292 cout << prefix_map_[console_level] << msg;
293 }
294
295 if (LOG_LEVEL_PANIC <= log_level && log_level <= log_level_) {
296 pthread_mutex_lock(&lock_);
297 locked = true;
298 ofs_ << prefix;
299 ofs_ << msg;
300 ofs_.flush();
301 log_line_++;
302 pthread_mutex_unlock(&lock_);
303 locked = false;
304 }
305 } catch (exception &e) {
306 if (locked) {
307 pthread_mutex_unlock(&lock_);
308 }
309 cerr << e.what() << endl;
310 return LOG_STATUS_ERR;
311 }
312
313 return LOG_STATUS_OK;
314}
315
316#ifndef ASSERT
317#ifdef DEBUG
318#define ASSERT(expression, description, ...) \
319 do { \
320 if (!(expression)) { \
321 LOG_PANIC(description, ##__VA_ARGS__); \
322 LOG_PANIC("%s", lbt()); \
323 assert(expression); \
324 } \
325 } while (0)
326
327#else // DEBUG
328#define ASSERT(expression, description, ...) \
329 do { \
330 (void)(expression); \
331 } while (0)
332#endif // DEBUG
333
334#endif // ASSERT
335
336#ifndef TRACE
337#ifdef DEBUG
338#define TRACE(format, ...) LOG_TRACE(format, ##__VA_ARGS__)
339#else // DEBUG
340#define TRACE(...)
341#endif // DEBUG
342
343#endif // TRACE
344
345#define SYS_OUTPUT_FILE_POS ", File:" << __FILE__ << ", line:" << __LINE__ << ",function:" << __FUNCTION__
346#define SYS_OUTPUT_ERROR ",error:" << errno << ":" << strerror(errno)
347
354const char *lbt();
355
356} // 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:237
Definition: log.h:163
Definition: log.h:143