开源框架log4cpp实战(开源gui框架)
gudong366 2025-07-18 16:31 4 浏览
1.Log4cpp使用
Log4cpp中主要包含Category(种类),Appender(附加器),Layout(布局),Priorty(优先级),NDC(嵌套的诊断上下文)。
Category、Appender与Layout三者的关系如下图:
2.安装
官网地址
:https://sourceforge.net/projects/log4cpp/files/latest/downloa
解压:
tar zxf log4cpp-1.1.3.tar.gz
编译:
cd log4cpp
./configure
make
make check
sudo make install
sudo ldconfig
默认安装路径:
头文件:
/usr/local/include/log4cpp
库文件:/usr/local/lib/liblog4cpp
测试范例
使用log4cpp的基本步骤如下:
1.实例化一个layout对象
2.初始化一个appender对象
3.把layout对象附着在appender对象
4.调用
log4cpp::Category::getInstance("name")。实例化一个category对象;
5.把appender对象附加到category上,根据additivity的值取代其它appender或附加在其它appender后。
6.设置category的优先级
简单来说,上面存在这样一种关系:
layout-->appender-->category
#include "log4cpp/Category.hh"
#include "log4cpp/FileAppender.hh"
#include "log4cpp/BasicLayout.h
int main(int argc,char *argv[])
{
// 1实例化一个layout 对象
log4cpp::Layout *layout = new log4cpp::BasicLayout();
//2. 初始化一个appender 对象
log4cpp::Appender *appender = new log4cpp::FileAppender("FileAppender", "./test_log4cpp1.log");
// 3. 把layout对象附着在appender对象上
appender->setLayout(layout);
//4. 实例化一个category对象
log4cpp::Category &warn_log = log4cpp::Category::getInstance("qaa");
//5. 设置additivity为false,替换已有的appender
warn_log.setAdditivity(false);
//6 把appender对象附到category上
warn_log.setAppender(appender);
//设置category的优先级,低于此优先级的日志不被记录
warn_log.setPriority(log4cpp::Priority::WARN);
//记录一些日志
warn_log.info("Program info which cannot be wirten");
warn_log.debug("This debug message will fail to write");
warn_log.alert("Alert info");
//其他记录日志方式
warn_log.log(log4cpp::Priority::WARN, "This will be a logged war
ning");
log4cpp::Priority::PriorityLevel priority;
bool this_is_critical = true;
if (this_is_critical)
priority = log4cpp::Priority::CRIT;
else
priority = log4cpp::Priority::DEBUG;
warn_log.log(priority, "Importance depends on context");
warn_log.critStream()<<"This will show up << as"<<1<<"critical message";
// clean up and flush all appenders
log4cpp::Category::shutdown();
return 0;
}
编译:g++ -o test_log4cpp1 test_log4cpp1.cpp -llog4cpp -lpthread
配置文件使用步骤
基本步骤:
1.读取解析配置文件。
2.实例化category对象。
3.正常使用这些category对象进行日志处理。
# 文件名: test_log4cpp2.conf
# a simple test config
#定义了3个category sub1, sub2, sub1.sub2
log4j.rootCategory=DEBUG, rootAppender
log4j.category.sub1=A1
log4j.category.sub2=INFO
log4j.category.sub1.sub2=ERROR, A2
# 设置sub1.sub2 的additivity属性
log4j.additivity.sub1.sub2=false
#定义rootAppender类型和layout属性
log4j.appender.rootAppender=org.apache.log4j.ConsoleAppender
log4j.appender.rootAppender.layout=org.apache.log4j.BasicLayout
#定义A1的属性
log4j.appender.A1=org.apache.log4j.FileAppender
log4j.appender.A1.fileName=A1.log
log4j.appender.A1.layout=org.apache.log4j.SimpleLayout
#定义A2的属性
log4j.appender.A2=org.apache.log4j.ConsoleAppender
log4j.appender.A2.layout=org.apache.log4j.PatternLayout
#log4j.appender.A2.layout.ConversionPattern=The message '%m' at time%d%n
log4j.appender.A2.layout.ConversionPattern=%d %m %n
// FileName: test_log4cpp2.cpp
// Test log4cpp by config file.
#include "log4cpp/Category.hh"
#include "log4cpp/PropertyConfigurator.hh"
int main(int argc, char *argv[])
{
//1 读取解析配置文件
// 读取出错, 完全可以忽略,可以定义一个缺省策略或者使用系统缺省策略
// BasicLayout输出所有优先级日志到ConsoleAppender
try{
log4cpp::PropertyConfigurator::configure(("./test_log4cpp2.conf");
}catch(log4cpp::ConfigureFailure& f){
std::cout << "Configure Problem " <<f.what()<<std::endl;
return -1;
}
// 2 实例化category对象
// 这些对象即使配置文件没有定义也可以使用,不过其属性继承其父category
// 通常使用引用可能不太方便,可以使用指针,以后做指针使用
// log4cpp::Category* root = &log4cpp::Category::getRoot();
log4cpp::Category& root = log4cpp::Category::getRoot() ;
log4cpp::Category& sub1 = log4cpp::Category::getInstance(std::string("sub1"));
log4cpp::Category& sub3 = log4cpp::Category::getInstance(std::string("sub1.sub2"));
// 3 正常使用这些category对象进行日志处理。
// sub1 has appender A1 and rootappender.
sub1.info("This is some info");
sub1.alert("A warning");
// sub3 only have A2 appender.
sub3.debug("This debug message will fail to write");
sub3.alert("All hands abandon ship");
sub3.critStream() << "This will show up << as " << 1 << " critical message";
sub3 << log4cpp::Priority::ERROR
<< "And this will be an error";
sub3.log(log4cpp::Priority::WARN, "This will be a logged warning");
return 0;
}
编译:g++ -o test_log4cpp2 test_log4cpp2.cpp -llog4cpp -lpthread
Category类
这个是归类的意思,具有树型结构,将日志按"区域"划分。Log4cpp有且只一个根Category,可以有多个子Category组成树型结构。Category具有Priority、additivity属性与若干方法。下面列出所有的属性与常用方法。
属性:Name
Category的名称。不可重复。
相关方法
virtual const std::string& getName() const throw();
属性:Priority
日志的优先级
对于根Category,必须指定Priority。(priority < Priority::NOTSET)
对于非根Category,可以不指定Priority,此时优先级继承自父Category。
对于非根Category,也可以指定Priority,此时优先级覆盖父Category的优先级。
//设置当前Category的优先级
virtual void setPriority(Priority::Value priority);
//获取当前对象的优先级
virtual Priority::Value getPriority() const throw();
// 设置root Category的优先级
static void setRootPriority(Priority::Value priority);
// 获取root Category的优先级
static Priority::Value getRootPriority() throw();
//获取当前category继承表中的优先级,如果当前的优先值没有设置的话,则找他的父亲。
//如果父亲没有找到的话,他会继续向上找,因为root Category的优先值默认为Priority::INFO
//所以肯定能找到
virtual Priority::Value getChainedPriority() const throw();
// 返回当前拥有priority优先级
virtual bool isPriorityEnabled(Priority::Value priority) const throw();
属性:additivity
每个Category都有一个additivity属性,该属性默认值为true。
如果值为true,则该Category的Appender包含了父Category的Appender。
如果值为false,则该Category的Appender取代了父Category的Appender。
相关方法
virtual void setAdditivity(bool additivity);
virtual bool getAdditivity() const throw();
属性:parent
上级Category。根Category的parent为空。
相关方法
virtual Category* getParent() throw();
virtual const Category* getParent() const throw();
方法:getRoot
静态方法。取得根Category。
static Category& getRoot();
方法:getInstance
静态方法。取得指定名称(参数name)的Category,如果不存在,则自动创建一个以name命名,parent为rootCategory,Priority为INFO的Category(说白了就是一个工厂方法,不要和单例模式混了)。
static Category& getInstance(const std::string& name);
方法:exists
静态方法。判断是否存在指定名称(参数name)的Category。如果存在,则返回相应的Category(指针),否则返回空指针。
static Category* exists(const std::string& name);
方法:shutdownForced
静态方法。从所有的Category中移除所有的Appender,并且删除所有的Appender。(shutdown方法只是不使用Appender,并没有彻底从内存中销毁Appender)。
static void shutdownForced();
方法:Appender相关
//添加一个Appender到Category中。
// 该方法将把Appender的所有权交给Category管理
virtual void addAppender(Appender* appender);
// 添加一个Appender到Category中。
// 但是该方法并不把Appender的所有权交给Category管理
virtual void addAppender(Appender& appender);
// 获取指定名字的Appender(指针)。如果不存在则返回空指针
virtual Appender* getAppender(const std::string& name) const;
// 获取所有的Appender,以指针的方式存储在set中
virtual AppenderSet getAllAppenders() const;
// 删除所有的Appender
virtual void removeAllAppenders();
// 删除指定的Appender
virtual void removeAppender(Appender* appender);
// 判断指定Appender是否被当前Category拥有所有权。如果是的话,在删除该Appender时,将同时销毁它。
virtual bool ownsAppender(Appender* appender) const throw();
使用virtual void addAppender(Appender* appender);方法时,Category会接管appender的所有权,并确保会在合适的时机销毁它,所以不要再在外面调用delete方法去销毁它。所以不要轻易删除。
如下面代码:
log4cpp::Appender*appender = new log4cpp::OstreamAppender("default", &std::cout);
root.addAppender(appender);
delete appender; // Error! Don't delete it
方法:日志相关
Category的日志输出方式有两种,一种是简单的传递std::string类型的字符串,一种是采用类似c api中的printf,可以格式化生成字符串。
// 以指定的优先级生成日志
virtual void log(Priority::Value priority,const std::string& message) throw();
//以指定的优先级与格式化生成日志,类似c api中的printf方法
virtual void log(Priority::Value priority, const char* stringFormat,...) throw();
// 格式化生成日志的一种变体,直接传递va_list参数
virtual void logva(Priority::Value priority, const char* stringFormat,va_list va) throw();
//除了以上三种通用日志三种方法外,Log4cpp还指供了多种预定义Priority的方法,如:
void debug(const char* stringFormat, ...) throw();
void info(const char* stringFormat, ...) throw();
.....
例子:
log4cpp::Category& rootCategory = log4cpp::Category::getRoot();
rootCategory.error("This is error message\n");
rootCategory.log(log4cpp::Priority::DEBUG, "This is %d message\n", 8);
方法: CategoryStream
每个CategoryStream对象封装一种优先级的日志输出,并提供了对“<<”符号的重载函数。CategoryStream对象内部借由std::ostringstream来实现流式格式化输出生成日志消息(std::string)。
// 获取(生成)指定优先级的CategoryStream
virtual CategoryStream getStream(Priority::Value priority);
// 对运算符“<<”的重载。也是获取(生成)指定优先级的CategoryStream
virtual CategoryStream operator<<(Priority::Value priority);
// 快捷方法。还有infoStram()等预定义优先级的快捷方法。
inline CategoryStream debugStream();
.....
CategoryStream只是作为临时对象,总在对象销毁时才会正真将日志输出(flush)。可以强制调用CategoryStream的flush方法,这样会不利于阅读,日志代码应该跟实际业务无关,代码行尽可能少,随时可以屏蔽日志功能。
例子:
log4cpp::Category& root = log4cpp::Category::getRoot();
root << log4cpp::Priority::ERROR << "This is error message";
root.debugStream() << "This is " << 8 << " message";
Appender类
Appender负责把日志写入相应设备,如控制台,文件,调试器,windows日志,syslog等。
比如下面输出到文件系统中。
FileAppender
作用:输出到文件系统。
构造函数:
FileAppender(const std::string& name, const std::string& fileName,bool append = true, mode_t mode = 00644);
DailyRollingFileAppender
功能:
一种特例化的FileApppender,文件系统以天为单位进行管理,当生成日志时的日期发生变化时,将会生成新的日志文件。
构造函数:
DailyRollingFileAppender(const std::string& name,const std::string& fileName,unsigned int maxDaysToKeep = maxDaysToKeepDefault,bool append = true,mode_t mode = 00644);
OstreamAppender
作用:输出到指定流,需要指定std:ostream对象,可以是std::cout或std::cerr或其它派生自std::ostream的流对象。
构造函数:OstreamAppender(const std::string& name, std::ostream* stream);
例子:
log4cpp::OstreamAppender * osAppender = new log4cpp::OstreamAppender("osAppender",&std::cout);
RemoteSyslogAppender
作用:输出到远程syslog系统。
构造函数:
RemoteSyslogAppender(const std::string& name,
const std::string& syslogName,
const std::string& relayer,
int facility = LOG_USER,
int portNumber = 514);
相关参数:
SmptAppender
作用:通过smtp协议发送到指定邮箱。
构造函数:
SmptAppender(const std::string& name, const std::string& host, const std::string& from,const std::string& to, const std::string& subject);
相关参数:
StringQueueAppender
作用:输出到内存/字符串队列。
构造函数:StringQueueAppender(const std::string& name);
相关参数:
SyslogAppender
作用:输出到本地syslog系统。
相关参数:
SyslogAppender(const std::string& name, const std::string& syslogName,int facility = LOG_USER);
BufferingAppender
作用:输出到缓存队列
Win32DebugAppender
作用:输出到Windows缺省调试器。
IdsaAppender
作用:输出到Idsa服务。
NTEventLogAppender
输出到Windows日志系统
Layout类
Layout控制输出日志的显示样式。Log4cpp内置了4种Layout。
PassThroughLayout
没有布局的“布局”,你让它写什么它就写什么,它不会为你添加任何东,连换行符都懒得为你加。
SimpleLayout
简单布局。只有简单优先级输出,相当于PatternLayout格式化为:“%p: %m%n”。
BasicLayout
基本布局。添加“时间”、“优先级”、“种类”、“NDC”。相当于PatternLayout格式化“%R %p %c %x: %m%n”
PatternLayout
格式化布局。它的使用方式类似C语言中的printf,使用格式化它符串来描述输出格式。目前支持的转义定义如下:
%% - 转义字符'%'
%c - Category
%d - 日期,如%d{%H:%M:%S,%l}。日期的格式符号与ANSI C函数strftime中的一致。但增加了一个格式符号%l,表示毫秒,占三个十进制位。
%m - 消息
%n - 换行符;会根据平台的不同而不同,但对用户透明。
%p - 优先级
%r - 自从layout被创建后的毫秒数
%R - 从1970年1月1日开始到目前为止的秒数
%u - 进程开始到目前为止的时钟周期数
%x - NDC
%t - 线程id
Priority优先级
日志的优先级。Log4cpp内置了10种优先级。
typedef enum {
EMERG = 0,
FATAL = 0,
ALERT = 100,
CRIT = 200,
ERROR = 300,
WARN = 400,
NOTICE = 500,
INFO = 600,
DEBUG = 700,
NOTSET = 800
} PriorityLevel;
取值越小,优先级越高。如一个Category的优先级为INFO(600),则包括EMEGR、FATAL、ALERT、CRIT、ERROR、WARN、INFO等小于或等于600的日志都会被输出,而DEBUG等大于600的日志则不会被输出。
注意:优先级是一个整数,不一定要只取上面的预定义值,比如说101也是可以。对于根Category,优先级不能大于或等于NOTSET(800)。
NDC
NDC是以线程为基础的,每个线程拥有且只有一个NDC。NDC的几个常用方法是push、pop、get、clear。
Push:把一个字符串压入NDC栈。
Pop:从NDC栈中退出上一次压入的字符串。
Get:取得当前NDC栈中的字符串,每次压入的字符串用空格隔开。
Clear:清空NDC栈中的字符串。
NDC用法可以在每个函数入口处调用NDC::push(__FUNCTION__); 在函数出口处调用NDC::pop(); 在PatternLayout中指定%x参数。这样就可以在日志中清晰的知道函数的调用情况。
这篇文章就分析到这里,欢迎关注,转发,点赞,收藏。
相关推荐
- linux sed系列 第四篇:sed工业实战——日志处理与数据清洗
-
“掌握了sed的编程能力后,我们如同装备精良的工匠,终于可以踏入真实的工业战场。本篇将聚焦sed在日志分析、数据合规化、多文件批处理等场景中的应用,看它如何在海量数据中游刃有余,展现文本处理的...
- Linux下sed的简单使用(linux中sed是什么意思)
-
1、sed简介stremeditor流编辑器,它是一项Linux指令,功能同awk类似,差别在于,sed简单,对列处理的功能要差一些,awk的功能复杂,对列处理的功能比较强大,sed编辑器是一行一...
- linux基础命令之date命令(linux中的date)
-
date命令主要用于显示或者设置系统时间语法格式:date参数对象使用date命令时,最好先使用date--help命令查看支持哪些参数,有些小型Linux系统下的date命令,只支持一些基本参...
- Ubuntu linux 常用命令(ubuntu常用的50个命令)
-
使用dpkg命令来安装.deb包。sudodpkg-i~/example.deb如果在安装过程中遇到依赖问题,可以使用以下命令来修复:sudoapt-getinstall-f将flut...
- Linux基础命令-sed命令(linux教程:sed命令的用法)
-
Sed全名streameditor流编辑器,它是一个强大的文本处理工具,它可以从文件中接受输入,也可以接受来自标准输入流的输入,它擅长取行。Sed的用途非常广泛,包括:1)文本替换2)选择性的输...
- linux sed系列 第二篇:sed进阶技巧——地址定位与正则表达式
-
“上一篇我们掌握了sed的基础替换,如同获得了第一把钥匙。现在,让我们更进一步,学习如何精准锁定目标行,如同拥有了导航地图,让每一次操作都直击要害!”地址定位的四种维度sed的强大,很大程度上源...
- 火狐Firefox浏览器140发布:手动Unload标签页、优化翻译体验等
-
IT之家6月24日消息,Mozilla在发布版本139不到一个月后,推出了最新的开源网页浏览器Firefox140。新版本增加了手动Unload标签页的功能,优化了垂直标签页的调...
- Linux 基本正则表达式及扩展正则表达式功能举例
-
在Linux中,正则表达式(RegularExpression)是一种强大的模式匹配工具,用于在文本中查找、匹配和处理特定模式的字符串。Linux支持两种类型的正则表达式:基本正则表达式(Basic...
- linux下find命令的经典26个使用示例
-
简介find命令是基于unix的操作系统中常用的工具之一。顾名思义,它在目录层次结构中查找文件和目录。用户可以传递不同的参数,并根据文件的名称、扩展名、类型、大小、权限、修改时间、所有者、组等搜索文件...
- linux运维中特殊符号的应用与实践
-
路径位置类的特殊符号(1)、波浪线(~)在linux系统的命令行中,~表示用户的家目录,超级用户为/root,普通用户为/home。假设我当前目录在usr/local下[root@xrylocal]...
- 开源框架log4cpp实战(开源gui框架)
-
1.Log4cpp使用Log4cpp中主要包含Category(种类),Appender(附加器),Layout(布局),Priorty(优先级),NDC(嵌套的诊断上下文)。Category、App...
- Linux find命令详解(linux find -l)
-
一、命令介绍Linuxfind命令是类unix操作系统中最重要和最常用的命令行实用程序之一。find命令用于根据指定的条件搜索和定位与参数匹配的文件和目录列表。find命令提供了广泛的选项,允许用户...
- Linux运维:单引号与双引号的使用(linux 单引号和双引号)
-
1、单引号的使用单引号可以将它中间的所有任意字符还原为字面意义,实现屏蔽Shell元字符的功能。注意不可以在两个单引号中间单独插入一个单引号,单引号必须成对出现。示例1:定义一个变量,并输出变量的...
- Linux技巧:find 命令用法详细说明,看完会有收获
-
在Linux命令中,find是比较复杂难用的命令。使用该命令搜索文件时,常常发现自己找了一些例子能用,但稍微改一下条件,就搜不到想要的结果。下面会以一些实例来说明使用find命令的关键要点和...
- Linux Shell中单引号、双引号、反引号的解释
-
1、单引号('')单引号所见即所得,直接显示单引号里的内容。即单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的。比如下面的例子,单引号所见即所得。2、双引号("...
- 一周热门
- 最近发表
-
- linux sed系列 第四篇:sed工业实战——日志处理与数据清洗
- Linux下sed的简单使用(linux中sed是什么意思)
- linux基础命令之date命令(linux中的date)
- Ubuntu linux 常用命令(ubuntu常用的50个命令)
- Linux基础命令-sed命令(linux教程:sed命令的用法)
- linux sed系列 第二篇:sed进阶技巧——地址定位与正则表达式
- 火狐Firefox浏览器140发布:手动Unload标签页、优化翻译体验等
- Linux 基本正则表达式及扩展正则表达式功能举例
- linux下find命令的经典26个使用示例
- linux运维中特殊符号的应用与实践
- 标签列表
-
- linux一键安装 (31)
- linux运行java (33)
- ln linux (27)
- linux 磁盘管理 (31)
- linux 内核升级 (30)
- linux 运行python (28)
- linux 备份文件 (30)
- linux 网络测试 (30)
- linux 网关配置 (31)
- linux jre (32)
- linux 杀毒软件 (32)
- linux语法 (33)
- linux博客 (33)
- linux 压缩目录 (37)
- linux 查看任务 (32)
- 制作linux启动u盘 (35)
- linux 查看存储 (29)
- linux乌班图 (31)
- linux挂载镜像 (31)
- linux 软件源 (28)
- linux题目 (30)
- linux 定时脚本 (30)
- linux 网站搭建 (28)
- linux 远程控制 (34)
- linux bind (31)