C++服务器框架开发10——日志系统1~9代码

该专栏记录了在学习一个开发项目的过程中遇到的疑惑和问题。
其教学视频见:[C++高级教程]从零开始开发服务器框架(sylar)

上一篇:C++服务器框架开发9——日志系统LogFormatter_4/各个类的关系梳理/std::function/std::get

这次给出前面1~9的代码,一两处小错误我已经做了修改。但还有其他的错误,等着视频中遇到了再改吧。

log.h

#ifndef __SYLAR_LOG_H__
#define __SYLAR_LOG_H__

#include
#include
#include
#include
#include
#include
#include
namespace sylar {

	//日志事件
	class LogEvent {
	public:
		typedef std::shared_ptr<LogEvent> ptr;
		LogEvent();
		const char* getFile() const { return m_file; }
		int32_t getLine() const { return m_line; }
		uint32_t getElapse()const { return m_elapse; }
		uint32_t getThreadId()const { return m_threadId; }
		uint32_t getFiberId()const { return m_fiberId; }
		uint64_t getTime()const { return m_time; }
		const  std::string& getContent() const { return m_content; }
	private:
		const char* m_file = nullptr; //文件名
		int32_t m_line = 0;			  //行号
		uint32_t m_elapse = 0;        //程序启动开始到现在的毫秒数
		uint32_t m_threadId = 0;	  //线程ID
		uint32_t m_fiberId = 0;		  //协程ID
		uint64_t m_time;			  //时间戳
		std::string m_content;		  //内容
	};

	//日志级别
	class LogLevel {
	public:
		enum Level {
			UNKNOW = 0,
			DEBUG = 1,
			INFO = 2,
			WARN = 3,
			ERROR = 4,
			FATAL = 5
		};
		static const char* ToString(LogLevel::Level level);
	};

	//日志格式器
	class LogFormatter {
	public:
		typedef std::shared_ptr<LogFormatter> ptr;
		LogFormatter(const std::string& pattern);

		//%t %thread_id %m%n
		std::string format(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event);
	public:
		class FormatItem {
		public:
			typedef std::shared_ptr<FormatItem> ptr;
			FormatItem(const std::string& fmt = "");
			virtual ~FormatItem(){}
			virtual void format(std::ostream& os, std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) = 0;
		};

		void init();
	private:
		std::string m_pattern;
		std::vector<FormatItem::ptr> m_items;

	};
	
	//日志输出目标
	class LogAppender {
	public:
		typedef std::shared_ptr<LogAppender> ptr;
		virtual ~LogAppender() {}

		virtual void log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event)=0;

		void setFormatter(LogFormatter::ptr val) { m_formatter = val; }
		LogFormatter::ptr getFormatter() const { return m_formatter; }
	protected:
		LogLevel::Level m_level;
		LogFormatter::ptr  m_formatter;
	};

	//日志器
	class Logger {
	public:
		typedef std::shared_ptr<Logger> ptr;

		Logger(const std::string& name = "root");
		void log(LogLevel::Level level, LogEvent::ptr event);

		void debug(LogEvent::ptr event);
		void info(LogEvent::ptr event);
		void warn(LogEvent::ptr event);
		void error(LogEvent::ptr event);
		void fatal(LogEvent::ptr event);

		void addAppender(LogAppender::ptr appender);
		void delAppender(LogAppender::ptr appender);
		LogLevel::Level getLevel() const { return m_level; }
		void setLevel(LogLevel::Level val) { m_level = val; }

		const std::string& getName()const { return m_name; }
	private:
		std::string m_name;                        //日志名称
		LogLevel::Level m_level;                   //日志级别
		std::list<LogAppender::ptr> m_appenders;   //Appender集合
	};


	//输出到控制台的Appender
	class StdoutLogAppender : public LogAppender {
	public:
		typedef std::shared_ptr<StdoutLogAppender> ptr;
		void log(std::shared_ptr<Logger> logger,LogLevel::Level level, LogEvent::ptr event) override;
	};

	//定义输出到文件的Appender
	class FileLogAppender : public LogAppender {
	public:
		typedef std::shared_ptr<FileLogAppender>ptr;
		FileLogAppender(const std::string& filename);
		void log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event)override;

		//重新打开文件,文件打开成功返回true
		bool reopen();
	private:
		std::string m_filename;
		std::ofstream m_filestream;
	};
}


#endif

log.cc

#include"log.h"
#include 
#include
#include
#include
namespace sylar {

	const char* LogLevel::ToString(LogLevel::Level level) {
		switch (level) {
	#define XX(name) \
		case LogLevel::name:\
			return #name;\
			break;
			XX(DEBUG);
			XX(INFO);
			XX(WARN);
			XX(ERROR);
			XX(FATAL);
	#undef XX
		default:
			return "UNKNOW";		
		}
		return "UNKNOW";
	}
	class MessageFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getContent();
		}
	};
	class LevelFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << LogLevel::ToString(level);
		}
	};

	class ElapseFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getElapse();
		}
	};

	class NameFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << logger->getName();
		}
	};

	class ThreadIdFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getThreadId();
		}
	};

	class FiberIdFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getFiberId();
		}
	};

	class ThreadIdFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getThreadId();
		}
	};

	class DateTimeFormatItem : public LogFormatter::FormatItem {
	public:
		DateTimeFormatItem(const std::string& format = "%Y-%m-%d %H:%M:%S")
			:m_format(format) {
		}

		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getTime();
		}
	private:
		std::string m_format;
	};

	class FilenameFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getFile();
		}
	};

	class LineFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << event->getLine();
		}
	};

	class NewLineFormatItem : public LogFormatter::FormatItem {
	public:
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << std::endl;
		}
	};


	class StringFormatItem : public LogFormatter::FormatItem {
	public:
		StringFormatItem(const std::string& str)
			:m_string(str) {}
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << m_string;
		}
	private:
		std::string m_string;
	};

	class TabFormatItem : public LogFormatter::FormatItem {
	public:
		TabFormatItem(const std::string& str = "") {}
		void format(std::ostream& os, Logger::ptr logger, LogLevel::Level level, LogEvent::ptr event) override {
			os << "\t";
		}
	private:
		std::string m_string;
	};

	Logger::Logger(const std::string& name)
		:m_name(name) {
	}

	void Logger::addAppender(LogAppender::ptr appender) {
		m_appenders.push_back(appender);
	}

	void Logger::delAppender(LogAppender::ptr appender) {
		for (auto it = m_appenders.begin(); it != m_appenders.end(); ++it) {
			if (*it == appender) {
				m_appenders.erase(it);
				break;
			}
		}
	}

	void Logger::log(LogLevel::Level level, LogEvent::ptr event) {
		if (level >= m_level) {
			for (auto & i : m_appenders) {
				i->log(level, event);
			}
		}
	}
	void Logger::debug(LogEvent::ptr event) {
		log(LogLevel::DEBUG, event);
	}

	void Logger::info(LogEvent::ptr event) {
		log(LogLevel::INFO, event);
	}

	void Logger::warn(LogEvent::ptr event) {
		log(LogLevel::WARN, event);
	}

	void Logger::error(LogEvent::ptr event) {
		log(LogLevel::ERROR, event);
	}

	void Logger::fatal(LogEvent::ptr event) {
		log(LogLevel::FATAL, event);
	}

	FileLogAppender::FileLogAppender(const std::string& filename)
		:m_filename(filename) {
	}

	void FileLogAppender::log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) {
		if (level >= m_level) {
			m_filestream << m_formatter->format(logger,level, event);
		}
	}

	bool FileLogAppender::reopen() {
		if (m_filestream) {
			m_filestream.close();
		}
		m_filestream.open(m_filename);
		return !!m_filestream;
	}

	void StdoutLogAppender::log(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) {
		if (level >= m_level) {
			std::cout << m_formatter->format(logger,level, event);
		}
	}

	LogFormatter::LogFormatter(const std::string& pattern)
		:m_pattern(pattern) {
	}

	std::string LogFormatter::format(std::shared_ptr<Logger> logger, LogLevel::Level level, LogEvent::ptr event) {
		std::stringstream ss;
		for (auto& i : m_items) {
			i->format(ss, logger, level,event);
		}
		return ss.str();
	}

	//%xxx %xxx{xxx} %%
	void LogFormatter::init() {
		std::vector < std::tuple<std::string, std::string, int>>vec;
		std::string nstr;
		for (size_t i = 0; i < m_pattern.size(); ++i) {
			if (m_pattern[i] != '%') {
				nstr.append(1, m_pattern[i]);
				continue;
			}

			if ((i + 1) < m_pattern.size()) {
				if (m_pattern[i + 1] == '%') {
					nstr.append(1, '%');
					continue;
				}
			}
			size_t n = i + 1;
			int fmt_status = 0;
			size_t fmt_begin = 0;
			
			std::string str;
			std::string fmt;
			while (n < m_pattern.size()) {
				if (isspace(m_pattern[n])) {
					break;
				}
				if (fmt_status == 0) {
					if (m_pattern[n] == '{') {
						str = m_pattern.substr(i + 1, n - i - 1);
						fmt_status = 1;//解析格式
						fmt_begin = n;
						++n;
						continue;
					}
				}
				if (fmt_status == 1) {
					if (m_pattern[n] == '}') {
						fmt = m_pattern.substr(fmt_begin + 1, n - fmt_begin - 1);
						fmt_status = 1;
						break;
					}
				}
			}

			if (fmt_status == 0) {
				if (!nstr.empty()) {
					vec.push_back(std::make_tuple(nstr, "", 0));
					nstr.clear();
				}
				str = m_pattern.substr(i + 1, n - i - 1);
				vec.push_back(std::make_tuple(str, fmt, 1));
				i = n;
			}
			else if(fmt_status == 1){
				std::cout << "pattern parse error:" << m_pattern << " - " << m_pattern.substr(i) << std::endl;
				vec.push_back(std::make_tuple("<>", fmt, 0));
			}
			else if (fmt_status == 2) {
				if (!nstr.empty()) {
					vec.push_back(std::make_tuple(nstr, "", 0));
					nstr.clear();
				}
				vec.push_back(std::make_tuple(str, fmt, 1));
				i = n;
			}
		}

		if (!nstr.empty()) {
			vec.push_back(std::make_tuple(nstr, "", 0));
		}
		static std::map<std::string, std::function<FormatItem::ptr(const std::string& str)>> s_format_items = {
	#define XX(str,C)\
		{#str, [](const std::string& fmt){return FormatItem::ptr (new C(fmt));}}

		XX(m,MessageFormatItem),
		XX(p,LevelFormatItem),
		XX(r,ElapseFormatItem),
		XX(c,NameFormatItem),
		XX(t,ThreadIdFormatItem),
		XX(n,NewLineFormatItem),
		XX(d,DateTimeFormatItem),
		XX(f,FilenameFormatItem),
		XX(l,LineFormatItem),
	#undef XX
		};
		for (auto& i : vec) {
			if (std::get<2>(i) == 0) {
				m_items.push_back(FormatItem::ptr(new StringFormatItem(std::get<0>(i))));
			}
			else {
				auto it = s_format_items.find(std::get<0>(i));
				if (it == s_format_items.end()) {
					m_items.push_back(FormatItem::ptr(new StringFormatItem("< + std::get<0>(i) + ">>")));
				}
				else {
					m_items.push_back(it->second(std::get<1>(i)));
				}
			}
			std::cout << std::get<0>(i) << " - " << std::get<1>(i) << " - " << std::get<2>(i) << std::endl;
		}
	}

}

你可能感兴趣的:(分布式服务器开发,c++,服务器,分布式)