logger.h
/**
* logger.h
* @brief 简易日志模块
*/
#ifndef __LOGGER_H__
#define __LOGGER_H__
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cstdlib>
#include <stdint.h>
typedef enum log_rank{
INFO = 0,
WARNING,
ERROR,
FATAL,
} log_rank_t;
void initLogger(const std::string &info_filename, const std::string &warn_filename,
const std::string &error_filename);
class Logger{
friend void initLogger(const std::string &info_filename, const std::string &warn_filename,
const std::string &error_filename);
public:
Logger(log_rank_t log_rank):m_log_rank(log_rank){};
~Logger();
static std::ostream &start(log_rank_t log_rank, const int line, const std::string &fun);
private:
static std::ostream &getStream(log_rank_t log_rank);
static std::ofstream m_info_file;
static std::ofstream m_warn_file;
static std::ofstream m_error_file;
log_rank_t m_log_rank;
};
#define LOG(log_rank) \
Logger(log_rank).start(log_rank, __LINE__, __FUNCTION__)
#endif
logger.cpp
#include <cstdlib>
#include <ctime>
#include "logger.h"
std::ofstream Logger::m_info_file;
std::ofstream Logger::m_warn_file;
std::ofstream Logger::m_error_file;
void initLogger(const std::string &info_filename, const std::string &warn_filename,
const std::string &error_filename){
Logger::m_info_file.open(info_filename.c_str(), std::ofstream::app);
Logger::m_warn_file.open(warn_filename.c_str(), std::ofstream::app);
Logger::m_error_file.open(error_filename.c_str(), std::ofstream::app);
}
std::ostream &Logger::getStream(log_rank_t log_rank){
if(log_rank == INFO){
return m_info_file.is_open() ? m_info_file : std::cout;
}
if(log_rank == WARNING){
return m_warn_file.is_open() ? m_warn_file : std::cout;
}
if(log_rank == ERROR){
return m_error_file.is_open() ? m_error_file : std::cout;
}
}
std::ostream &Logger::start(log_rank_t log_rank, const int line, const std::string &fun){
time_t tm;
time(&tm);
char time_string[128];
strftime(time_string, sizeof(time_string),"[%Y.%m.%d %X] ", localtime(&tm));
return getStream(log_rank) << time_string
<< "function[" << fun <<"] "
<< "line[" << line <<"] "
<< std::flush;
}
Logger::~Logger(){
getStream(m_log_rank) << std::endl << std::flush;
if(m_log_rank == FATAL){
m_info_file.close();
m_warn_file.close();
m_error_file.close();
abort();
}
}
测试文件
#include <iostream>
#include "logger.h"
int main(){
initLogger("log/info.log", "log/warning.log", "log/error.log");
LOG(INFO) << "info " << "test";
LOG(INFO) << "info " << "test";
LOG(WARNING) << "warning " << "test";
LOG(WARNING) << "warning " << "test";
LOG(ERROR) << "error " << "test";
LOG(ERROR) << "error " << "test";
}
C语言实现日志封装
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
void logC(const char *func, const char *file, const int line,
const char *type, const char *format, ...)
{
FILE *file_fp;
time_t loacl_time;
char time_str[128];
// 获取本地时间
time(&loacl_time);
strftime(time_str, sizeof(time_str), "[%Y.%m.%d %X]", localtime(&loacl_time));
// 日志内容格式转换
va_list ap;
va_start(ap, format);
char fmt_str[2048];
vsnprintf(fmt_str, sizeof(fmt_str), format, ap);
va_end(ap);
// 打开日志文件
file_fp = fopen("./main.log", "a");
// 写入到日志文件中
if (file_fp != NULL)
{
fprintf(file_fp, "[%s]%s[%s@%s:%d] %s\n", type, time_str, func,
file, line, fmt_str);
fclose(file_fp);
}
else
{
fprintf(stderr, "[%s]%s[%s@%s:%d] %s\n", type, time_str, func,
file, line, fmt_str);
}
}
#define LOGC(type, format, ...) logC(__func__, __FILE__, __LINE__, type, format, ##__VA_ARGS__)
int main()
{
LOGC("LOG_DEBUG", "a=%d", 10);
return 0;
}