自己动手写一个C++日志库
logger.h
//
// Created by Fkkt on 2023/9/8.
//
#pragma once
#include <string>
#include <iostream>
#include <fstream>
#include <chrono>
#include <sstream>
namespace fkkt {
class logger {
public:
enum log_level {
D, // Debug
I, // Info
W, // Warning
E // Error
};
/**
* Construct logger
*
* @param log_file_name log file name
* @param default_console_log_level log level, see log_level
* @param mode mode, default is append
*/
explicit logger(const std::string &log_file_name = "app.log",
log_level default_console_log_level = D,
const std::ios_base::openmode &mode = std::ios_base::app);
~logger();
/**
* Set level of console, which will be print
*
* @param level log level, see log_level
*/
void set_console_log_level(log_level level);
template<typename... Args>
void d(Args... args) {
std::ostringstream oss;
append(oss, args...);
write(D, oss.str());
}
template<typename... Args>
void i(Args... args) {
std::ostringstream oss;
append(oss, args...);
write(D, oss.str());
}
template<typename... Args>
void w(Args... args) {
std::ostringstream oss;
append(oss, args...);
write(D, oss.str());
}
template<typename... Args>
void e(Args... args) {
std::ostringstream oss;
append(oss, args...);
write(D, oss.str());
}
private:
std::ofstream log_file;
log_level console_log_level;
static std::string get_log_level(log_level level);
static std::string get_current_time_stamp();
void write(log_level level, const std::string &message);
void append(std::ostringstream &oss) {}
template<typename T, typename... Args>
void append(std::ostringstream &oss, const T &first, Args... args) {
oss << first;
append(oss, args...);
}
};
}
logger.cpp
//
// Created by Fkkt on 2023/9/8.
//
#include "logger.h"
#include <iostream>
#include <ctime>
#include <iomanip>
#include <fstream>
#include <mutex>
namespace fkkt {
logger::logger(const std::string &log_file_name,
log_level default_console_log_level,
const std::ios_base::openmode &mode) : console_log_level(default_console_log_level) {
log_file.open(log_file_name, mode);
if (!log_file.is_open()) {
throw std::runtime_error("Failed to open log file: " + log_file_name);
}
std::ios::sync_with_stdio(false);
set_console_log_level(W);
}
logger::~logger() {
if (log_file.is_open()) {
log_file.close();
}
std::ios::sync_with_stdio(true);
}
void logger::set_console_log_level(log_level level) {
console_log_level = level;
}
std::string logger::get_log_level(log_level level) {
switch (level) {
case D:
return "DEBUG";
case I:
return "INFO";
case W:
return "WARNING";
case E:
return "ERROR";
default:
return "UNKNOWN";
}
}
std::string logger::get_current_time_stamp() {
auto currentTime = std::chrono::system_clock::now();
auto currentTimeT = std::chrono::system_clock::to_time_t(currentTime);
auto timeInfo = *std::localtime(¤tTimeT);
std::stringstream ss;
ss << std::put_time(&timeInfo, "%Y-%m-%d %H:%M:%S");
return ss.str();
}
void logger::write(log_level level, const std::string &message) {
std::lock_guard<std::mutex> lock(std::mutex);
std::string logMessage = get_current_time_stamp() + " [" + get_log_level(level) + "] " + message + "\n";
if (level >= console_log_level) {
std::cout << logMessage;
}
if (log_file.is_open()) {
log_file << logMessage;
}
}
}
使用方法
#include "logger.h"
int main() {
auto log = make_unique<fkkt::logger>("app.log", fkkt::logger::log_level::D, ios::in);
log->set_console_log_level(fkkt::logger::D);
log->d("Hello ", 10924);
return 0;
}
标签:std,console,log,level,oss,C++,动手,日志,logger
From: https://www.cnblogs.com/imorning/p/cpp_log_utils.html