Muduo 原版作者认为没有必要为Linux 服务器使用C++新标准线程库、时间表示等特性,但我想学习以下新知识还是有必要的;

后面将POSIX 标准替换成已有的C++标准库;

1. Timestamp

Timestamp,时间戳,记录时间相关信息;

gmtime_r(&seconds, &tm_time) 获取的是世界标准时间,localtime_r(&seconds, &tm_time) 可以依据硬件信息选择当前所在时区;

C++11 提供了chrono 库,可以如下获取当前时间;

Timestamp Timestamp::now() {

return Timestamp(std::chrono::duration_cast(

std::chrono::system_clock::now().time_since_epoch())

.count());

}

获取的时间单位是微秒级别;

2. Log

Log 是日志系统,为了防止系统无法处理错误,或者为了单独的错误而中断整体运行;

当前未实现异步;

2.1 LogStream

日志流的整体思路如上;

关于Boost 单元测试框架:

Boost Unit Test 包含头文件后定义测试Module 即可使用

BOOST_AUTO_TEST_CASE(TestName) {

BOOST_CHECK_EQUAL(a, b);

}

单元测试由n 个BOOST_AUTO_TEST_CASE 构成,普通的ASSERT 断言会使程序异常退出,但是单元测试会继续测试直至全部测试完毕;

测试框架以后应该尝试下Google Test;

2.2 Logger

Logger 是日志输入输出的接口,与外界交互;包含了时间戳、LogStream ;

采用C++ 风格的日志输入模式:

LOG_INFO << "Hello, world!";

并提供日志等级:

enum LogLevel {

TRACE,

DEBUG,

INFO,

WARN,

ERROR,

FATAL,

NUM_LOG_LEVELS,

};

当前记录等级若大于调用等级则当作空语句,表示不关心;

当前记录等级默认为INFO,getenv 获取当前设置并以g_logLevel 表示

Logger::LogLevel initLogLevel() {

if (::getenv("MUDUO_LOG_TRACE"))

return Logger::TRACE;

else if (::getenv("MUDUO_LOG_DEBUG"))

return Logger::DEBUG;

else

return Logger::INFO;

}

LOG_INFO 等日志输入由宏封装而成;

#define LOG_TRACE \

if (TinyMuduo::Logger::logLevel() <= TinyMuduo::Logger::TRACE) \

TinyMuduo::Logger(__FILE__, __LINE__, TinyMuduo::Logger::TRACE, __func__) \

.stream()

#define LOG_DEBUG \

if (TinyMuduo::Logger::logLevel() <= TinyMuduo::Logger::DEBUG) \

TinyMuduo::Logger(__FILE__, __LINE__, TinyMuduo::Logger::DEBUG, __func__) \

.stream()

#define LOG_INFO \

if (TinyMuduo::Logger::logLevel() <= TinyMuduo::Logger::INFO) \

TinyMuduo::Logger(__FILE__, __LINE__).stream()

#define LOG_WARN \

TinyMuduo::Logger(__FILE__, __LINE__, TinyMuduo::Logger::WARN).stream()

#define LOG_ERROR \

TinyMuduo::Logger(__FILE__, __LINE__, TinyMuduo::Logger::ERROR).stream()

#define LOG_FATAL \

TinyMuduo::Logger(__FILE__, __LINE__, TinyMuduo::Logger::FATAL).stream()

#define LOG_SYSERR TinyMuduo::Logger(__FILE__, __LINE__, false).stream()

#define LOG_SYSFATAL TinyMuduo::Logger(__FILE__, __LINE__, true).stream()

WARN、ERROR、FATAL 必须上报日志; 注意到Logger 的构造参数,TRACE 和 DEBUG 提供 function 参数便于验证,INFO 为默认等级,只需要传递 FILE 和 LINE 即够需求;

LOG_SYSERR 和 LOG_SYSFATAL 拥有 toAbort 参数,toAbort == true 则是FATAL 等级,反之为ERROR;

另外,在Logger 实际实现的Impl 类中,errno 参数通常为0,在发生LOG_SYSERR 和 LOG_SYSFATAL 时,才会传入errno;如遇errno ,则会以如下进行错误处理:

Logger 构造后,向Impl 传递参数构造

Logger::Impl::Impl(LogLevel level, int savedErrno, const char *file, int line)

: _time(Timestamp::now()), _stream(), _level(level), _line(line),

_basename(file) {

formatTime();

Fmt tid("%5d ", CurrentThread::tid());

assert(tid.length() == 6);

_stream << T(tid.data(), 6);

_stream << T(LogLevelName[level], 6);

if (savedErrno != 0) {

_stream << strerror_tl(savedErrno) << " (errno=" << savedErrno << ") ";

}

}

先打印Log 时间,接着打印线程id 和 Log 等级; 最后处理errno 情况:

const char *strerror_tl(int savedErrno) {

return strerror_r(savedErrno, t_errnobuf, sizeof t_errnobuf);

}

单条Log 信息格式为: 目前还不是线程安全的Log;

好文阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: