轉載請註明出處:http://blog.csdn.net/jmppok/article/details/17375057
ios
C++程序在後臺運行時,可經過log4cplus記錄日誌。當C++程序運行在遠程服務器上時,咱們就須要遠程登錄到該服務器才能查看日誌。進一步,若是該C++程序一個並行程序或者分佈式程序,爲了查看程序的運行狀態,咱們就須要登錄到N臺服務器上,tail -f xx.log.這種情形聽起來就很使人不爽,而實際上,不少服務端開發者都遇到過或正在遭受這個問題的困擾。express
做爲Log4J的翻版,Log4cplus也提供了SockeAppender,能夠經過SocketAppender將日誌輸出到一個指定的log server上,從而解決上述問題。apache
關於Log4cplus的介紹,請參考C++開源日誌庫log4cplus服務器
在Log4cplus的源碼包中,有一個loggingServer目錄,該目錄中實現了一個LoggingServer。app
在編譯Log4cplus時,會自動編譯該目錄,在目錄中生成loggingServer可執行文件,固然能夠本身make(須要依賴log4cplus庫)。框架
loggingServer使用方式以下:less
./loggingserver 9000 log4cplus.properties
log4cplus.properties是一個log4cplus的配置文件,和普通的log4cplus配置文件相同,loggingserver收到各個socket發來的日誌後,根據配置文件信息,將其寫入文件。socket
下面是一個簡單的配置文件示例:分佈式
log4cplus.rootLogger=DEBUG, STDOUT, ALL_MSGS log4cplus.appender.STDOUT=log4cplus::ConsoleAppender log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout #log4cplus.appender.STDOUT.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n log4cplus.appender.STDOUT.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n #設置日誌追加到文件尾 log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender #設置日誌文件大小 log4cplus.appender.ALL_MSGS.MaxFileSize=100MB #設置生成日誌最大個數 log4cplus.appender.ALL_MSGS.MaxBackupIndex=10 #設置輸出日誌路徑 log4cplus.appender.ALL_MSGS.File=log/test.log log4cplus.appender.ALL_MSGS.layout=log4cplus::PatternLayout #設置日誌打印格式 #log4cplus.appender.ALL_MSGS.layout.ConversionPattern=|%D:%d{%Q}|%p|%t|%l|%m|%n log4cplus.appender.ALL_MSGS.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n #匹配相同日誌級別,只有debug日誌才輸入到該文件中 #log4cplus.appender.ALL_MSGS.filters.1=log4cplus::spi::LogLevelMatchFilter #log4cplus.appender.DEBUG_MSGS.filters.1.LogLevelToMatch=DEBUG #log4cplus.appender.DEBUG_MSGS.filters.1.AcceptOnMatch=true #log4cplus.appender.DEBUG_MSGS.filters.2=log4cplus::spi::DenyAllFilter
// Module: LOG4CPLUS // File: loggingserver.cxx // Created: 5/2003 // Author: Tad E. Smith // // // Copyright 2003-2010 Tad E. Smith // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include <cstdlib> #include <iostream> #include <log4cplus/configurator.h> #include <log4cplus/socketappender.h> #include <log4cplus/helpers/socket.h> #include <log4cplus/thread/threads.h> #include <log4cplus/spi/loggingevent.h> namespace loggingserver { class ClientThread : public log4cplus::thread::AbstractThread { public: ClientThread(log4cplus::helpers::Socket clientsock) : clientsock(clientsock) { std::cout << "Received a client connection!!!!" << std::endl; } ~ClientThread() { std::cout << "Client connection closed." << std::endl; } virtual void run(); private: log4cplus::helpers::Socket clientsock; }; } int main(int argc, char** argv) { if(argc < 3) { std::cout << "Usage: port config_file" << std::endl; return 1; } int port = std::atoi(argv[1]); const log4cplus::tstring configFile = LOG4CPLUS_C_STR_TO_TSTRING(argv[2]); log4cplus::PropertyConfigurator config(configFile); config.configure(); log4cplus::helpers::ServerSocket serverSocket(port); if (!serverSocket.isOpen()) { std::cout << "Could not open server socket, maybe port " << port << " is already in use." << std::endl; return 2; } while(1) { loggingserver::ClientThread *thr = new loggingserver::ClientThread(serverSocket.accept()); thr->start(); } return 0; } //////////////////////////////////////////////////////////////////////////////// // loggingserver::ClientThread implementation //////////////////////////////////////////////////////////////////////////////// void loggingserver::ClientThread::run() { while(1) { if(!clientsock.isOpen()) { return; } log4cplus::helpers::SocketBuffer msgSizeBuffer(sizeof(unsigned int)); if(!clientsock.read(msgSizeBuffer)) { return; } unsigned int msgSize = msgSizeBuffer.readInt(); log4cplus::helpers::SocketBuffer buffer(msgSize); if(!clientsock.read(buffer)) { return; } log4cplus::spi::InternalLoggingEvent event = log4cplus::helpers::readFromBuffer(buffer); log4cplus::Logger logger = log4cplus::Logger::getInstance(event.getLoggerName()); logger.callAppenders(event); } }
前面啓動了LoggingServer,下面說一下須要收集其日誌的各個應用程序中配置。工具
說白了,就是在原來的基礎上加一個SocketAppender,SocketAppender會自動將日誌發送給loggingserver。這樣直接在loggingserver上就能夠查看全部服務器上的日誌信息啦。哥終於不用再擔憂大家的運行狀態啦!
log4cplus.rootLogger=DEBUG, STDOUT, ALL_MSGS,RemoteServer log4cplus.appender.STDOUT=log4cplus::ConsoleAppender log4cplus.appender.STDOUT.layout=log4cplus::PatternLayout #log4cplus.appender.STDOUT.layout.ConversionPattern=%d{%m/%d/%y %H:%M:%S} [%t] %-5p %c{2} %%%x%% - %m [%l]%n log4cplus.appender.STDOUT.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n #設置日誌追加到文件尾 log4cplus.appender.ALL_MSGS=log4cplus::RollingFileAppender #設置日誌文件大小 log4cplus.appender.ALL_MSGS.MaxFileSize=100MB #設置生成日誌最大個數 log4cplus.appender.ALL_MSGS.MaxBackupIndex=10 #設置輸出日誌路徑 log4cplus.appender.ALL_MSGS.File=log/test.log log4cplus.appender.ALL_MSGS.layout=log4cplus::PatternLayout #設置日誌打印格式 #log4cplus.appender.ALL_MSGS.layout.ConversionPattern=|%D:%d{%Q}|%p|%t|%l|%m|%n log4cplus.appender.ALL_MSGS.layout.ConversionPattern=[%-5p %d{%y-%m-%d %H:%M:%S}] [%l]%n%m%n%n #匹配相同日誌級別,只有debug日誌才輸入到該文件中 #log4cplus.appender.ALL_MSGS.filters.1=log4cplus::spi::LogLevelMatchFilter #log4cplus.appender.DEBUG_MSGS.filters.1.LogLevelToMatch=DEBUG #log4cplus.appender.DEBUG_MSGS.filters.1.AcceptOnMatch=true #log4cplus.appender.DEBUG_MSGS.filters.2=log4cplus::spi::DenyAllFilter log4cplus.appender.RemoteServer=log4cplus::SocketAppender log4cplus.appender.RemoteServer.host=localhost log4cplus.appender.RemoteServer.port=9000
上面第一行的RemoteServer和最後三行即爲添加一個SocketAppender。將日誌發送到遠端的loggingserver。
固然對本地的日誌記錄沒有影響,本地仍正常記錄。
同時咱們還能夠設置多個RemoetServer....,不過貌似也沒這個必要...
固然咱們能夠實現本身的loggingserver,更加的高端大氣上檔次。
a.未來自不一樣客戶端的日誌分別存儲;
b.不一樣級別的日誌單獨存儲;
c.在發現錯誤時,郵件通知;
d.實現一個B/S的日誌瀏覽工具;
e.日誌入庫;
f.存入HDFS,用Hadoop Map/Reduce挖掘;
g.接入Storm(實時流處理框架)對其進行分析;
...