日志滚动
日志滚动条件
1、文件大小(例如每写满1G换下一个文件)
2、时间(每天零点新建一个日志文件,不论前一个文件是否写满)
一个典型的日志文件名
logfile_test.20130411-115604.popo.7743.log
Logger 类图
File类图
file类是LogFile的一个内置类
LogFile头文件(logfile.h)
#ifndef MUDUO_BASE_LOGFILE_H
#define MUDUO_BASE_LOGFILE_H
#include <muduo/base/Mutex.h>
#include <muduo/base/Types.h>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
namespace muduo
{
class LogFile : boost::noncopyable
{
public:
LogFile(const string& basename,
size_t rollSize,
bool threadSafe = true,
int flushInterval = 3);
~LogFile();
void append(const char* logline, int len);
void flush();
private:
void append_unlocked(const char* logline, int len);
static string getLogFileName(const string& basename, time_t* now); //获取日志文件路径
void rollFile(); //滚动日志
const string basename_; //日志文件basename
const size_t rollSize_; //日志文件达到 rolSize_ 换一个新文件
const int flushInterval_; //日志文件写入间隔时间 ,不是每一次的日志都直接写入文件,这样也有助于提高效率
int count_; //计数器 ,当达到kCheckTimeRoll_时,会去检测是否要滚动日志文件
boost::scoped_ptr<MutexLock> mutex_;
time_t startOfPeriod_; //开始记录日志时间(调整至零点)
time_t lastRoll_; //上一次滚动日志文件时间
time_t lastFlush_;//上一次日志写入文件时间
class File; //日志文件类
boost::scoped_ptr<File> file_; //日子文件指针,这是一个智能指针
const static int kCheckTimeRoll_ = 1024; //
const static int kRollPerSeconds_ = 60*60*24; //一天
};
}
#endif // MUDUO_BASE_LOGFILE_HLogFile的源文件
#include <muduo/base/LogFile.h>
#include <muduo/base/Logging.h> // strerror_tl
#include <muduo/base/ProcessInfo.h>
#include <assert.h>
#include <stdio.h>
#include <time.h>
using namespace muduo;
// not thread safe 不是线程安全
class LogFile::File : boost::noncopyable //不可复制
{
public:、
/********
//File 类
**********/
explicit File(const string& filename)
: fp_(::fopen(filename.data(), "ae")),
writtenBytes_(0)
{
assert(fp_); //断言fp_指针是否为空
::setbuffer(fp_, buffer_, sizeof buffer_); //是指缓冲区的大小
// posix_fadvise POSIX_FADV_DONTNEED ?
}
//虚构函数 , 关闭fp_指针
~File()
{
::fclose(fp_);
}
//追加 日志
void append(const char* logline, const size_t len)
{
size_t n = write(logline, len);
size_t remain = len - n;
while (remain > 0)
{
size_t x = write(logline + n, remain);
if (x == 0)
{
int err = ferror(fp_);
if (err)
{
fprintf(stderr, "LogFile::File::append() failed %s\n", strerror_tl(err));
}
break;
}
n += x;
remain = len - n; // remain -= x
}
writtenBytes_ += len;
}
//清空缓冲区
void flush()
{
::fflush(fp_);
}
size_t writtenBytes() const { return writtenBytes_; }
private:
//不加锁写入文件,logfile已经加锁了
size_t write(const char* logline, size_t len)
{
#undef fwrite_unlocked
return ::fwrite_unlocked(logline, 1, len, fp_);
}
FILE* fp_;
char buffer_[64*1024];
size_t writtenBytes_;
};
/*******
LogFile类
*******/
LogFile::LogFile(const string& basename,
size_t rollSize,
bool threadSafe,
int flushInterval)
: basename_(basename),//文件basename
rollSize_(rollSize),//日志滚动大小界限
flushInterval_(flushInterval), //清空缓冲区
count_(0),
mutex_(threadSafe ? new MutexLock : NULL),//是否以线程安全的方式进行操作
startOfPeriod_(0),
lastRoll_(0),
lastFlush_(0)
{
//断言 ,basename 是否包含"/"
assert(basename.find('/') == string::npos);
//滚动日志
rollFile();
}
LogFile::~LogFile()
{
}
//追加 日志记录
void LogFile::append(const char* logline, int len)
{
if (mutex_)
{
MutexLockGuard lock(*mutex_);
append_unlocked(logline, len);
}
else
{
append_unlocked(logline, len);
}
}
void LogFile::flush()
{
if (mutex_)
{
MutexLockGuard lock(*mutex_);
file_->flush();
}
else
{
file_->flush();
}
}
void LogFile::append_unlocked(const char* logline, int len)
{
file_->append(logline, len);
//判断是否要滚动日志文件了 ,大小上测试
if (file_->writtenBytes() > rollSize_)
{
//滚动日志文件
rollFile();
}
else
{
//时间上测试 ,就是计数器
if (count_ > kCheckTimeRoll_)
{
count_ = 0;
time_t now = ::time(NULL);
time_t thisPeriod_ = now / kRollPerSeconds_ * kRollPerSeconds_;
if (thisPeriod_ != startOfPeriod_)
{
rollFile();
}
//是否应该清空数据
else if (now - lastFlush_ > flushInterval_)
{
lastFlush_ = now;
file_->flush();
}
}
//计数器++
else
{
++count_;
}
}
}
//日志滚动
void LogFile::rollFile()
{
time_t now = 0;
string filename = getLogFileName(basename_, &now);
time_t start = now / kRollPerSeconds_ * kRollPerSeconds_;
//如果是时间上的滚动,那么就要更新一下时间了
if (now > lastRoll_)
{
lastRoll_ = now;
lastFlush_ = now;
startOfPeriod_ = start;
file_.reset(new File(filename));
}
}
//得到日志文件名
string LogFile::getLogFileName(const string& basename, time_t* now)
{
string filename;
filename.reserve(basename.size() + 64);
filename = basename;
char timebuf[32];
char pidbuf[32];
struct tm tm;
*now = time(NULL);
gmtime_r(now, &tm); // FIXME: localtime_r ?
strftime(timebuf, sizeof timebuf, ".%Y%m%d-%H%M%S.", &tm);
filename += timebuf;
filename += ProcessInfo::hostname();
snprintf(pidbuf, sizeof pidbuf, ".%d", ProcessInfo::pid());
filename += pidbuf;
filename += ".log";
return filename;
}LogFile测试类 LogFile_Test.cc
#include <muduo/base/LogFile.h>
#include <muduo/base/Logging.h>
boost::scoped_ptr<muduo::LogFile> g_logFile;
//msg日志内容,日志长度
void outputFunc(const char* msg, int len)
{
g_logFile->append(msg, len);
}
void flushFunc()
{
g_logFile->flush();
}
int main(int argc, char* argv[])
{
char name[256];
strncpy(name, argv[0], 256);
//日志滚动的大小200*1000 = 196k
g_logFile.reset(new muduo::LogFile(::basename(name), 200*1000));
//Logger的输出函数
muduo::Logger::setOutput(outputFunc);
//Logger的缓冲区清空函数
muduo::Logger::setFlush(flushFunc);
//日志
muduo::string line = "1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ ";
//10000条日志记录
for (int i = 0; i < 10000; ++i)
{
LOG_INFO << line << i;
usleep(1000);
}
}程序输出:
[root@localhost bin]# ls -lh logfile_test*
-rwxr-xr-x. 1 root root 610K Oct 17 16:02 logfile_test
-rw-r--r--. 1 root root 196K Oct 17 16:03 logfile_test.20131017-080304.localhost.localdomain.2656.log
-rw-r--r--. 1 root root 196K Oct 17 16:03 logfile_test.20131017-080309.localhost.localdomain.2656.log
-rw-r--r--. 1 root root 196K Oct 17 16:03 logfile_test.20131017-080312.localhost.localdomain.2656.log
-rw-r--r--. 1 root root 196K Oct 17 16:03 logfile_test.20131017-080314.localhost.localdomain.2656.log
-rw-r--r--. 1 root root 196K Oct 17 16:03 logfile_test.20131017-080316.localhost.localdomain.2656.log
-rw-r--r--. 1 root root 196K Oct 17 16:03 logfile_test.20131017-080319.localhost.localdomain.2656.log
-rw-r--r--. 1 root root 87K Oct 17 16:03 logfile_test.20131017-080321.localhost.localdomain.2656.log
[root@localhost bin]#
467

被折叠的 条评论
为什么被折叠?



