log4cpp深度封装[通俗易懂]

log4cpp深度封装[通俗易懂]简介关于log4cpp的介绍与好处就不再赘言了,百度一搜一大把。主要是对于log4cpp的使用如果不封装一下,感觉还是挺麻烦的,例如不少函数名挺长的。所以自己动手把它的日常使用进行了封装,可以让使用log4cpp就像调用一句printf()函数一样简单快捷。封装目标不需要用一次就调用一次getInstance,只需要在main文件中引入一次即可封装成需要使用时只需简短的一举logError(“s

大家好,又见面了,我是你们的朋友全栈君。

简介

关于log4cpp的介绍与好处就不再赘言了,百度一搜一大把。主要是对于log4cpp的使用如果不封装一下,感觉还是挺麻烦的,例如不少函数名挺长的。所以自己动手把它的日常使用进行了封装,可以让使用log4cpp就像调用一句printf()函数一样简单快捷。

封装目标

  1. 不需要用一次就调用一次getInstance,只需要在main文件中引入一次即可
  2. 封装成需要使用时只需简短的一举logError(“somelog”) 就搞定
  3. 输出的日志内容包含:文件名,函数名,行号(通过以上函数调用即可)
  4. 利用单例模式封装

具体实现

类定义 & 宏定义

巧妙的使用宏定义可以缩短函数调用形式(虽然effective c++ 和google C++编程规范都极力反对使用太多宏)

#ifndef _MYLOG_H
#define _MYLOG_H

#include<log4cpp/Category.hh>
#include<iostream>

//日志优先级
enum Priority {
    ERROR,
    WARN,
    INFO,
    DEBUG
};

//用单例模式封装log4cpp
class Mylog {
 public: 
    static Mylog& getInstance();
    static void destory();

    void setPriority(Priority priority);
    void error(const char* msg);
    void warn(const char* msg);
    void info(const char* msg);
    void debug(const char* msg);

 private:
    Mylog();  //单例模式:构造函数私有化

 private:
    static Mylog *plog_;
    log4cpp::Category &category_ref_;
};

//*****************************************************
//注意:
//文件名 __FILE__ ,函数名 __func__ ,行号__LINE__ 是编译器实现的
//并非C++头文件中定义的 
//前两个变量是string类型,且__LINE__是整形,所以需要转为string类型
//******************************************************

//整数类型文件行号 ->转换为string类型
inline std::string int2string(int line) {
    std::ostringstream oss;
    oss << line;
    return oss.str();
}


//定义一个在日志后添加 文件名 函数名 行号 的宏定义
#define suffix(msg) std::string(msg).append(" ##")\
        .append(__FILE__).append(":").append(__func__)\
        .append(":").append(int2string(__LINE__))\
        .append("##").c_str()


//不用每次使用时写 getInstance语句
//只需要在主函数文件中写: #define _LOG4CPP_即可在整个程序中使用
#ifdef _LOG4CPP_
Mylog &log = Mylog::getInstance();
#else
extern Mylog &log;
#endif

//缩短并简化函数调用形式
#define logError(msg) log.error(suffix(msg))
#define logWarn(msg) log.warn(suffix(msg))
#define logInfo(msg) log.info(suffix(msg))
#define logDebug(msg) log.debug(suffix(msg))

#endif

成员函数的实现:

#include<iostream>
#include "Mylog.h"
#include<log4cpp/PatternLayout.hh>
#include<log4cpp/OstreamAppender.hh>
#include<log4cpp/FileAppender.hh>
#include<log4cpp/Priority.hh>

using namespace std;

Mylog* Mylog::plog_ = NULL;

//获取log指针
Mylog& Mylog::getInstance() {
    if ( plog_ == NULL ) {
        plog_ = new Mylog;
    }
    return *plog_;
}


//销毁
void Mylog::destory() {
    if (plog_) {
        plog_->category_ref_.info("Mylog destroy");
        plog_->category_ref_.shutdown();
        delete plog_;
    }
}


//构造函数
Mylog::Mylog(): 
    category_ref_(log4cpp::Category::getRoot()) {
    //自定义输出格式
    log4cpp::PatternLayout *pattern_one =
        new log4cpp::PatternLayout;
    pattern_one->setConversionPattern("%d: %p %c %x:%m%n");

    log4cpp::PatternLayout *pattern_two =
        new log4cpp::PatternLayout;
    pattern_two->setConversionPattern("%d: %p %c %x:%m%n");

    //获取屏幕输出
    log4cpp::OstreamAppender *os_appender = 
        new log4cpp::OstreamAppender("osAppender",&std::cout);
    os_appender->setLayout(pattern_one);

    //获取文件日志输出 ( 日志文件名:mylog.txt )
    log4cpp::FileAppender *file_appender = 
        new log4cpp::FileAppender("fileAppender","mylog.txt");
    file_appender->setLayout(pattern_two);

    category_ref_.setPriority(log4cpp::Priority::DEBUG);
    category_ref_.addAppender(os_appender);
    category_ref_.addAppender(file_appender);

    category_ref_.info("Mylog created!");
}


//设置优先级
void Mylog::setPriority(Priority priority) {
    switch (priority) {
        case (ERROR):
            category_ref_.setPriority(log4cpp::Priority::ERROR);
            break;

        case (WARN):
            category_ref_.setPriority(log4cpp::Priority::WARN);
            break;

        case (INFO):
            category_ref_.setPriority(log4cpp::Priority::INFO);
            break;

        case (DEBUG):
            category_ref_.setPriority(log4cpp::Priority::DEBUG);
            break;

        default:
            category_ref_.setPriority(log4cpp::Priority::DEBUG);
            break;    
    }
}


void Mylog::error(const char* msg) {
    category_ref_.error(msg);
}

void Mylog::warn(const char* msg) {
    category_ref_.warn(msg);
}

void Mylog::info(const char* msg) {
    category_ref_.info(msg);
}

void Mylog::debug(const char* msg) {
    category_ref_.debug(msg);
}

这样就大致完成了满足前述目标的封装了。
假如程序中有一个func.h的头文件,其实现文件时func.cpp,如下所示:

func.h:


#ifndef _FUNC_H
#define _FUNC_H

void func();

#endif

func.cpp:

/*************************************************************************
 > File Name: func.cpp
 > Author: 
 > Mail: 
 > Created Time: Thu 30 Jul 2015 06:54:49 AM PDT
 ************************************************************************/


#include<iostream>
#include "func.h"
#include"Mylog.h"

using namespace std;

void func() {
 logError("hello allen,func() called");
}


测试程序:

只需要在主函数中加入第一行语句 #define LOG4CPP (注意需要在第一行引入)
而其他头文件或实现文件中都不需要再添加任何语句引入log4cpp,都可以畅通无阻地使用了

#define _LOG4CPP_

#include<iostream>
#include "Mylog.h"
#include "func.h"


using namespace std;

int main(void) {
    //Mylog& log = Mylog::getInstance();
    //log.setPriority(ERROR);
    logError("error allen");
    logWarn("warn allen");

    func();


    return 0;
}

运行结果:

这里写图片描述

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/158415.html原文链接:https://javaforall.net

(0)
上一篇 2022年7月13日 下午4:16
下一篇 2022年7月13日 下午4:36


相关推荐

  • window命令提示符快捷键

    window命令提示符快捷键window 命令提示符快捷键

    2026年3月26日
    23
  • 如何配置pycharm的环境变量

    如何配置pycharm的环境变量如何配置 pycharm 的环境变量第一步 找到 pycharm 的程序文件的地址右键 gt 属性 gt 复制 起始位置 里面的位置第二步 添加到电脑的环境变量我的电脑 gt 右键 gt 属性 gt 高级系统设置 gt 高级 gt 环境变量 gt Administrato gt 找到 Path gt 编辑 gt 新建 gt 粘贴 pycharm 程序文件地址 gt 确定

    2026年3月27日
    2
  • awr报告分析 mysql_生成awr报告

    awr报告分析 mysql_生成awr报告主要参考文档 http blog 163 com blog static 6 概况 Oracle 内部以一定的频率把系统关键的统计信息和负载情况存储起来 生成 snapshot 快照 所有的 snapshot 存储在 awr 中 即 automaticwor 当发现主要参考文档 http 34376

    2026年3月19日
    1
  • oracle中clob类型的使用

    oracle中clob类型的使用oracle 中 clob 类型的使用

    2026年3月19日
    2
  • ImageView ScaleType 解析

    ImageView ScaleType 解析publicstaticenumScaleType{MATRIX,FIT_XY,FIT_START,FIT_CENTER,FIT_END,CENTER,CENTER_CROP,CENTER_INSIDE;private…

    2022年6月21日
    31
  • hive数据类型有哪些?[通俗易懂]

    hive数据类型有哪些?[通俗易懂] 关系数据库里有表(table),分区,hive里也有这些东西,这些东西在hive技术里称为hive的数据模型。今天本文介绍hive的数据类型,数据模型以及文件存储格式。这些知识大家可以类比关系数据库的相关知识。  首先我要讲讲hive的数据类型。Hive支持两种数据类型,一类叫原子数据类型,一类叫复杂数据类型。  原子数据类型包括数值型、布尔型和字符串类型,具体如下表所示:基本数据类型类型…

    2026年2月7日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号