log4cpp安装使用
1. 主页:http://log4cpp.sourceforge.net
“Log4cpp is library of C++ classes for flexible logging to files, syslog, IDSA and other destinations. It is modeled after the Log4j Java library, staying as close to their API as is reasonable.”
api文档地址:http://log4cpp.sourceforge.net/api/hierarchy.html
2.下载安装
环境:ubuntu 14.04 LTS,gcc 4.8.4
下载源码包 log4cpp-1.1.2rc1.tar.gz
$tar xzvf log4cpp-1.1.2rc1.tar.gz
$cd log4cpp
$./configure --with-pthreads
$make
$make check
$make install
安装完成后,头文件在/usr/local/include/log4cpp,库安装在/usr/local/lib/,文件名liglog4cpp.so.5.0.6,还有几个符号链接
3.测试
测试代码 main.cpp
#include "log4cpp/Category.hh" #include "log4cpp/PropertyConfigurator.hh" int main(int argc, char* argv[]) { std::string initFileName = "log4cpp.properties"; log4cpp::PropertyConfigurator::configure(initFileName); log4cpp::Category& root = log4cpp::Category::getRoot(); log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1")); log4cpp::Category& sub2 = log4cpp::Category::getInstance(std::string("sub1.sub2")); root.warn("Storm is coming"); sub1.debug("Received storm warning"); sub1.info("Closing all hatches"); sub2.debug("Hiding solar panels"); sub2.error("Solar panels are blocked"); sub2.debug("Applying protective shield"); sub2.warn("Unfolding protective shield"); sub2.info("Solar panels are shielded"); sub1.info("All hatches closed"); root.info("Ready for storm."); log4cpp::Category::shutdown(); return 0; }
编译:g++ main.cpp -L/usr/local/lib -llog4cpp -pthread -I/usr/local/include -o main
log配置文件:log4cpp.properties
log4cpp.rootCategory=DEBUG, rootAppender log4cpp.category.sub1=DEBUG, A1, A2 log4cpp.category.sub1.sub2=DEBUG, A3 log4cpp.appender.rootAppender=ConsoleAppender log4cpp.appender.rootAppender.layout=PatternLayout log4cpp.appender.rootAppender.layout.ConversionPattern=%d [%p] %m%n log4cpp.appender.A1=FileAppender log4cpp.appender.A1.fileName=A1.log log4cpp.appender.A1.layout=BasicLayout log4cpp.appender.A2=FileAppender log4cpp.appender.A2.threshold=WARN log4cpp.appender.A2.fileName=A2.log log4cpp.appender.A2.layout=PatternLayout log4cpp.appender.A2.layout.ConversionPattern=%d [%p] %m%n log4cpp.appender.A3=RollingFileAppender log4cpp.appender.A3.fileName=A3.log log4cpp.appender.A3.maxFileSize=200 log4cpp.appender.A3.maxBackupIndex=1 log4cpp.appender.A3.layout=PatternLayout log4cpp.appender.A3.layout.ConversionPattern=%d [%p] %m%n
4.简单封装
Log.h
#ifndef LOG_H #define LOG_H #include <log4cpp/Category.hh> #include <log4cpp/PropertyConfigurator.hh> #include <log4cpp/Priority.hh> #include <stdarg.h> #include <syslog.h> // confirm to log4cpp::priority::PriorityLevel #define DEBUG_LEVEL 700 #define INFO_LEVEL 600 #define WARN_LEVEL 400 #define ERROR_LEVEL 300 #define FATAL_LEVEL 0 #define LOG(level,format, args...) do {\ Log::getInstance().write(level, __FUNCTION__, format, ##args);\ }while(0); class Log { public: static Log& getInstance() { return instance_;} void write(int level, const char* func, const char* format, ...); private: Log(); virtual ~Log(); void init(); void cleanup(); log4cpp::Priority::Value currentPriority(); void formatFunc(const char* func, const char* format, va_list alist, std::string& msg); private: static Log instance_; log4cpp::Category* logger_; }; #endif // LOG_H
Log.cpp
#include "Log.h" #include <syslog.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <pthread.h> #include <sys/timeb.h> #include <time.h> #include <errno.h> #include <string.h> #include <stdlib.h> #include <stdio.h> #include <stdexcept> #include <log4cpp/Configurator.hh> using std::string; #define BUF_LEN 4096 //int fdLog_ = -1; Log Log::instance_; Log::Log() { syslog(LOG_INFO, "Log constructor"); init(); } Log::~Log() { syslog(LOG_INFO, "Log deconstructor"); cleanup(); } void Log::init() { logger_ = NULL; try { std::string basePath("/myapp/lib/"); std::string confFile = basePath + "log4cpp.priority"; log4cpp::PropertyConfigurator::configure(confFile); log4cpp::Category& root = log4cpp::Category::getRoot(); log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1")); logger_ = &sub1; } catch(std::exception const& e) { syslog(LOG_NOTICE, "init log error[%s]", e.what()); } catch(...) { syslog(LOG_INFO, "init log error[%d, %s]", errno, strerror(errno)); } syslog(LOG_INFO, "log init finished"); } void Log::cleanup() { log4cpp::Category::shutdown(); } int Log::currentPriority() { if (logger_) { return logger_->getPriority(); } return INFO_LEVEL; } void Log::write(int level, const char* func, const char* format, ...) { if (Config::getInstance().NoLogOutput_) { return; } if (level > currentPriority()) { return; } if (NULL == logger_) { return; } std::string info; va_list alist; va_start (alist, format); formatFunc(func, format, alist, info); va_end(alist); try { switch(level) { case FATAL_LEVEL: logger_->fatal(info); break; case ERROR_LEVEL: logger_->error(info); break; case WARN_LEVEL: logger_->warn(info); break; case INFO_LEVEL: logger_->info(info); break; case DEBUG_LEVEL: logger_->debug(info); break; default: break; } } catch(...) { syslog(LOG_INFO, "output log failed"); } } void Log::formatFunc(const char* func, const char* format, va_list alist, std::string& msg) { char buf[BUF_LEN] = {0}; int prefixLen = snprintf(buf, BUF_LEN-1, " 0x%lX %s(): ",\ pthread_self(), func); int contentLen = vsnprintf(buf+prefixLen, BUF_LEN-1-prefixLen, format, alist); int dataLen = prefixLen + contentLen; buf[dataLen] = '\n'; msg = buf; } #endif