feat:添加log模块

This commit is contained in:
duanshengchao 2025-12-03 17:09:26 +08:00
parent f3f08af3f9
commit 001c4459f0
6 changed files with 257 additions and 4 deletions

View File

@ -56,6 +56,7 @@ set(H_HEADER_FILES
include/alarmEventUtils.h include/alarmEventUtils.h
include/alarmEventDataService.h include/alarmEventDataService.h
include/alarmEventConfigDialog.h include/alarmEventConfigDialog.h
include/logger.h
) )
set(CPP_SOURCE_FILES set(CPP_SOURCE_FILES
@ -93,6 +94,7 @@ set(CPP_SOURCE_FILES
source/alarmEventUtils.cpp source/alarmEventUtils.cpp
source/alarmEventDataService.cpp source/alarmEventDataService.cpp
source/alarmEventConfigDialog.cpp source/alarmEventConfigDialog.cpp
source/logger.cpp
) )
set(UI_FILES set(UI_FILES
@ -219,6 +221,7 @@ install(TARGETS PowerMaster
set(CONFIG_FILES set(CONFIG_FILES
alarmEventService_config.ini alarmEventService_config.ini
realTimeDataService_config.ini realTimeDataService_config.ini
log_config.ini
) )
set(CONFIG_FILE_DIR "${CMAKE_BINARY_DIR}/config") set(CONFIG_FILE_DIR "${CMAKE_BINARY_DIR}/config")
# #

71
include/logger.h Normal file
View File

@ -0,0 +1,71 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <QObject>
#include <QFile>
#include <QDateTime>
// 日志宏定义
#define LOG(level, module, message) Logger::instance().log(Logger::level, module, message)
#define LOG_DEBUG(module, message) LOG(DEBUG, module, message)
#define LOG_INFO(module, message) LOG(INFO, module, message)
#define LOG_WARN(module, message) LOG(WARNING, module, message)
#define LOG_ERROR(module, message) LOG(ERROR, module, message)
#define LOG_FATAL(module, message) LOG(FATAL, module, message)
class QSettings;
class Logger : public QObject
{
Q_OBJECT
public:
enum LogLevel
{
FATAL = 0,
ERROR,
WARNING,
INFO,
DEBUG
};
//获取单例实例
static Logger& instance();
void log(LogLevel, const QString&, const QString&);
private:
explicit Logger();
~Logger();
//禁止拷贝
Logger(const Logger&) = delete; //delete关键字表示该函数不可用包括编译器自动生成的函数
Logger& operator=(const Logger&) = delete;
void initialize();
void loadConfig(/*const QString&*/); //本系统是通过Settings类进行配置文件信息读取
void setLogFile(const QString&);
void shutdown();
void writeToFile(const QString&);
void rollLogFiles(); //当文件大小超过设置上线时会触发'滚动'
QString formatLogMessage(LogLevel, const QString&, const QString&);
struct LogEntry
{
QDateTime time;
LogLevel level;
QString module;
QString message;
Qt::HANDLE threadId;
};
//配置参数
QSettings* m_settings;
LogLevel m_logLevel;
QString m_logFilePath;
QFile m_logFile;
qint64 m_maxFileSize;
int m_maxBackupFiles;
bool m_outputToConsole;
bool m_outputOtFile;
};
#endif //LOGGER_H

6
log_config.ini Normal file
View File

@ -0,0 +1,6 @@
[Log]
level=DEBUG
maxSize=10485760
backups=5
consoleOutput=false
fileOutput=true

View File

@ -1,4 +1,5 @@
#include "alarmEventDataService.h" #include "alarmEventDataService.h"
#include "logger.h"
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QUrlQuery> #include <QUrlQuery>
@ -296,28 +297,31 @@ void AlarmEventDataService::onRabbitMQConnected()
void AlarmEventDataService::onRabbitMQDisconnected() void AlarmEventDataService::onRabbitMQDisconnected()
{ {
qWarning() << "Disconnected to RabbitMQ"; //qWarning() << "Disconnected to RabbitMQ";
LOG_WARN("RabbitMQ", "Disconnected to RabbitMQ");
m_serviceStatus = ServiceStatus::Disconnected; m_serviceStatus = ServiceStatus::Disconnected;
scheduleReconnect(); scheduleReconnect();
} }
void AlarmEventDataService::onRabbitMQError(QAMQP::Error error) void AlarmEventDataService::onRabbitMQError(QAMQP::Error error)
{ {
qWarning() << m_amqpClient->errorString(); //qWarning() << m_amqpClient->errorString();
LOG_WARN("RabbitMQ", m_amqpClient->errorString());
m_serviceStatus = ServiceStatus::Error; m_serviceStatus = ServiceStatus::Error;
scheduleReconnect(); scheduleReconnect();
} }
void AlarmEventDataService::onRabbitMQSocketError(QAbstractSocket::SocketError error) void AlarmEventDataService::onRabbitMQSocketError(QAbstractSocket::SocketError error)
{ {
qWarning() << "RabbitMQ connection socket error: " << error; //qWarning() << "RabbitMQ connection socket error: " << error;
LOG_WARN("RabbitMQ", QString("RabbitMQ connection socket error: %1").arg(error));
m_serviceStatus = ServiceStatus::Error; m_serviceStatus = ServiceStatus::Error;
scheduleReconnect(); scheduleReconnect();
} }
void AlarmEventDataService::onAmqpQueueOpend() void AlarmEventDataService::onAmqpQueueOpend()
{ {
//qInfo() << "AmqpQueue opend"; LOG_INFO("RabbitMQ", "AmqpQueue opend");
m_amqpQueue->declare(QAmqpQueue::AutoDelete); m_amqpQueue->declare(QAmqpQueue::AutoDelete);
m_amqpQueue->bind(m_amqpExchange, m_config.rabbitMQConfig.routingKey); //对于广播类型的交换机消息会发送给所有与之绑定的队列所以此时routingKey无所谓 m_amqpQueue->bind(m_amqpExchange, m_config.rabbitMQConfig.routingKey); //对于广播类型的交换机消息会发送给所有与之绑定的队列所以此时routingKey无所谓
connect(m_amqpQueue, SIGNAL(messageReceived()), this, SLOT(onMessageReceived())); connect(m_amqpQueue, SIGNAL(messageReceived()), this, SLOT(onMessageReceived()));
@ -331,6 +335,7 @@ void AlarmEventDataService::onMessageReceived()
{ {
QAmqpMessage message = m_amqpQueue->dequeue(); QAmqpMessage message = m_amqpQueue->dequeue();
//qDebug() << message.payload(); //qDebug() << message.payload();
LOG_INFO("RabbitMQ", QString("messageReceived: %1").arg(message.payload()));
MessageHandleResult result = processMessage(message); MessageHandleResult result = processMessage(message);
//手动确认消息 //手动确认消息
@ -353,11 +358,13 @@ void AlarmEventDataService::onHistoricalRequestFinished(QNetworkReply* reply)
{ {
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
processHistoricalResponse(data); processHistoricalResponse(data);
LOG_INFO("Http", QString(data));
} }
else else
{ {
QString errorMsg = QString("Request HistoricalData error: %1").arg(/*reply->request().url().toDisplayString(),*/ reply->errorString()); QString errorMsg = QString("Request HistoricalData error: %1").arg(/*reply->request().url().toDisplayString(),*/ reply->errorString());
emit historicalQueryError(errorMsg); emit historicalQueryError(errorMsg);
LOG_ERROR("Http", errorMsg);
} }
reply->deleteLater(); reply->deleteLater();

View File

@ -226,6 +226,7 @@ void AlarmEventDataModel::setFilter(const AlarmEventDataFilter& filter)
if(m_dataMode == RealTime) if(m_dataMode == RealTime)
return; return;
//qInfo() << "AlarmEventDataModel::setFilter()";
m_currentFilter = filter; m_currentFilter = filter;
refresh(); refresh();
} }
@ -244,6 +245,7 @@ void AlarmEventDataModel::refresh()
if(m_dataMode == RealTime) if(m_dataMode == RealTime)
return; return;
//qInfo() << "AlarmEventDataModel::refresh()";
AlarmEventDataService::instance()->queryHistoricalEvents(m_currentFilter.beginTime(), m_currentFilter.endTime(), m_currentFilter.confirmStatus()); AlarmEventDataService::instance()->queryHistoricalEvents(m_currentFilter.beginTime(), m_currentFilter.endTime(), m_currentFilter.confirmStatus());
} }

164
source/logger.cpp Normal file
View File

@ -0,0 +1,164 @@
#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);
}