feat:添加log模块
This commit is contained in:
parent
f3f08af3f9
commit
001c4459f0
|
|
@ -56,6 +56,7 @@ set(H_HEADER_FILES
|
|||
include/alarmEventUtils.h
|
||||
include/alarmEventDataService.h
|
||||
include/alarmEventConfigDialog.h
|
||||
include/logger.h
|
||||
)
|
||||
|
||||
set(CPP_SOURCE_FILES
|
||||
|
|
@ -93,6 +94,7 @@ set(CPP_SOURCE_FILES
|
|||
source/alarmEventUtils.cpp
|
||||
source/alarmEventDataService.cpp
|
||||
source/alarmEventConfigDialog.cpp
|
||||
source/logger.cpp
|
||||
)
|
||||
|
||||
set(UI_FILES
|
||||
|
|
@ -219,6 +221,7 @@ install(TARGETS PowerMaster
|
|||
set(CONFIG_FILES
|
||||
alarmEventService_config.ini
|
||||
realTimeDataService_config.ini
|
||||
log_config.ini
|
||||
)
|
||||
set(CONFIG_FILE_DIR "${CMAKE_BINARY_DIR}/config")
|
||||
# 确保配置文件目录存在
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[Log]
|
||||
level=DEBUG
|
||||
maxSize=10485760
|
||||
backups=5
|
||||
consoleOutput=false
|
||||
fileOutput=true
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "alarmEventDataService.h"
|
||||
#include "logger.h"
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrlQuery>
|
||||
|
|
@ -296,28 +297,31 @@ void AlarmEventDataService::onRabbitMQConnected()
|
|||
|
||||
void AlarmEventDataService::onRabbitMQDisconnected()
|
||||
{
|
||||
qWarning() << "Disconnected to RabbitMQ";
|
||||
//qWarning() << "Disconnected to RabbitMQ";
|
||||
LOG_WARN("RabbitMQ", "Disconnected to RabbitMQ");
|
||||
m_serviceStatus = ServiceStatus::Disconnected;
|
||||
scheduleReconnect();
|
||||
}
|
||||
|
||||
void AlarmEventDataService::onRabbitMQError(QAMQP::Error error)
|
||||
{
|
||||
qWarning() << m_amqpClient->errorString();
|
||||
//qWarning() << m_amqpClient->errorString();
|
||||
LOG_WARN("RabbitMQ", m_amqpClient->errorString());
|
||||
m_serviceStatus = ServiceStatus::Error;
|
||||
scheduleReconnect();
|
||||
}
|
||||
|
||||
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;
|
||||
scheduleReconnect();
|
||||
}
|
||||
|
||||
void AlarmEventDataService::onAmqpQueueOpend()
|
||||
{
|
||||
//qInfo() << "AmqpQueue opend";
|
||||
LOG_INFO("RabbitMQ", "AmqpQueue opend");
|
||||
m_amqpQueue->declare(QAmqpQueue::AutoDelete);
|
||||
m_amqpQueue->bind(m_amqpExchange, m_config.rabbitMQConfig.routingKey); //对于广播类型的交换机,消息会发送给所有与之绑定的队列,所以此时routingKey无所谓
|
||||
connect(m_amqpQueue, SIGNAL(messageReceived()), this, SLOT(onMessageReceived()));
|
||||
|
|
@ -331,6 +335,7 @@ void AlarmEventDataService::onMessageReceived()
|
|||
{
|
||||
QAmqpMessage message = m_amqpQueue->dequeue();
|
||||
//qDebug() << message.payload();
|
||||
LOG_INFO("RabbitMQ", QString("messageReceived: %1").arg(message.payload()));
|
||||
MessageHandleResult result = processMessage(message);
|
||||
|
||||
//手动确认消息
|
||||
|
|
@ -353,11 +358,13 @@ void AlarmEventDataService::onHistoricalRequestFinished(QNetworkReply* reply)
|
|||
{
|
||||
QByteArray data = reply->readAll();
|
||||
processHistoricalResponse(data);
|
||||
LOG_INFO("Http", QString(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
QString errorMsg = QString("Request HistoricalData error: %1").arg(/*reply->request().url().toDisplayString(),*/ reply->errorString());
|
||||
emit historicalQueryError(errorMsg);
|
||||
LOG_ERROR("Http", errorMsg);
|
||||
}
|
||||
|
||||
reply->deleteLater();
|
||||
|
|
|
|||
|
|
@ -226,6 +226,7 @@ void AlarmEventDataModel::setFilter(const AlarmEventDataFilter& filter)
|
|||
if(m_dataMode == RealTime)
|
||||
return;
|
||||
|
||||
//qInfo() << "AlarmEventDataModel::setFilter()";
|
||||
m_currentFilter = filter;
|
||||
refresh();
|
||||
}
|
||||
|
|
@ -244,6 +245,7 @@ void AlarmEventDataModel::refresh()
|
|||
if(m_dataMode == RealTime)
|
||||
return;
|
||||
|
||||
//qInfo() << "AlarmEventDataModel::refresh()";
|
||||
AlarmEventDataService::instance()->queryHistoricalEvents(m_currentFilter.beginTime(), m_currentFilter.endTime(), m_currentFilter.confirmStatus());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
Loading…
Reference in New Issue