实现
#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
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;
_time64(&long_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:
std::deque<std::string> m_task;
std::condition_variable m_cond;
std::mutex m_mutex;
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:
SpaceFunction _spaceFunction;
std::shared_ptr<std::ofstream> m_logFile = nullptr;
std::shared_ptr<std::thread> m_thread = nullptr;
public:
LogCpp()
{
ini();
}
~LogCpp()
{
getGlobalLogCpp()->m_logFile->close();
}
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);
}
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;
}
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;
}
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;
}
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
return *this;
}
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
return *this;
}
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
return *this;
}
static LogCpp *getGlobalLogCpp()
{
static LogCpp *g_logCpp = new LogCpp();
return g_logCpp;
}
};
#endif
示例
#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;
}
地址
|