C++日志调试打印接口

1、debug_log.h头文件

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : debug_log.h
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年2月28日
    功能描述 : 日志类头文件
    修改历史 :
******************************************************************************/
#ifdef __cplusplus
#include <string>
#endif

#ifndef _DEBUG_LOG_H_
#define _DEBUG_LOG_H_

#ifdef __cplusplus

namespace debug_log {

class DebugLog {
public:
	DebugLog() :
		m_debugLevel(-1),
		m_fileName("") { }

	virtual ~DebugLog();

	virtual void write(int level, const std::string &msg);
	bool isLogFileSet();
	bool isLogLevelSet();
	void setDebugLogLevel(int level);
	void setDebugLogFile(std::string fileName, std::string *error);
	const std::string& getDebugLogFile();
	int getDebugLogLevel();

private:
	/* 日志级别 */
	int m_debugLevel;

	/* 日志文件 */
	std::string m_fileName;
};

}  // namespace debug_log

#endif  // __cplusplus

#endif  // _DEBUG_LOG_H_


2、debug_log.cpp接口实现

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : debug_log.cpp
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年2月28日
    功能描述 : 日志类接口实现
    修改历史 :
******************************************************************************/
#include <stddef.h>
#include <fstream>

#include "debug_log.h"
#include "debug_log_writer.h"

namespace debug_log {

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.~DebugLog
    功能描述 : 析构函数
    输入参数 : 无
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
DebugLog::~DebugLog() {
	DebugLogWriter::getInstance().close(this->m_fileName);
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.setDebugLogFile
    功能描述 : 设置日志文件
    输入参数 : std::string fileName  
               std::string *error     
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
void DebugLog::setDebugLogFile(std::string fileName, std::string *error) {
	if (this->isLogFileSet()) {
		DebugLogWriter::getInstance().close(this->m_fileName);
	}

	this->m_fileName = fileName;

	DebugLogWriter::getInstance().open(this->m_fileName, error);
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.setDebugLogLevel
    功能描述 : 设置日志级别
    输入参数 : int level  
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
void DebugLog::setDebugLogLevel(int level) {
	this->m_debugLevel = level;
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.isLogFileSet
    功能描述 : 是否设置日志文件
    输入参数 : 无
    输出参数 : 无
    返 回 值 : bool
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
bool DebugLog::isLogFileSet() {
	return (this->m_fileName.empty() == false);
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.isLogLevelSet
    功能描述 : 是否设置日志级别
    输入参数 : 无
    输出参数 : 无
    返 回 值 : bool
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
bool DebugLog::isLogLevelSet() {
	return (this->m_debugLevel != -1);
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.getDebugLogFile
    功能描述 : 获取日志文件
    输入参数 : 无
    输出参数 : 无
    返 回 值 : const std::string&
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
const std::string& DebugLog::getDebugLogFile() {
	return this->m_fileName;
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.getDebugLogLevel
    功能描述 : 获取日志级别
    输入参数 : 无
    输出参数 : 无
    返 回 值 : int
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
int DebugLog::getDebugLogLevel() {
	return (this->m_debugLevel < 0) ? 0 : this->m_debugLevel;
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLog.write
    功能描述 : 写日志
    输入参数 : int level          
               const std::string &msg  
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
void DebugLog::write(int level, const std::string &msg) {
	if (level <= this->m_debugLevel) {
		std::string msgf = "[" + std::to_string(level) + "]" + msg;
		DebugLogWriter &d = DebugLogWriter::getInstance();
		d.write_log(this->m_fileName, msgf);
	}
}

}  // namespace debug_log

3、debug_log_writer.h头文件

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : debug_log_writer.h
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年2月28日
    功能描述 : 写日志类头文件
    修改历史 :
******************************************************************************/
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

#include <map>
#include <string>
#include <cstring>
#include <iostream>

#ifndef _DEBUG_LOG_WRITER_H_
#define _DEBUG_LOG_WRITER_H_

namespace debug_log {

class DebugLogWriter {
public:
	static DebugLogWriter &getInstance() {
		static DebugLogWriter instance;
		return instance;
	}

	void write_log(const std::string &fileName, const std::string &msg);
	void close(const std::string &fileName);
	int open(const std::string &fileName, std::string *error);

private:
	DebugLogWriter() { }
	~DebugLogWriter() { }

    // C++ 03
    // ========
    // Dont forget to declare these two. You want to make sure they
    // are unacceptable otherwise you may accidentally get copies of
    // your singleton appearing.
	DebugLogWriter(DebugLogWriter const&);
	void operator=(DebugLogWriter const&);
};

}  // namespace debug_log

#endif  // _DEBUG_LOG_WRITER_H_

4、debug_log_writer.cpp接口实现

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : debug_log_writer.cpp
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年2月28日
    功能描述 : 写日志文件类接口实现
    修改历史 :
******************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <fstream>

#include "shared_files.h"
#include "debug_log_writer.h"

namespace debug_log {

/*****************************************************************************
    函 数 名 : debug_log.DebugLogWriter.open
    功能描述 : 打开文件
    输入参数 : const std::string &fileName  
               std::string *error           
    输出参数 : 无
    返 回 值 : int
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
int DebugLogWriter::open(const std::string &fileName, std::string *error) {
	return utils::SharedFiles::getInstance().open(fileName, error);
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLogWriter.close
    功能描述 : 关闭文件句柄
    输入参数 : const std::string &fileName  
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
void DebugLogWriter::close(const std::string &fileName) {
	utils::SharedFiles::getInstance().close(fileName);
}

/*****************************************************************************
    函 数 名 : debug_log.DebugLogWriter.write_log
    功能描述 : 写日志文件
    输入参数 : const std::string &fileName  
               const std::string &msg   
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年2月28日
*****************************************************************************/
void DebugLogWriter::write_log(const std::string &fileName,
	const std::string &msg) {
	std::string err;
	std::string lmsg = msg + "\n";
	utils::SharedFiles::getInstance().write(fileName, lmsg, &err);
	if (err.size() > 0) {
		printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, err.c_str());
	}
}

}  // namespace debug_log

5、shared_files.h头文件

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : shared_files.h
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年5月8日
    功能描述 : 共享文件操作类头文件
    修改历史 :
******************************************************************************/
#ifndef _UTILS_SHARED_FILES_H_
#define _UTILS_SHARED_FILES_H_

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <utility>
#include <vector>
#include <fstream>
#include <string>

namespace utils {

typedef struct file_handler {
    int shm_id_structure;
    pthread_mutex_t lock;
    char file_name[];
} file_handler_t;

class SharedFiles {
public:
	bool open(const std::string &fileName, std::string *error);
	void close(const std::string &fileName);
	bool write(const std::string &fileName, const std::string &msg,
        std::string *error);

    static SharedFiles& getInstance() {
    	static SharedFiles instance;
    	return instance;
    }

protected:
	std::pair<file_handler_t *, FILE *> find_handler(
		const std::string &fileName);
	std::pair<file_handler_t *, FILE *> add_new_handler(
		const std::string &fileName, std::string *error);

private:
	 SharedFiles() {}
	~SharedFiles() {}

    // C++ 03
    // ========
    // Dont forget to declare these two. You want to make sure they
    // are unacceptable otherwise you may accidentally get copies of
    // your singleton appearing.
    SharedFiles(SharedFiles const&);
    void operator=(SharedFiles const&);

	std::vector<std::pair<std::string,
		std::pair<file_handler_t *, FILE *> > > m_handlers;
};

}  // namespace utils

#endif  // _UTILS_SHARED_FILES_H_

6、shared_files.cpp接口实现

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : shared_files.cpp
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年5月8日
    功能描述 : 共享文件操作接口实现
    修改历史 :
******************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
	
#include <utility>
#include <fstream>
#include <string>

#include "shared_files.h"

namespace utils {

/*****************************************************************************
    函 数 名 : utils.SharedFiles.find_handler
    功能描述 : 查找文件句柄
    输入参数 : const std::string &fileName  
    输出参数 : 无
    返 回 值 : std::pair<file_handler_t *, FILE *>
    作    者 : zhangcan
    日    期 : 2017年5月8日
*****************************************************************************/
std::pair<file_handler_t *, FILE *> SharedFiles::find_handler(
	const std::string &fileName) {
	for (auto i : this->m_handlers) {
		if (i.first == fileName) {
			return i.second;
		}
	}

	return std::pair<file_handler_t *, FILE *>(NULL, NULL);
}

/*****************************************************************************
    函 数 名 : utils.SharedFiles.add_new_handler
    功能描述 : 添加文件句柄
    输入参数 : const std::string &fileName  
               std::string *error           
    输出参数 : 无
    返 回 值 : std::pair<file_handler_t *, FILE *>
    作    者 : zhangcan
    日    期 : 2017年5月8日
*****************************************************************************/
std::pair<file_handler_t *, FILE *> SharedFiles::add_new_handler(
	const std::string &fileName, std::string *error) {
	int ret;
	FILE *fp;
	int shm_id;
	bool toBeCreated = true;
	key_t mem_key_structure;
	file_handler_t *new_debug_log;
	struct shmid_ds shared_mem_info;

	/* 打开文件 */
	fp = fopen(fileName.c_str(), "a");
	if (fp == NULL) {
		error->assign("Failed to open file: " + fileName);
		goto err_fh;
	}

	/* 创建IPC通讯ID */
	mem_key_structure = ftok(fileName.c_str(), 1);
	if (mem_key_structure < 0) {
		error->assign("Failed to select key for the shared memory (1): ");
        error->append(strerror(errno));
        goto err_mem_key;
	}

	/* 创建共享内存对象 */
	shm_id = shmget(mem_key_structure, sizeof(file_handler_t) + fileName.size() + 1, \
		IPC_CREAT | IPC_EXCL | 0666);
	if (shm_id < 0) {
		toBeCreated = false;
		shm_id = shmget(mem_key_structure, sizeof(file_handler_t) + fileName.size() + 1, \
			IPC_CREAT | 0666);
		if (shm_id < 0) {
			error->assign("Failed to allocate shared memory (1): ");
            error->append(strerror(errno));
            goto err_shmget1;
		}
	}

	/* 获得共享内存的状态 */
	ret = shmctl(shm_id, IPC_STAT, &shared_mem_info);
	if (ret < 0) {
		error->assign("Failed to get information on shared memory (1): ");
        error->append(strerror(errno));
        goto err_shmctl1;
	}

	/* 把共享内存区对象映射到调用进程的地址空间 */
	new_debug_log = reinterpret_cast<file_handler_t *>(shmat(shm_id, NULL, 0));
	if ((reinterpret_cast<char *>(new_debug_log)[0]) == -1) {
		error->assign("Failed to attach shared memory (1): ");
        error->append(strerror(errno));
        goto err_shmat1;
	}

	if ((toBeCreated == false) && (shared_mem_info.shm_nattch == 0)) {
		toBeCreated = true;
	}

	if (toBeCreated == true) {
		memset(new_debug_log, '\0', sizeof(file_handler_t));
		pthread_mutex_init(&new_debug_log->lock, NULL);
		new_debug_log->shm_id_structure = shm_id;
		memcpy(new_debug_log->file_name, fileName.c_str(), fileName.size());
		new_debug_log->file_name[fileName.size()] = '\0';
	}

	this->m_handlers.push_back(std::make_pair(fileName, std::make_pair(new_debug_log, fp)));

	return std::make_pair(new_debug_log, fp);

err_shmget1:
err_shmctl1:
err_shmat1:
	shmdt(new_debug_log);

err_mem_key:
	fclose(fp);

err_fh:
	return std::pair<file_handler_t *, FILE *>(NULL, NULL);
}

/*****************************************************************************
    函 数 名 : utils.SharedFiles.open
    功能描述 : 打开文件
    输入参数 : const std::string &fileName  
               std::string *error           
    输出参数 : 无
    返 回 值 : bool
    作    者 : zhangcan
    日    期 : 2017年5月8日
*****************************************************************************/
bool SharedFiles::open(const std::string &fileName, std::string *error) {
	bool bRet = true;
	std::pair<file_handler_t *, FILE *> a;

	/* 查找文件句柄 */
	a = this->find_handler(fileName);
	if (a.first == NULL) {
		/* 创建文件句柄 */
		a = this->add_new_handler(fileName, error);
	}

	if ((a.first == NULL) && (error->size() == 0)) {
		error->assign("Not able to open: " + fileName);
		bRet = false;
	}

	return bRet;
}

/*****************************************************************************
    函 数 名 : utils.SharedFiles.close
    功能描述 : 关闭文件
    输入参数 : const std::string &fileName  
    输出参数 : 无
    返 回 值 : 无
    作    者 : zhangcan
    日    期 : 2017年5月8日
*****************************************************************************/
void SharedFiles::close(const std::string &fileName) {
	std::pair<file_handler_t *, FILE *> a;

	if (fileName.empty()) {
		return;
	}

	a = this->find_handler(fileName);
	if ((a.first == NULL) || (a.second == NULL)) {
		return;
	}

	/* 关闭文件 */
	fclose(a.second);
	a.second = NULL;

	/* 删除共享内存 */
	shmctl(a.first->shm_id_structure, IPC_RMID, NULL);
}

/*****************************************************************************
    函 数 名 : utils.SharedFiles.write
    功能描述 : 写数据
    输入参数 : const std::string &fileName  
               const std::string &msg       
               std::string *error           
    输出参数 : 无
    返 回 值 : bool
    作    者 : zhangcan
    日    期 : 2017年5月8日
*****************************************************************************/
bool SharedFiles::write(const std::string &fileName,
	const std::string &msg, std::string *error) {
	bool ret = true;
	size_t wrote;
	std::pair<file_handler_t *, FILE *> a;

	a = this->find_handler(fileName);
	if (a.first == NULL) {
		error->assign("file is not open: " + fileName);
        return false;
	}

	pthread_mutex_lock(&a.first->lock);
    wrote = fwrite(reinterpret_cast<const char *>(msg.c_str()), 1, msg.size(), a.second);
    if (wrote < msg.size()) {
        error->assign("failed to write: " + fileName);
        ret = false;
    }
    fflush(a.second);
    pthread_mutex_unlock(&a.first->lock);

    return ret;
}

}  // namespace utils

7、编译以上代码生成动态库

CC     := g++ --std=c++11
TARGET := libDebugLog.so
INCS   := ./debug_log ./utils ../include
FLAGES := $(addprefix -I, $(INCS))

SRCS   := $(wildcard ./debug_log/*.cpp)
SRCS   += $(wildcard ./utils/*.cpp)

$(TARGET): $(SRCS)
	$(CC) -shared -fPIC $(FLAGES) -o $@ $^
	@mv $(TARGET) ./libs/

.PHONY: clean
clean:
	@rm -rf ./debug_log/*.o ./utils/*.o
	@rm -rf ./libs/$(TARGET)

8、测试代码

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : test_debug_log.h
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年5月12日
    功能描述 : 测试DebugLog类头文件
    修改历史 :
******************************************************************************/
#ifdef __cplusplus
#include <stdio.h>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#endif

#ifndef _TEST_DEBUG_LOG_H_
#define _TEST_DEBUG_LOG_H_

#include "debug_log.h"

#ifdef __cplusplus

using debug_log::DebugLog;

class Test_1 {
public:
	Test_1() :
		m_debugLog(new DebugLog())
	{}

	~Test_1(){
		if (m_debugLog != NULL) {
			delete m_debugLog;
		}
	}

	void init(int level, std::string fileName);

	void debug(int level, const std::string &msg);

	void test();

private:
	DebugLog *m_debugLog;
};

#endif  // __cplusplus

#endif  // _TEST_DEBUG_LOG_H_

/******************************************************************************

            版权所有 (C), 2016-2017, 西安网络科技有限公司

 ******************************************************************************
    文 件 名 : test_debug_log.cpp
    版 本 号 : V1.0
    作    者 : zhangcan
    生成日期 : 2017年5月11日
    功能描述 : 测试DebugLog功能
    修改历史 :
******************************************************************************/
#include "test_debug_log.h"

void Test_1::init(int level, std::string fileName) {
	if (m_debugLog != NULL) {
		std::string msg;

		m_debugLog->setDebugLogLevel(level);
		m_debugLog->setDebugLogFile(fileName, &msg);
		if (msg.size() > 0) {
			std::cout << msg << std::endl;
		}
	}
	else {
		std::cout << "new DebugLog failed!" << std::endl;
	}
}

void Test_1::debug(int level, const std::string &msg) {
	if (m_debugLog != NULL) {
		m_debugLog->write(level, msg);
	}
}

void Test_1::test() {
	std::string msg;
	std::stringstream head;

	head << "[" << __FUNCTION__ << ":" << __LINE__ << "] ";

	msg = "123456789";
	msg = head.str() + msg;

	debug(1, msg);
}

int main() {
	Test_1 *pTest = new Test_1();
	if (pTest != NULL) {
		pTest->init(9, "debug.log");
	}
	else
	{
		std::cout << "new Test_1 failed!" << std::endl;
		return -1;	
	}

	pTest->test();

	return 0;
}

编译代码

CC     := g++ --std=c++11
INCS   := ./ ../utils ../../include
LIBS   := DebugLog
FLAGES := $(addprefix -I, $(INCS))
FLAGES += -L../libs/ -Wl,-rpath ../libs/ $(addprefix -l, $(LIBS))

out :
	$(CC) -o test_debug_log test_debug_log.cpp $(FLAGES)

.PHONY:clean
clean:
	@rm -rf test_debug_log

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值