#include <iostream>
#include <fstream>
#include <string>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <queue>
#include <chrono>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <string>
#pragma warning(disable : 4996)
enum class LogLevel {
Debug = 0,
Info = 1,
Warn = 2,
Error = 3,
Critical = 4
};
class Logger {
public:
Logger() : m_stop(false), m_worker(&Logger::worker, this) {
}
~Logger() {
stop();
m_worker.join();
}
void log(LogLevel level, const std::string& message) {
std::unique_lock<std::mutex> lock(m_mutex);
m_queue.emplace(level, message);
m_condition.notify_one();
}
void stop() {
std::unique_lock<std::mutex> lock(m_mutex);
m_stop = true;
m_condition.notify_one();
}
private:
void worker() {
while (true) {
LogLevel level;
std::string message;
{
std::unique_lock<std::mutex> lock(m_mutex);
m_condition.wait(lock, [this] { return m_stop || !m_queue.empty(); });
if (m_stop && m_queue.empty()) {
break;
}
level = m_queue.front().first;
message = m_queue.front().second;
m_queue.pop();
}
std::ofstream out("log.txt", std::ios_base::app);
if (!out.good()) {
return;
}
std::string log = GetTimeWithMilliseconds() + " " + message;
out << log << std::endl;
out.close();
}
}
std::string GetTimeWithMilliseconds() {
auto now = std::chrono::system_clock::now();
auto now_c = std::chrono::system_clock::to_time_t(now);
auto millisec = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 1000;
std::stringstream ss;
ss << std::put_time(std::localtime(&now_c), "%Y-%m-%d %H:%M:%S") << ' ' << std::setfill('0') << std::setw(3) << millisec.count();
return ss.str();
}
private:
std::mutex m_mutex;
std::condition_variable m_condition;
std::queue<std::pair<LogLevel, std::string>> m_queue;
std::thread m_worker;
bool m_stop;
};
Logger logger; // 单例
void foo1() {
for (int i = 0; i < 2000; i++) {
logger.log(LogLevel::Debug, "foo1:"+std::to_string(i));
logger.log(LogLevel::Debug, "foo1 This is a debug message.");
logger.log(LogLevel::Info, "foo1 This is an info message.");
logger.log(LogLevel::Warn, "foo1 This is a warn message.");
logger.log(LogLevel::Error, "foo1 This is an error message.");
logger.log(LogLevel::Critical, "foo1 This is a critical message.");
}
}
void foo2() {
for (int i = 0; i < 1000; i++) {
logger.log(LogLevel::Debug, "foo2:" + std::to_string(i));
logger.log(LogLevel::Debug, "foo2 This is a debug message.");
logger.log(LogLevel::Info, "foo2 This is an info message.");
logger.log(LogLevel::Warn, "foo2 This is a warn message.");
logger.log(LogLevel::Error, "foo2 This is an error message.");
logger.log(LogLevel::Critical, "foo2 This is a critical message.");
}
}
int main() {
std::thread t1(foo1);
std::thread t2(foo2);
t1.join();
t2.join();
return 0;
}
分享一个C++日志类:支持多线程,异步输出到本地的日志
最新推荐文章于 2024-04-03 08:17:25 发布