一个简简单单的废物C++11日志输出封装

实现

#pragma once

#ifndef _LOG_CPP_HPP_
#define _LOG_CPP_HPP_

#include <iostream>
#include <string>
#include <deque>
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <fstream>
#ifdef _MSC_VER
#include <ctime>
#include <memory>
#define LOG_FUNCTION __FUNCSIG__
#else
#define LOG_FUNCTION __PRETTY_FUNCTION__
#endif
// 日志输出等级
#ifndef LOG_CPP_LEVEL
#define LOG_CPP_LEVEL 100
#endif

// 默认日志输出等级,全部
#define LOG_CPP_DEBUG 1
#define LOG_CPP_INFO 10
#define LOG_CPP_ERROR 100

/**
* @brief Get the Current Time object
*
* @return std::string
*/
inline std::string getCurrentTime()
{
    
    
#ifndef _MSC_VER
	auto tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
	struct tm *ptm = localtime(&tt);
	char date[60] = {
    
     0 };
	sprintf(date, "%d-%02d-%02d %02d:%02d:%02d",
		(int)ptm->tm_year + 1900, (int)ptm->tm_mon + 1, (int)ptm->tm_mday,
		(int)ptm->tm_hour, (int)ptm->tm_min, (int)ptm->tm_sec);
	return date;
#else
	struct tm newtime;
	char am_pm[] = "AM";
	__time64_t long_time;
	char date[60] = {
    
     0 };
	errno_t err;

	// Get time as 64-bit integer.
	_time64(&long_time);
	// Convert to local time.
	err = _localtime64_s(&newtime, &long_time);
	sprintf_s(date, "%d-%02d-%02d %02d:%02d:%02d",
		(int)newtime.tm_year + 1900, (int)newtime.tm_mon + 1, (int)newtime.tm_mday,
		(int)newtime.tm_hour, (int)newtime.tm_min, (int)newtime.tm_sec);
	return date;
#endif
}

class SpaceFunction
{
    
    
public:
	SpaceFunction &operator<<(const std::string _t) {
    
     return *this; }
	SpaceFunction &operator<<(const int _t) {
    
     return *this; }
};

class LogCpp
{
    
    
private:
	/**
	* @brief 本对象的任务队列
	*
	*/
	std::deque<std::string> m_task;

	/**
	* @brief 写入线程条件变量
	*
	*/
	std::condition_variable m_cond;

	/**
	* @brief 写入线程执行锁
	*
	*/
	std::mutex m_mutex;

	/**
	* @brief 初始化
	*
	*/
	void ini()
	{
    
    
		m_thread = std::make_shared<std::thread>([this]()
		{
    
    
			while (true) {
    
    
				std::unique_lock<std::mutex> lock(m_mutex);
				if (this->m_task.empty() || this->m_logFile == nullptr) {
    
    
					m_cond.wait(lock);
				}
				this->m_logFile->write(m_task.front().c_str(), m_task.front().size());
				m_task.pop_front();
				std::this_thread::yield();
			} });
		m_thread->detach();
	}

public:
	/**
	* @brief 空白函数
	*
	* @param _t 需要忽略的参数
	* @return LogCpp& 自身引用
	*/
	SpaceFunction _spaceFunction;
	/**
	* @brief 日志文件指针
	*
	*/
	std::shared_ptr<std::ofstream> m_logFile = nullptr;
	/**
	* @brief 写文件线程指针
	*
	*/
	std::shared_ptr<std::thread> m_thread = nullptr;

public:
	/**
	* @brief Construct a new LogCpp object
	*
	*/
	LogCpp()
	{
    
    
		ini();
	}

	~LogCpp()
	{
    
    
		getGlobalLogCpp()->m_logFile->close();
	}

	/**
	* @brief Set the Global Path object
	*
	* @param filePath
	*/
	static void setGlobalPath(const std::string &filePath)
	{
    
    
		if (nullptr != getGlobalLogCpp()->m_logFile)
		{
    
    
			getGlobalLogCpp()->m_logFile->close();
			getGlobalLogCpp()->m_logFile = nullptr;
		}
		getGlobalLogCpp()->m_logFile = std::make_shared<std::ofstream>(filePath, std::ios::app);
	}

	/**
	* @brief 输出日志
	*
	* @param log 日志串
	* @return LogCpp 全局对象
	*/
	LogCpp &operator<<(const std::string &log)
	{
    
    
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
    
    
			m_task.emplace_back(log);
		}
		else
		{
    
    
			m_task.back().append(log);
		}
		m_cond.notify_one();
		return *this;
	}
	/**
	* @brief 输出日志
	*
	* @param num 数字
	* @return LogCpp 全局对象
	*/
	LogCpp &operator<<(int num)
	{
    
    
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
    
    
			m_task.emplace_back(std::to_string(num));
		}
		else
		{
    
    
			m_task.back().append(std::to_string(num));
		}
		m_cond.notify_one();
		return *this;
	}

	/**
	* @brief 新的一行
	*
	* @return LogCpp 对象本身
	*/
	LogCpp &addLine()
	{
    
    
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
    
    
			m_task.emplace_back("\n" + getCurrentTime());
		}
		else
		{
    
    
			m_task.back().append("\n" + getCurrentTime());
		}
		m_cond.notify_one();
		return *this;
	}

	/**
	* @brief 错误输出
	*
	* @return LogCpp& 自身引用
	*/
	LogCpp &err()
	{
    
    

#if LOG_CPP_LEVEL >= LOG_CPP_ERROR
#define LogErr (LogCpp::getGlobalLogCpp()->addLine().err() << __FILE__ << ":" << LOG_FUNCTION << ":" << __LINE__ << " ")
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
    
    
			m_task.emplace_back(" [ERROR] ");
		}
		else
		{
    
    
			m_task.back().append(" [ERROR] ");
		}
		m_cond.notify_one();
#else
		// 舍弃流
#define LogErr (LogCpp::getGlobalLogCpp()->_spaceFunction)
#endif // LOG_CPP_LEVEL
		return *this;
	}

	/**
	* @brief 信息输出
	*
	* @return LogCpp& 自身引用
	*/
	LogCpp &info()
	{
    
    

#if LOG_CPP_LEVEL >= LOG_CPP_INFO
#define LogInfo (LogCpp::getGlobalLogCpp()->addLine().info() << __FILE__ << ":" << LOG_FUNCTION << ":" << __LINE__ << " ")
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
    
    
			m_task.emplace_back(" [INFO] ");
		}
		else
		{
    
    
			m_task.back().append(" [INFO] ");
		}
		m_cond.notify_one();
#else
		// 舍弃流
#define LogErr (LogCpp::getGlobalLogCpp()->_spaceFunction)
#endif // LOG_CPP_LEVEL
		return *this;
	}

	/**
	* @brief 调试输出
	*
	* @return LogCpp& 自身引用
	*/
	LogCpp &debug()
	{
    
    
#if LOG_CPP_LEVEL >= LOG_CPP_DEBUG
#define LogDebug (LogCpp::getGlobalLogCpp()->addLine().debug() << __FILE__ << ":" << LOG_FUNCTION << ":" << __LINE__ << " ")
		std::unique_lock<std::mutex> lock(m_mutex);
		if (m_task.empty())
		{
    
    
			m_task.emplace_back(" [DEBUG] ");
		}
		else
		{
    
    
			m_task.back().append(" [DEBUG] ");
		}
		m_cond.notify_one();
#else
		// 舍弃流
#define LogErr (LogCpp::getGlobalLogCpp()->_spaceFunction)
#endif // LOG_CPP_LEVEL
		return *this;
	}

	/**
	* @brief 全局日志对象指针
	*
	*/
	static LogCpp *getGlobalLogCpp()
	{
    
    
		static LogCpp *g_logCpp = new LogCpp();
		return g_logCpp;
	}
};

#endif // !_LOG_CPP_HPP_


示例

#define LOG_CPP_LEVEL 10

#include "./logcpp.hpp"
#include <iostream>
#include <chrono>
#include <string>
#include <sstream>

int main() {
    
    
    LogCpp::setGlobalPath(".\\log.txt");
    while (true) {
    
    
        LogErr << "卧槽卧槽";
        LogInfo << "卧槽卧槽";
        LogDebug << "卧槽卧槽";
    }
    return 0;
}

地址

猜你喜欢

转载自blog.csdn.net/qq_44575789/article/details/122146724