瀏覽代碼

boost log实现glog 类似功能:
1.输出文件名行号
2.支持日志分级
3.支持命令行指定输出到标准错误
……

tanghai 14 年之前
父節點
當前提交
3e68b11c17
共有 4 個文件被更改,包括 60 次插入33 次删除
  1. 2 1
      Cpp/Platform/CMakeLists.txt
  2. 41 19
      Cpp/Platform/Log/Log.cc
  3. 15 9
      Cpp/Platform/Log/Log.h
  4. 2 4
      Cpp/Platform/Log/LogTest.cc

+ 2 - 1
Cpp/Platform/CMakeLists.txt

@@ -1,4 +1,5 @@
 ADD_SUBDIRECTORY(Thread)
 ADD_SUBDIRECTORY(Rpc)
 ADD_SUBDIRECTORY(Mono)
-ADD_SUBDIRECTORY(Orm)
+ADD_SUBDIRECTORY(Orm)
+ADD_SUBDIRECTORY(Log)

+ 41 - 19
Cpp/Platform/Log/Log.cc

@@ -12,12 +12,15 @@
 #include <boost/log/attributes.hpp>
 #include <boost/log/sinks/text_multifile_backend.hpp>
 #include <boost/log/attributes/current_thread_id.hpp>
-
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+#include <boost/log/sinks/sync_frontend.hpp>
+#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <gflags/gflags.h>
 #include "Log/Log.h"
 
-namespace attrs = boost::log::attributes;
-namespace fmt = boost::log::formatters;
-namespace keywords = boost::log::keywords;
+DEFINE_bool(logtoconsole, false, "log messages go to stderr instead of logfiles");
+
+using namespace boost::log;
 
 namespace Egametang {
 
@@ -27,36 +30,55 @@ std::string FileName(const char* s)
 	return path.filename().string();
 }
 
-BoostLogInit::BoostLogInit(const char* fileName)
-{
-	auto core = boost::log::core::get();
-	core->add_global_attribute("TimeStamp", boost::make_shared<attrs::local_clock>());
-	core->add_global_attribute("ThreadId", boost::make_shared<attrs::current_thread_id>());
+bool ELog::isInit = false;
+sources::severity_logger<SeverityLevel> ELog::slog;
 
-	pSink = boost::make_shared<text_sink>();
+void ELog::Init(const char* fileName)
+{
+	if (isInit)
+	{
+		return;
+	}
+	isInit = true;
 
-	std::string logFileName = std::string(fileName) + ".log";
-	auto logStream = boost::make_shared<std::ofstream>(
-	        logFileName.c_str());
+	auto core = core::get();
+	typedef sinks::synchronous_sink<sinks::text_ostream_backend> text_sink;
+	auto pSink = boost::make_shared<text_sink>();
+	std::string logFileName = FileName(fileName) + ".log";
+	auto logStream = boost::make_shared<std::ofstream>(logFileName.c_str());
 	if (!logStream->good())
 	{
 		throw std::runtime_error("Failed to open a log file");
 	}
 	pSink->locked_backend()->add_stream(logStream);
 
-	pSink->locked_backend()->auto_flush(true);
+	// 是否输出到标准错误
+	if (FLAGS_logtoconsole)
+	{
+		pSink->locked_backend()->add_stream(
+		        boost::shared_ptr<std::ostream>(&std::clog, boost::log::empty_deleter()));
+	}
 
 	pSink->locked_backend()->set_formatter(
-	        fmt::format("%1%: %2% - %3%") % fmt::attr<unsigned int>("LineID", keywords::format =
-	                "%08x")
-	                % fmt::attr<boost::log::attributes::current_thread_id::held_type>("ThreadID")
-	                % fmt::attr<boost::log::trivial::severity_level>("Severity") % fmt::message());
+			formatters::format("[%1%][%2%][%3%]%4%")
+				% formatters::attr<unsigned int>("Line #", keywords::format = "%08x")
+				% formatters::date_time<boost::posix_time::ptime>("TimeStamp")
+				% formatters::attr<boost::thread::id>("ThreadID", keywords::format = "%05d")
+				% formatters::message()
+	);
+
+	pSink->set_filter(boost::log::filters::attr<SeverityLevel>("Severity", std::nothrow) >= INFO);
+
+    core->add_global_attribute("Line #", boost::make_shared<attributes::counter<unsigned int>>());
+    core->add_global_attribute("TimeStamp", boost::make_shared<attributes::local_clock>());
+    core->add_global_attribute("ThreadID", boost::make_shared<attributes::current_thread_id>());
 
 	core->add_sink(pSink);
 }
 
-BoostLogInit::~BoostLogInit()
+boost::log::sources::severity_logger<SeverityLevel>& ELog::GetSLog()
 {
+	return slog;
 }
 
 } // Egametang

+ 15 - 9
Cpp/Platform/Log/Log.h

@@ -7,25 +7,31 @@
 #include <string>
 #include <boost/shared_ptr.hpp>
 #include <boost/log/trivial.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/log/sinks/sync_frontend.hpp>
-#include <boost/log/sinks/text_ostream_backend.hpp>
+#include <boost/log/sources/severity_logger.hpp>
 
 namespace Egametang {
 
-#define ELOG(level) BOOST_LOG_TRIVIAL(level) << "[" << FileName(__FILE__) << ":" << __LINE__ << "] "
+#define ELOG(level) BOOST_LOG_SEV(ELog::GetSLog(), level) << "[" << FileName(__FILE__) << ":" << __LINE__ << "] "
 
 std::string FileName(const char* s);
 
-class BoostLogInit
+enum SeverityLevel
+{
+	INFO       = 0,
+	WARNING    = 1,
+	ERROR      = 2,
+	FATAL      = 3,
+};
+
+class ELog: public boost::noncopyable
 {
 private:
-	typedef boost::log::sinks::synchronous_sink<boost::log::sinks::text_ostream_backend> text_sink;
-	boost::shared_ptr<text_sink> pSink;
+	static bool isInit;
+	static boost::log::sources::severity_logger<SeverityLevel> slog;
 
 public:
-	BoostLogInit(const char* fileName);
-	~BoostLogInit();
+	static void Init(const char* fileName);
+	static boost::log::sources::severity_logger<SeverityLevel>& GetSLog();
 };
 }
 #endif // BASE_LOG_H

+ 2 - 4
Cpp/Platform/Log/LogTest.cc

@@ -3,7 +3,6 @@
 
 #include <gtest/gtest.h>
 #include <gmock/gmock.h>
-#include <glog/logging.h>
 #include <gflags/gflags.h>
 #include "Log/Log.h"
 
@@ -15,17 +14,16 @@ class LogTest: public testing::Test
 
 TEST_F(LogTest, Log)
 {
-	ELOG(trace) << "Test ELOG Marco!";
+	ELOG(INFO) << "Test ELOG Marco!";
 }
 
 } // namespace Egametang
 
 int main(int argc, char* argv[])
 {
-	Egametang::BoostLogInit log(argv[0]);
 	testing::InitGoogleTest(&argc, argv);
-	google::InitGoogleLogging(argv[0]);
 	google::ParseCommandLineFlags(&argc, &argv, true);
+	Egametang::ELog::Init(argv[0]);
 	return RUN_ALL_TESTS();
 }