Summary: Moved LogBuffer class to an internal header. Removed some unneccesary indirection. Enabled log buffer for BackgroundCallFlush. Forced log buffer flush right after Unlock to improve time ordering of info log. Test Plan: make check; db_bench compare LOG output Reviewers: sdong Reviewed By: sdong CC: leveldb, igor Differential Revision: https://reviews.facebook.net/D16707main
parent
04d2c26e17
commit
66da467983
@ -0,0 +1,67 @@ |
||||
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#include "util/log_buffer.h" |
||||
|
||||
#include <sys/time.h> |
||||
|
||||
namespace rocksdb { |
||||
|
||||
LogBuffer::LogBuffer(const InfoLogLevel log_level, |
||||
Logger*info_log) |
||||
: log_level_(log_level), info_log_(info_log) {} |
||||
|
||||
void LogBuffer::AddLogToBuffer(const char* format, va_list ap) { |
||||
if (!info_log_ || log_level_ < info_log_->GetInfoLogLevel()) { |
||||
// Skip the level because of its level.
|
||||
return; |
||||
} |
||||
|
||||
const size_t kLogSizeLimit = 512; |
||||
char* alloc_mem = arena_.AllocateAligned(kLogSizeLimit); |
||||
BufferedLog* buffered_log = new (alloc_mem) BufferedLog(); |
||||
char* p = buffered_log->message; |
||||
char* limit = alloc_mem + kLogSizeLimit - 1; |
||||
|
||||
// store the time
|
||||
gettimeofday(&(buffered_log->now_tv), nullptr); |
||||
|
||||
// Print the message
|
||||
if (p < limit) { |
||||
va_list backup_ap; |
||||
va_copy(backup_ap, ap); |
||||
p += vsnprintf(p, limit - p, format, backup_ap); |
||||
va_end(backup_ap); |
||||
} |
||||
|
||||
// Add '\0' to the end
|
||||
*p = '\0'; |
||||
|
||||
logs_.push_back(buffered_log); |
||||
} |
||||
|
||||
void LogBuffer::FlushBufferToLog() { |
||||
for (BufferedLog* log : logs_) { |
||||
const time_t seconds = log->now_tv.tv_sec; |
||||
struct tm t; |
||||
localtime_r(&seconds, &t); |
||||
Log(log_level_, info_log_, |
||||
"(Original Log Time %04d/%02d/%02d-%02d:%02d:%02d.%06d) %s", |
||||
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, |
||||
t.tm_sec, static_cast<int>(log->now_tv.tv_usec), log->message); |
||||
} |
||||
logs_.clear(); |
||||
} |
||||
|
||||
void LogToBuffer(LogBuffer* log_buffer, const char* format, ...) { |
||||
if (log_buffer != nullptr) { |
||||
va_list ap; |
||||
va_start(ap, format); |
||||
log_buffer->AddLogToBuffer(format, ap); |
||||
va_end(ap); |
||||
} |
||||
} |
||||
|
||||
} // namespace rocksdb
|
@ -0,0 +1,46 @@ |
||||
// Copyright (c) 2014, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
#pragma once |
||||
|
||||
#include "rocksdb/env.h" |
||||
#include "util/arena.h" |
||||
#include "util/autovector.h" |
||||
|
||||
namespace rocksdb { |
||||
|
||||
class Logger; |
||||
|
||||
// A class to buffer info log entries and flush them in the end.
|
||||
class LogBuffer { |
||||
public: |
||||
// log_level: the log level for all the logs
|
||||
// info_log: logger to write the logs to
|
||||
LogBuffer(const InfoLogLevel log_level, Logger* info_log); |
||||
|
||||
// Add a log entry to the buffer.
|
||||
void AddLogToBuffer(const char* format, va_list ap); |
||||
|
||||
// Flush all buffered log to the info log.
|
||||
void FlushBufferToLog(); |
||||
|
||||
private: |
||||
// One log entry with its timestamp
|
||||
struct BufferedLog { |
||||
struct timeval now_tv; // Timestamp of the log
|
||||
char message[1]; // Beginning of log message
|
||||
}; |
||||
|
||||
const InfoLogLevel log_level_; |
||||
Logger* info_log_; |
||||
Arena arena_; |
||||
autovector<BufferedLog*> logs_; |
||||
}; |
||||
|
||||
// Add log to the LogBuffer for a delayed info logging. It can be used when
|
||||
// we want to add some logs inside a mutex.
|
||||
extern void LogToBuffer(LogBuffer* log_buffer, const char* format, ...); |
||||
|
||||
} // namespace rocksdb
|
Loading…
Reference in new issue