muduo库学习笔记十六:base库之日志库三 LogFile类

LogFile类

1、在介绍Logger类时,我们提到Logger类可以自定义Output xx函数和Flush xx函数,由用户来选择日志信息的输出位置以及flush方式,例如在muduo库学习笔记十三:base库之日志库一 Logger类示例程序中,我们就使用fwrite和fflush作为日志信息输出方法。而LogFile类就相当于定义了Muduo库自己的输出到日志文件的Output和Flush函数。

2、LogFile类定义了日志滚动的规则,可以根据用户传入参数进行定制。首先根据日志大小进行滚动,其次根据时间进行滚动。此外,日志信息不是直接输出到文件,是先到缓冲区,再由缓冲区输出到文件,LogFile类也定义了缓冲区flush的时间间隔。

类图:

知识点:

1、append_unlocked函数调用File类中的append函数进行缓冲区写入,并对日志文件滚动以及缓冲区flush进行控制。

2、 time_t startOfPeriod_;    // 开始记录日志时间(调整至当天零点距离1970年1月1号的秒数)--方便下次滚动日志时进行比较
3、LogFile类可以选择是否采用线程安全版本,非线程安全版本效率高

4、void LogFile::rollFile()函数    time_t start = now / kRollPerSeconds_ * kRollPerSeconds_;

 这里先除kRollPerSeconds_ 后乘kRollPerSeconds_表示对齐至kRollPerSeconds_整数倍,也就是时间调整到当天零点。
示例1:

#include <muduo/base/LogFile.h>
#include <muduo/base/Logging.h>

boost::scoped_ptr<muduo::LogFile> g_logFile;

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);
  g_logFile.reset(new muduo::LogFile(::basename(name), 200*1000));
  /*
  成员函数void reset(T * p = 0):成员函数reset()的功能是重置scoped_ptr,它删除原来保存的指针,
  再保存新的指针值p。如果p是空指针,那么scoped_ptr将不持有任何指针。
  */
  muduo::Logger::setOutput(outputFunc);
  muduo::Logger::setFlush(flushFunc);

  muduo::string line = "1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ ";

  for (int i = 0; i < 10000; ++i)
  {
    LOG_INFO << line << i;

    usleep(1000);
  }
}

该例子是将指定内容输入到目标文件中,通过LogFile类使用指定的滚动策略进行记录。

示例2

#include <muduo/base/Logging.h>
#include <muduo/base/LogFile.h>
#include <muduo/base/ThreadPool.h>

#include <stdio.h>

int g_total;
FILE* g_file;
boost::scoped_ptr<muduo::LogFile> g_logFile;

void dummyOutput(const char* msg, int len)
{
  g_total += len;
  if (g_file)
  {
    fwrite(msg, 1, len, g_file);
  }
  else if (g_logFile)
  {
    g_logFile->append(msg, len);
  }
}

void bench(const char* type)//性能测试
{
  muduo::Logger::setOutput(dummyOutput);
  muduo::Timestamp start(muduo::Timestamp::now());
  g_total = 0;

  int n = 1000*1000;
  const bool kLongLog = false;
  muduo::string empty = " ";
  muduo::string longStr(3000, 'X');
  longStr += " ";
  for (int i = 0; i < n; ++i)
  {
    LOG_INFO << "Hello 0123456789" << " abcdefghijklmnopqrstuvwxyz"
             << (kLongLog ? longStr : empty)
             << i;
  }
  muduo::Timestamp end(muduo::Timestamp::now());
  double seconds = timeDifference(end, start);
  printf("%12s: %f seconds, %d bytes, %10.2f msg/s, %.2f MiB/s\n",
         type, seconds, g_total, n / seconds, g_total / seconds / (1024 * 1024));
}

void logInThread()
{
  LOG_INFO << "logInThread";//输出到标准输出
  usleep(1000);
}

int main()
{
  getppid(); // for ltrace and strace

//线程池
  muduo::ThreadPool pool("pool");
  pool.start(5);//启动5个线程
  pool.run(logInThread);//线程池中的线程运行5个任务
  pool.run(logInThread);
  pool.run(logInThread);
  pool.run(logInThread);
  pool.run(logInThread);

//主线程
  LOG_TRACE << "trace";//主线程输出
  LOG_DEBUG << "debug";
  LOG_INFO << "Hello";
  LOG_WARN << "World";
  LOG_ERROR << "Error";
  LOG_INFO << sizeof(muduo::Logger);
  LOG_INFO << sizeof(muduo::LogStream);
  LOG_INFO << sizeof(muduo::Fmt);
  LOG_INFO << sizeof(muduo::LogStream::Buffer);

  sleep(1);
  bench("nop");

  char buffer[64*1024];

  g_file = fopen("/dev/null", "w");
  setbuffer(g_file, buffer, sizeof buffer);
  bench("/dev/null");
  fclose(g_file);

  g_file = fopen("/tmp/log", "w");
  setbuffer(g_file, buffer, sizeof buffer);
  bench("/tmp/log");
  fclose(g_file);

  g_file = NULL;
  g_logFile.reset(new muduo::LogFile("test_log_st", 500*1000*1000, false));//非线程安全,不加锁
  bench("test_log_st");

  g_logFile.reset(new muduo::LogFile("test_log_mt", 500*1000*1000, true));//线程安全方式写入
  bench("test_log_mt");
  g_logFile.reset();
}

输出

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值