muduo学习笔记 日志类

learn_muduo

Logger

Logger有六个日志等级

  • TRACE
  • DEBUG
  • INFO
  • WARN
  • ERROR
  • FATAL

日志的输出语句是通过宏定义完成,编译期完成宏定义替换,创建Logger的临时对象。

#define LOG_TRACE if (muduo::Logger::logLevel() <= muduo::Logger::TRACE) \
	muduo::Logger(__FILE__, __LINE__, muduo::Logger::TRACE, __func__).stream()

#define LOG_DEBUG if (muduo::Logger::logLevel() <= muduo::Logger::DEBUG) \
	muduo::Logger(__FILE__, __LINE__, muduo::Logger::DEBUG, __func__).stream()

#define LOG_INFO if (muduo::Logger::logLevel() <= muduo::Logger::INFO) \
	muduo::Logger(__FILE__, __LINE__).stream()

#define LOG_WARN muduo::Logger(__FILE__, __LINE__, muduo::Logger::WARN).stream()

#define LOG_ERROR muduo::Logger(__FILE__, __LINE__, muduo::Logger::ERROR).stream()

#define LOG_FATAL muduo::Logger(__FILE__, __LINE__, muduo::Logger::FATAL).stream()

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

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

Logger的构造函数

Logger::Logger(SourceFile file, int line)
	: impl_(INFO, 0, file, line)
{
}

Logger::Logger(SourceFile file, int line, LogLevel level, const char* func)
	: impl_(level, 0, file, line)
{
 	impl_.stream_ << func << ' ';
}

Logger::Logger(SourceFile file, int line, LogLevel level)
	: impl_(level, 0, file, line)
{
}

Logger::Logger(SourceFile file, int line, bool toAbort)
	: impl_(toAbort? FATAL:ERROR, errno, file, line)
{
}

Impl类

Logger的构造函数中用到了Impl类,Impl类保存Logger的数据。

class Impl
{
public:
	typedef Logger::LogLevel LogLevel;
	Impl(LogLevel level, int old_errno, const SourceFile& file, int line);
	void formatTime();
	void finish();

	Timestamp time_;
	LogStream stream_;
	LogLevel level_;
	int line_;
	SourceFile basename_;

}; // class Impl

日志的时间,线程号,级别等在Impl构造函数初始化时完成,将这些信息写到LogStream对象中。

Logger::Impl::Impl(LogLevel level, int savedErrno, const SourceFile& file, int line)
	: time_(Timestamp::now()),
	  stream_(),
	  level_(level),
	  line_(line),
	  basename_(file)
{
	formatTime();
	CurrentThread::tid();
	stream_ << T(CurrentThread::tidString(), CurrentThread::tidStringLength());
	stream_ << T(LogLevelName[level], 6);
	if (savedErrno != 0){
		stream_ << strerror_tl(savedErrno) << " (errno=" << savedErrno << ") ";
	}
}	  

Logger的析构

Logger是临时对象,因此Logger的析构接管日志的输出工作。

// 将msg输出到stdout
void defaultOutput(const char* msg, int len)
{
	size_t n = fwrite(msg, 1, len, stdout);
}

Logger::OutputFunc g_output = defaultOutput;

// 文件名和行号 
void Logger::Impl::finish()
{
	stream_ << " - " << basename_ << ":" << line_ << "\n";
}

Logger::~Logger()
{
	impl_.finish();
	const LogStream::Buffer& buf(stream().buffer());
	g_output(buf.data(), buf.length());
	if (impl_.level_ == FATAL) {
		g_flush();
		abort();
	}
}

LogStream

FixedBuffer

LogStream中维护一个FixedBuffer::Buffer的缓冲区,FixedBuffer提供了append()、data()、length()等一些字符串的基本操作。

template<int SIZE>
class FixedBuffer : noncopyable
{
public:
	FixedBuffer()
		: cur_(data_)
	{
		setCookie(cookieStart);
	}

	~FixedBuffer()
	{
		setCookie(cookieEnd);
	}
	
	void append(const char* buf, size_t len)
	{
		if (implicit_cast<size_t>(avail()) > len)
		{
			memcpy(cur_, buf, len);
			cur_ += len;
		}
	}

	const char* data() const {  return data_; }
	int length() const { return static_cast<int>(cur_ - data_); }

	// write to data_ directly
	char* current() { return cur_; }
	int avail() { return static_cast<int>(end() - cur_); }
	void add(size_t len) { cur_ += len; }
	void reset() { cur_ = data_; }
	void bzero() { memZero(data_, sizeof(data_)); }
	
	// for used by GDB
	const char* debugString();
	void setCookie(void (*cookie)()) { cookie_ = cookie; }
	// for used by unit test
	string toString() const {return string(data_, length()); }
	StringPiece toStringPiece() const { return StringPiece(data_, length()); }


private:
	const char* end() const { return data_ + sizeof data_; }
	// Must be outline function for cookies.
	static void cookieStart();
	static void cookieEnd();

	void (*cookie_)();
	char data_[SIZE];
	char* cur_;
}; // class fixedBuffer

LogStream

Logstream重载了各种 operator << 函数,用于处理多种类型的数据,将这些日志信息追加到Buffer中。

class LogStream : noncopyable
{
  typedef LogStream self;
 public:

  typedef detail::FixedBuffer<detail::kSmallBuffer> Buffer;

  /* 重载的operator<<函数,将日志信息存放在缓冲区中 */
  self& operator<<(const char* str)
  {
    if (str)
    {
      buffer_.append(str, strlen(str));
    }
    else
    {
      buffer_.append("(null)", 6);
    }
    return *this;
  }

  /* ... */

 private:

  Buffer buffer_;

  static const int kMaxNumericSize = 32;
};

你可能感兴趣的:(muduo)