Skip to content

Commit ccaedd1

Browse files
committed
Enable log info with different levels.
Summary: * Now each Log related function has a variant that takes an additional argument indicating its log level, which is one of the following: - DEBUG, INFO, WARN, ERROR, FATAL. * To ensure backward-compatibility, old version Log functions are kept unchanged. * Logger now has a member variable indicating its log level. Any incoming Log request which log level is lower than Logger's log level will not be output. * The output of the newer version Log will be prefixed by its log level. Test Plan: Add a LogType test in auto_roll_logger_test.cc = Sample log output = 2014/02/11-00:03:07.683895 7feded179840 [DEBUG] this is the message to be written to the log file!! 2014/02/11-00:03:07.683898 7feded179840 [INFO] this is the message to be written to the log file!! 2014/02/11-00:03:07.683900 7feded179840 [WARN] this is the message to be written to the log file!! 2014/02/11-00:03:07.683903 7feded179840 [ERROR] this is the message to be written to the log file!! 2014/02/11-00:03:07.683906 7feded179840 [FATAL] this is the message to be written to the log file!! Reviewers: dhruba, xjin, kailiu Reviewed By: kailiu CC: leveldb Differential Revision: https://reviews.facebook.net/D16071
1 parent b2795b7 commit ccaedd1

File tree

6 files changed

+247
-25
lines changed

6 files changed

+247
-25
lines changed

include/rocksdb/env.h

+54-1
Original file line numberDiff line numberDiff line change
@@ -511,25 +511,56 @@ class Directory {
511511
virtual Status Fsync() = 0;
512512
};
513513

514+
enum InfoLogLevel {
515+
DEBUG = 0,
516+
INFO,
517+
WARN,
518+
ERROR,
519+
FATAL,
520+
NUM_INFO_LOG_LEVELS,
521+
};
522+
514523
// An interface for writing log messages.
515524
class Logger {
516525
public:
517526
enum { DO_NOT_SUPPORT_GET_LOG_FILE_SIZE = -1 };
518-
Logger() { }
527+
explicit Logger(const InfoLogLevel log_level = InfoLogLevel::ERROR)
528+
: log_level_(log_level) {}
519529
virtual ~Logger();
520530

521531
// Write an entry to the log file with the specified format.
522532
virtual void Logv(const char* format, va_list ap) = 0;
533+
534+
// Write an entry to the log file with the specified log level
535+
// and format. Any log with level under the internal log level
536+
// of *this (see @SetInfoLogLevel and @GetInfoLogLevel) will not be
537+
// printed.
538+
void Logv(const InfoLogLevel log_level, const char* format, va_list ap) {
539+
static const char* kInfoLogLevelNames[5] = {"DEBUG", "INFO", "WARN",
540+
"ERROR", "FATAL"};
541+
if (log_level < log_level_) {
542+
return;
543+
}
544+
char new_format[500];
545+
snprintf(new_format, sizeof(new_format) - 1, "[%s] %s",
546+
kInfoLogLevelNames[log_level], format);
547+
Logv(new_format, ap);
548+
}
523549
virtual size_t GetLogFileSize() const {
524550
return DO_NOT_SUPPORT_GET_LOG_FILE_SIZE;
525551
}
526552
// Flush to the OS buffers
527553
virtual void Flush() {}
554+
virtual InfoLogLevel GetInfoLogLevel() const { return log_level_; }
555+
virtual void SetInfoLogLevel(const InfoLogLevel log_level) {
556+
log_level_ = log_level;
557+
}
528558

529559
private:
530560
// No copying allowed
531561
Logger(const Logger&);
532562
void operator=(const Logger&);
563+
InfoLogLevel log_level_;
533564
};
534565

535566

@@ -547,7 +578,18 @@ class FileLock {
547578

548579
extern void LogFlush(const shared_ptr<Logger>& info_log);
549580

581+
extern void Log(const InfoLogLevel log_level,
582+
const shared_ptr<Logger>& info_log, const char* format, ...);
583+
584+
// a set of log functions with different log levels.
585+
extern void Debug(const shared_ptr<Logger>& info_log, const char* format, ...);
586+
extern void Info(const shared_ptr<Logger>& info_log, const char* format, ...);
587+
extern void Warn(const shared_ptr<Logger>& info_log, const char* format, ...);
588+
extern void Error(const shared_ptr<Logger>& info_log, const char* format, ...);
589+
extern void Fatal(const shared_ptr<Logger>& info_log, const char* format, ...);
590+
550591
// Log the specified data to *info_log if info_log is non-nullptr.
592+
// The default info log level is InfoLogLevel::ERROR.
551593
extern void Log(const shared_ptr<Logger>& info_log, const char* format, ...)
552594
# if defined(__GNUC__) || defined(__clang__)
553595
__attribute__((__format__ (__printf__, 2, 3)))
@@ -556,12 +598,23 @@ extern void Log(const shared_ptr<Logger>& info_log, const char* format, ...)
556598

557599
extern void LogFlush(Logger *info_log);
558600

601+
extern void Log(const InfoLogLevel log_level, Logger* info_log,
602+
const char* format, ...);
603+
604+
// The default info log level is InfoLogLevel::ERROR.
559605
extern void Log(Logger* info_log, const char* format, ...)
560606
# if defined(__GNUC__) || defined(__clang__)
561607
__attribute__((__format__ (__printf__, 2, 3)))
562608
# endif
563609
;
564610

611+
// a set of log functions with different log levels.
612+
extern void Debug(Logger* info_log, const char* format, ...);
613+
extern void Info(Logger* info_log, const char* format, ...);
614+
extern void Warn(Logger* info_log, const char* format, ...);
615+
extern void Error(Logger* info_log, const char* format, ...);
616+
extern void Fatal(Logger* info_log, const char* format, ...);
617+
565618
// A utility routine: write "data" to the named file.
566619
extern Status WriteStringToFile(Env* env, const Slice& data,
567620
const std::string& fname);

util/auto_roll_logger.h

+15-14
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,21 @@ namespace rocksdb {
1717
class AutoRollLogger : public Logger {
1818
public:
1919
AutoRollLogger(Env* env, const std::string& dbname,
20-
const std::string& db_log_dir,
21-
size_t log_max_size,
22-
size_t log_file_time_to_roll):
23-
dbname_(dbname),
24-
db_log_dir_(db_log_dir),
25-
env_(env),
26-
status_(Status::OK()),
27-
kMaxLogFileSize(log_max_size),
28-
kLogFileTimeToRoll(log_file_time_to_roll),
29-
cached_now(static_cast<uint64_t>(env_->NowMicros() * 1e-6)),
30-
ctime_(cached_now),
31-
cached_now_access_count(0),
32-
call_NowMicros_every_N_records_(100),
33-
mutex_() {
20+
const std::string& db_log_dir, size_t log_max_size,
21+
size_t log_file_time_to_roll,
22+
const InfoLogLevel log_level = InfoLogLevel::ERROR)
23+
: Logger(log_level),
24+
dbname_(dbname),
25+
db_log_dir_(db_log_dir),
26+
env_(env),
27+
status_(Status::OK()),
28+
kMaxLogFileSize(log_max_size),
29+
kLogFileTimeToRoll(log_file_time_to_roll),
30+
cached_now(static_cast<uint64_t>(env_->NowMicros() * 1e-6)),
31+
ctime_(cached_now),
32+
cached_now_access_count(0),
33+
call_NowMicros_every_N_records_(100),
34+
mutex_() {
3435
env->GetAbsolutePath(dbname, &db_absolute_path_);
3536
log_fname_ = InfoLogFileName(dbname_, db_absolute_path_, db_log_dir_);
3637
RollLogFile();

util/auto_roll_logger_test.cc

+57-5
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,8 @@ class AutoRollLoggerTest {
3939

4040
const string AutoRollLoggerTest::kSampleMessage(
4141
"this is the message to be written to the log file!!");
42-
const string AutoRollLoggerTest::kTestDir(
43-
test::TmpDir() + "/db_log_test");
44-
const string AutoRollLoggerTest::kLogFile(
45-
test::TmpDir() + "/db_log_test/LOG");
42+
const string AutoRollLoggerTest::kTestDir(test::TmpDir() + "/db_log_test");
43+
const string AutoRollLoggerTest::kLogFile(test::TmpDir() + "/db_log_test/LOG");
4644
Env* AutoRollLoggerTest::env = Env::Default();
4745

4846
// In this test we only want to Log some simple log message with
@@ -53,6 +51,11 @@ void LogMessage(Logger* logger, const char* message) {
5351
Log(logger, "%s", message);
5452
}
5553

54+
void LogMessage(const InfoLogLevel log_level, Logger* logger,
55+
const char* message) {
56+
Log(log_level, logger, "%s", message);
57+
}
58+
5659
void GetFileCreateTime(const std::string& fname, uint64_t* file_ctime) {
5760
struct stat s;
5861
if (stat(fname.c_str(), &s) != 0) {
@@ -64,6 +67,7 @@ void GetFileCreateTime(const std::string& fname, uint64_t* file_ctime) {
6467
void AutoRollLoggerTest::RollLogFileBySizeTest(AutoRollLogger* logger,
6568
size_t log_max_size,
6669
const string& log_message) {
70+
logger->SetInfoLogLevel(InfoLogLevel::INFO);
6771
// measure the size of each message, which is supposed
6872
// to be equal or greater than log_message.size()
6973
LogMessage(logger, log_message.c_str());
@@ -131,7 +135,6 @@ TEST(AutoRollLoggerTest, RollLogFileBySize) {
131135

132136
RollLogFileBySizeTest(&logger, log_max_size,
133137
kSampleMessage + ":RollLogFileBySize");
134-
135138
}
136139

137140
TEST(AutoRollLoggerTest, RollLogFileByTime) {
@@ -235,6 +238,55 @@ TEST(AutoRollLoggerTest, CreateLoggerFromOptions) {
235238
kSampleMessage + ":CreateLoggerFromOptions - both");
236239
}
237240

241+
TEST(AutoRollLoggerTest, InfoLogLevel) {
242+
InitTestDb();
243+
// the lengths of DEBUG, INFO, WARN, ERROR, FATAL respectively
244+
const int kInfoLogLevelNameLens[5] = {5, 4, 4, 5, 5};
245+
246+
size_t log_size = 8192;
247+
AutoRollLogger* logger =
248+
new AutoRollLogger(Env::Default(), kTestDir, "", log_size, 0);
249+
250+
int message_length = kSampleMessage.length();
251+
int log_length = 0;
252+
int total_logname_length = 0;
253+
for (int log_level = InfoLogLevel::FATAL; log_level >= InfoLogLevel::DEBUG;
254+
log_level--) {
255+
logger->SetInfoLogLevel((InfoLogLevel)log_level);
256+
total_logname_length += kInfoLogLevelNameLens[log_level];
257+
for (int log_type = InfoLogLevel::DEBUG; log_type <= InfoLogLevel::FATAL;
258+
log_type++) {
259+
// log messages with log level smaller than log_level will not be logged.
260+
LogMessage((InfoLogLevel)log_type, logger, kSampleMessage.c_str());
261+
}
262+
// 44 is the length of the message excluding the actual
263+
// message and log name.
264+
log_length += (message_length + 44) * (InfoLogLevel::FATAL - log_level + 1);
265+
log_length += total_logname_length;
266+
ASSERT_EQ(logger->GetLogFileSize(), log_length);
267+
}
268+
269+
// rerun the test but using different log functions.
270+
total_logname_length = 0;
271+
for (int log_level = InfoLogLevel::FATAL; log_level >= InfoLogLevel::DEBUG;
272+
log_level--) {
273+
logger->SetInfoLogLevel((InfoLogLevel)log_level);
274+
total_logname_length += kInfoLogLevelNameLens[log_level];
275+
276+
// again, messages with level smaller than log_level will not be logged.
277+
Debug(logger, "%s", kSampleMessage.c_str());
278+
Info(logger, "%s", kSampleMessage.c_str());
279+
Warn(logger, "%s", kSampleMessage.c_str());
280+
Error(logger, "%s", kSampleMessage.c_str());
281+
Fatal(logger, "%s", kSampleMessage.c_str());
282+
// 44 is the length of the message excluding the actual
283+
// message and log name.
284+
log_length += (message_length + 44) * (InfoLogLevel::FATAL - log_level + 1);
285+
log_length += total_logname_length;
286+
ASSERT_EQ(logger->GetLogFileSize(), log_length);
287+
}
288+
}
289+
238290
int OldLogFileCount(const string& dir) {
239291
std::vector<std::string> files;
240292
Env::Default()->GetChildren(dir, &files);

util/env.cc

+108
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,120 @@ void Log(Logger* info_log, const char* format, ...) {
4545
}
4646
}
4747

48+
void Log(const InfoLogLevel log_level, Logger* info_log, const char* format,
49+
...) {
50+
if (info_log) {
51+
va_list ap;
52+
va_start(ap, format);
53+
info_log->Logv(log_level, format, ap);
54+
va_end(ap);
55+
}
56+
}
57+
58+
void Debug(Logger* info_log, const char* format, ...) {
59+
if (info_log) {
60+
va_list ap;
61+
va_start(ap, format);
62+
info_log->Logv(InfoLogLevel::DEBUG, format, ap);
63+
va_end(ap);
64+
}
65+
}
66+
67+
void Info(Logger* info_log, const char* format, ...) {
68+
if (info_log) {
69+
va_list ap;
70+
va_start(ap, format);
71+
info_log->Logv(InfoLogLevel::INFO, format, ap);
72+
va_end(ap);
73+
}
74+
}
75+
76+
void Warn(Logger* info_log, const char* format, ...) {
77+
if (info_log) {
78+
va_list ap;
79+
va_start(ap, format);
80+
info_log->Logv(InfoLogLevel::WARN, format, ap);
81+
va_end(ap);
82+
}
83+
}
84+
void Error(Logger* info_log, const char* format, ...) {
85+
if (info_log) {
86+
va_list ap;
87+
va_start(ap, format);
88+
info_log->Logv(InfoLogLevel::ERROR, format, ap);
89+
va_end(ap);
90+
}
91+
}
92+
void Fatal(Logger* info_log, const char* format, ...) {
93+
if (info_log) {
94+
va_list ap;
95+
va_start(ap, format);
96+
info_log->Logv(InfoLogLevel::FATAL, format, ap);
97+
va_end(ap);
98+
}
99+
}
100+
48101
void LogFlush(const shared_ptr<Logger>& info_log) {
49102
if (info_log) {
50103
info_log->Flush();
51104
}
52105
}
53106

107+
void Log(const InfoLogLevel log_level, const shared_ptr<Logger>& info_log,
108+
const char* format, ...) {
109+
if (info_log) {
110+
va_list ap;
111+
va_start(ap, format);
112+
info_log->Logv(log_level, format, ap);
113+
va_end(ap);
114+
}
115+
}
116+
117+
void Debug(const shared_ptr<Logger>& info_log, const char* format, ...) {
118+
if (info_log) {
119+
va_list ap;
120+
va_start(ap, format);
121+
info_log->Logv(InfoLogLevel::DEBUG, format, ap);
122+
va_end(ap);
123+
}
124+
}
125+
126+
void Info(const shared_ptr<Logger>& info_log, const char* format, ...) {
127+
if (info_log) {
128+
va_list ap;
129+
va_start(ap, format);
130+
info_log->Logv(InfoLogLevel::INFO, format, ap);
131+
va_end(ap);
132+
}
133+
}
134+
135+
void Warn(const shared_ptr<Logger>& info_log, const char* format, ...) {
136+
if (info_log) {
137+
va_list ap;
138+
va_start(ap, format);
139+
info_log->Logv(InfoLogLevel::WARN, format, ap);
140+
va_end(ap);
141+
}
142+
}
143+
144+
void Error(const shared_ptr<Logger>& info_log, const char* format, ...) {
145+
if (info_log) {
146+
va_list ap;
147+
va_start(ap, format);
148+
info_log->Logv(InfoLogLevel::ERROR, format, ap);
149+
va_end(ap);
150+
}
151+
}
152+
153+
void Fatal(const shared_ptr<Logger>& info_log, const char* format, ...) {
154+
if (info_log) {
155+
va_list ap;
156+
va_start(ap, format);
157+
info_log->Logv(InfoLogLevel::FATAL, format, ap);
158+
va_end(ap);
159+
}
160+
}
161+
54162
void Log(const shared_ptr<Logger>& info_log, const char* format, ...) {
55163
if (info_log) {
56164
va_list ap;

util/env_hdfs.cc

+3-2
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,9 @@ class HdfsLogger : public Logger {
236236
uint64_t (*gettid_)(); // Return the thread id for the current thread
237237

238238
public:
239-
HdfsLogger(HdfsWritableFile* f, uint64_t (*gettid)())
240-
: file_(f), gettid_(gettid) {
239+
HdfsLogger(HdfsWritableFile* f, uint64_t (*gettid)(),
240+
const InfoLogLevel log_level = InfoLogLevel::ERROR)
241+
: Logger(log_level), file_(f), gettid_(gettid) {
241242
Log(mylog, "[hdfs] HdfsLogger opened %s\n",
242243
file_->getName().c_str());
243244
}

util/posix_logger.h

+10-3
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,16 @@ class PosixLogger : public Logger {
3838
Env* env_;
3939
bool flush_pending_;
4040
public:
41-
PosixLogger(FILE* f, uint64_t (*gettid)(), Env* env) :
42-
file_(f), gettid_(gettid), log_size_(0), fd_(fileno(f)),
43-
last_flush_micros_(0), env_(env), flush_pending_(false) { }
41+
PosixLogger(FILE* f, uint64_t (*gettid)(), Env* env,
42+
const InfoLogLevel log_level = InfoLogLevel::ERROR)
43+
: Logger(log_level),
44+
file_(f),
45+
gettid_(gettid),
46+
log_size_(0),
47+
fd_(fileno(f)),
48+
last_flush_micros_(0),
49+
env_(env),
50+
flush_pending_(false) {}
4451
virtual ~PosixLogger() {
4552
fclose(file_);
4653
}

0 commit comments

Comments
 (0)