PowerMaster/source/logger.cpp

165 lines
5.0 KiB
C++
Raw Normal View History

2025-12-03 17:09:26 +08:00
#include "logger.h"
#include <QCoreApplication>
#include <QSettings>
#include <QFileInfo>
#include <QDir>
#include <QTextStream>
Logger& Logger::instance()
{
//采用静态局部变量的方式,静态局部变量的初始化是在第一次访问时,以后的调用不会多次初始化,并且生命周期和程序一致
static Logger instance;
return instance;
}
Logger::Logger()
{
initialize();
}
Logger::~Logger()
{
shutdown();
}
void Logger::initialize()
{
//默认配置
m_logFilePath = "";
m_logLevel = INFO;
m_maxFileSize = 1024 *1024 * 10; //10MB
m_maxBackupFiles = 5;
m_outputToConsole = true;
m_outputOtFile = true;
//从配置文件中加载配置
loadConfig();
//创建log文件
QString filePath = QCoreApplication::applicationDirPath() + "/log/app.log";
setLogFile(filePath);
}
void Logger::loadConfig(/*const QString& configFilePath*/)
{
QString settingFile = QCoreApplication::applicationDirPath() + "/config/log_config.ini";
QFile file(settingFile);
if(file.open(QIODevice::ReadWrite))
{
m_settings = new QSettings(settingFile, QSettings::IniFormat);
QString strLevel = m_settings->value("Log/level").toString().toUpper();
if(strLevel == "DEBUG")
m_logLevel = DEBUG;
else if(strLevel == "INFO")
m_logLevel = INFO;
else if(strLevel == "WARNING")
m_logLevel = WARNING;
else if(strLevel == "ERROR")
m_logLevel = ERROR;
else if(strLevel == "FATAL")
m_logLevel = FATAL;
m_maxFileSize = m_settings->value("Log/maxSize").toLongLong();
m_maxBackupFiles = m_settings->value("Log/backups").toInt();
QString strOutputToConsole = m_settings->value("Log/consoleOutput").toString();
if(strOutputToConsole == "true")
m_outputToConsole = true;
else
m_outputToConsole = false;
QString strOutputToFile = m_settings->value("Log/fileOutput").toString();
if(strOutputToFile == "true")
m_outputOtFile = true;
else
m_outputOtFile = false;
}
}
void Logger::setLogFile(const QString& filePath)
{
//检查目录文件所在目录,如果不存在则创建目录
QFileInfo fileInfo(filePath);
QDir logDir = fileInfo.dir();
if(!logDir.exists())
logDir.mkpath(".");
//更新log文件前要先关闭当前已打开的文件
if(m_logFile.isOpen())
m_logFile.close();
m_logFilePath = filePath;
m_logFile.setFileName(filePath);
}
void Logger::shutdown()
{
if(m_logFile.isOpen())
m_logFile.close();
}
void Logger::writeToFile(const QString& message)
{
if(m_logFilePath.isEmpty())
return;
if(!m_logFile.isOpen())
{
if (!m_logFile.open(QIODevice::Append | QIODevice::Text))
{
qWarning() << "Failed to open log file:" << m_logFile.errorString();
return;
}
//打开文件时先键入一个换行符
QTextStream stream(&m_logFile);
stream.setEncoding(QStringConverter::Utf8);//强制UTF-8编码
stream << Qt::endl;
stream.flush(); //刷新输出缓冲区,确保数据立即写入文件
}
QTextStream stream(&m_logFile);
stream << message << Qt::endl;
stream.flush(); //刷新输出缓冲区,确保数据立即写入文件
if(m_logFile.size() > m_maxFileSize)
rollLogFiles();
}
void Logger::rollLogFiles()
{
if(m_logFile.isOpen())
m_logFile.close();
//删除最旧的备份文件(备份文件以‘日志文件.数字’的格式命名,数字越大表示文件越旧)
QFile::remove(QString("%1.%2").arg(m_logFilePath).arg(m_maxBackupFiles));
//剩余文件依次更改名称
for(int i = m_maxBackupFiles - 1; i > 0; i--)
QFile::rename(QString("%1.%2").arg(m_logFilePath).arg(i), QString("%1.%2").arg(m_logFilePath).arg(i + 1));
//将当前日志文件更改为'最新'的备份文件(编号为1)
QFile::rename(m_logFilePath, QString("%1.1").arg(m_logFilePath));
//更新当前配置文件(重新打开)
m_logFile.setFileName(m_logFilePath);
if (!m_logFile.open(QIODevice::Append | QIODevice::Text))
qWarning() << "Failed to open new log file after rolling:" << m_logFile.errorString();
}
QString Logger::formatLogMessage(LogLevel level, const QString& context, const QString& message)
{
static const char* levelStrings[] = {"FATAL", "ERROR", "WARNING", "INFO", "DEBUG"};
return QString("[%1] [%2] [%3] %4")
.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss")
,levelStrings[level]
,context
,message);
}
void Logger::log(LogLevel level, const QString& context, const QString& message)
{
if(level > m_logLevel)
return;
QString formatMessage = formatLogMessage(level, context, message);
if(m_outputToConsole)
QTextStream(stderr) << formatMessage << Qt::endl;
if(m_outputOtFile)
writeToFile(formatMessage);
}