提交 c30540b9 编写于 作者: mahuifa's avatar mahuifa

新功能:日志系统模块增加CSV保存功能

    1、日志系统模块可将日志信息保存到CSV文件,便于阅读、分类和查找日志信息;
    2、CSV文件可用于将日志信息导入数据库;
    3、修复了日志系统中通过日志行号创建新文件功能。
上级 b781f5a7
#---------------------------------------------------------------------
# 模块功能: qt日志系统模块,无第三方依赖
# 1、支持将日志保存到纯文本Log中;
# 2、支持将日志保存到纯文本的CSV中,便于阅读和查找日志信息
# 支持编译器:
# 开发者: mhf
# 邮箱 1603291350@qq.com
......
......@@ -20,16 +20,16 @@ void LogConfig::initTxtConfig()
QSettings config("./config.ini", QSettings::IniFormat);
if(!file.exists())
{
config.beginGroup("Txt");
config.beginGroup("LogConfig");
config.setValue("relyMode", 0);
config.setValue("time", 12);
config.setValue("time", 24);
config.setValue("size", 100);
config.setValue("name", "");
config.setValue("rowNum",1000);
config.endGroup();
}
config.beginGroup("Txt");
config.beginGroup("LogConfig");
txtConfig.relyMode = (TxtRelyMode)config.value("relyMode").toUInt();
txtConfig.time = config.value("time").toUInt();
txtConfig.size = config.value("size").toUInt();
......@@ -41,6 +41,6 @@ void LogConfig::initTxtConfig()
void LogConfig::setTxtLogName(QString name)
{
QSettings config("./config.ini", QSettings::IniFormat);
config.setValue("Txt/name", name);
config.setValue("LogConfig/name", name);
txtConfig.name = name;
}
......@@ -17,7 +17,7 @@ LogSaveBase::LogSaveBase(QObject *parent) : QObject(parent)
LogSaveBase::~LogSaveBase()
{
disconnect(LogInput::getInstance(), &LogInput::logData, this, &LogSaveBase::on_logData);
}
LogSaveBase* LogSaveBase::m_logSave = nullptr;
......
......@@ -22,6 +22,7 @@ public:
explicit LogSaveBase(QObject *parent = nullptr);
~LogSaveBase();
protected:
/**
* @brief 保存日志数据
* @param type 日志级别
......@@ -33,7 +34,6 @@ public:
*/
virtual void on_logData(QtMsgType type, QTime time, QString file, QString function, int line, QString msg) = 0;
protected:
/**
* @brief 打开新文件
* @return true:打开成功 false:打开失败
......
......@@ -5,6 +5,9 @@
LogSaveTxt::LogSaveTxt(QObject *parent) : LogSaveBase(parent)
{
m_strLogFormat = "%1 %2 %3 %4 %5 %6";
m_strNameFormat = "yyyy-MM-dd HH-mm-ss.log";
m_strTimeNameFormat = "yyyy-MM-dd.log";
}
LogSaveTxt::~LogSaveTxt()
......@@ -26,12 +29,37 @@ LogSaveBase *LogSaveTxt::getInstance()
return m_logSave;
}
void LogSaveTxt::on_logData(QtMsgType type, QTime time, QString file, QString function, int line, QString msg)
/**
* @brief 设置日志文件保存的数据类型
* @param type
*/
void LogSaveTxt::setFileType(FileType type)
{
if(!openNewFile())
this->m_type = type;
QMutexLocker locker(&m_mutex);
if(Log == m_type)
{
return;
m_strLogFormat = "%1 %2 %3 %4 %5 %6";
m_strNameFormat = "yyyy-MM-dd HH-mm-ss.log";
m_strTimeNameFormat = "yyyy-MM-dd.log";
}
else if(CSV == m_type)
{
m_strLogFormat = "%1,%2,%3,%4,%5,%6";
m_strNameFormat = "yyyy-MM-dd HH-mm-ss.CSV"; // 这里后缀只能用大写,因为小写的会被QTime替换
m_strTimeNameFormat = "yyyy-MM-dd.CSV";
}
else
{}
LogConfig::setTxtLogName(""); // 清除配置文件中的日志文件名,便于立刻替换Log/CSV文件,如果没有这一行会等待满足创建新文件的条件才会替换Log/CSV
m_file.close();
}
void LogSaveTxt::on_logData(QtMsgType type, QTime time, QString file, QString function, int line, QString msg)
{
QMutexLocker locker(&m_mutex);
QString strData = "debug";
switch (type) {
......@@ -51,9 +79,18 @@ void LogSaveTxt::on_logData(QtMsgType type, QTime time, QString file, QString fu
strData = "fatal";
break;
}
if(!openNewFile())
{
return;
}
strData += QString(10 - strData.count(), ' ');
QString strLog = QString("%1 %2 %3 %4 %5 %6").arg(time.toString("HH:mm:ss")).arg(strData).arg(file).arg(function).arg(line).arg(msg);
QString strLog = QString(m_strLogFormat)
.arg(time.toString("HH:mm:ss"))
.arg(strData)
.arg(file)
.arg(function)
.arg(line)
.arg(msg);
m_out << strLog <<"\n";
m_out.flush();
}
......@@ -66,7 +103,7 @@ void LogSaveTxt::on_logData(QtMsgType type, QTime time, QString file, QString fu
bool LogSaveTxt::openFile(QString name)
{
m_file.setFileName(QString("%1%2").arg(LOG_PATH).arg(name));
if(m_file.open(QIODevice::ReadWrite | QIODevice::Append | QIODevice::Text))
if(m_file.open(QIODevice::ReadWrite| QIODevice::Text))
{
m_out.setDevice(&m_file);
return true;
......@@ -109,27 +146,34 @@ bool LogSaveTxt::openNewFile()
*/
bool LogSaveTxt::relyTime()
{
QString strName = QDateTime::currentDateTime().toString("yyyy-MM-dd.log");
QString strName = QDateTime::currentDateTime().toString(m_strTimeNameFormat);
if(LogConfig::txtConfig.time == 12)
{
if(QTime::currentTime().hour() <= 12)
{
strName.replace(".log", "_上.log");
strName.replace(".CSV", "_上.CSV");
}
else
{
strName.replace(".log", "_下.log");
strName.replace(".CSV", "_下.CSV");
}
}
if(!m_file.isOpen()) // 文件未打开
{
return openFile(strName);
if(LogConfig::txtConfig.name.isEmpty()) // 配置文件中是否有文件名
{
LogConfig::setTxtLogName(strName);
}
return openFile(LogConfig::txtConfig.name);
}
else
{
if(strName != m_file.fileName())
if((LOG_PATH + strName) != m_file.fileName()) // 路径 + 新文件名 与打开的文件是否相同
{
LogConfig::setTxtLogName(strName);
m_file.close();
return openFile(strName);
}
......@@ -147,7 +191,7 @@ bool LogSaveTxt::relySize()
{
if(LogConfig::txtConfig.name.isEmpty())
{
QString strName = QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss.log");
QString strName = QDateTime::currentDateTime().toString(m_strNameFormat);
LogConfig::setTxtLogName(strName);
}
return openFile(LogConfig::txtConfig.name);
......@@ -157,7 +201,7 @@ bool LogSaveTxt::relySize()
if(m_file.size() >= LogConfig::txtConfig.size * 1024 * 1024) // 判断文件大小
{
m_file.close();
QString strName = QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss.log");
QString strName = QDateTime::currentDateTime().toString(m_strNameFormat);
LogConfig::setTxtLogName(strName);
return openFile(strName);
}
......@@ -171,16 +215,17 @@ bool LogSaveTxt::relySize()
*/
bool LogSaveTxt::relyRowNum()
{
static uint rowNum = 0; // 文件行数
if(!m_file.isOpen()) // 文件未打开
{
if(LogConfig::txtConfig.name.isEmpty())
{
QString strName = QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss.log");
QString strName = QDateTime::currentDateTime().toString(m_strNameFormat);
LogConfig::setTxtLogName(strName);
}
if(openFile(LogConfig::txtConfig.name))
{
QByteArray arr = m_file.readAll();
rowNum = QString(m_file.readAll()).split('\n').count(); // 获取文件行数
return true;
}
else
......@@ -190,10 +235,12 @@ bool LogSaveTxt::relyRowNum()
}
else
{
if(m_file.size() >= LogConfig::txtConfig.size * 1024 * 1024) // 判断文件大小
rowNum++;
if(rowNum > LogConfig::txtConfig.rowNum) // 判断文件行数
{
rowNum = 1;
m_file.close();
QString strName = QDateTime::currentDateTime().toString("yyyy-MM-dd HH-mm-ss.log");
QString strName = QDateTime::currentDateTime().toString(m_strNameFormat);
LogConfig::setTxtLogName(strName);
return openFile(strName);
}
......
/******************************************************************************
/******************************************************************************
* @文件名 logsavetxt.h
* @功能 将日志保存到txt中
* @开发者 mhf
......@@ -17,11 +17,23 @@
class LogSaveTxt : public LogSaveBase
{
Q_OBJECT
Q_PROPERTY(FileType m_type READ fileType WRITE setFileType)
public:
enum FileType // 日志保存的TxT文件类型
{
Log, // 日志保存到纯txt文本中
CSV, // 日志保存为csv文件,方便查看
};
public:
static LogSaveBase* getInstance(); // 获取单例对象
void on_logData(QtMsgType type, QTime time, QString file, QString function, int line, QString msg) override;
void setFileType(FileType type);
FileType fileType(){return m_type;}
protected:
void on_logData(QtMsgType type, QTime time, QString file, QString function, int line, QString msg) override;
bool openNewFile() override;
bool relyTime();
bool relySize();
......@@ -37,7 +49,11 @@ signals:
private:
QFile m_file;
QTextStream m_out;
FileType m_type;
QMutex m_mutex;
QString m_strLogFormat; // 保存的日志内容格式
QString m_strNameFormat; // 保存的日志文件名称格式
QString m_strTimeNameFormat; // 保存的日志文件名称格式
};
#endif // LOGSAVETXT_H
......@@ -28,3 +28,9 @@ void Widget::on_timer()
qWarning() << "Warning信息";
qCritical() << "critical信息";
}
void Widget::on_com_FileType_activated(int index)
{
((LogSaveTxt*)LogSaveTxt::getInstance())->setFileType((LogSaveTxt::FileType)index);
}
......@@ -20,6 +20,8 @@ private slots:
void on_timer();
void on_com_FileType_activated(int index);
private:
Ui::Widget *ui;
QTimer* m_timer;
......
......@@ -14,9 +14,45 @@
<string>Widget</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="2">
<item row="0" column="0" rowspan="2">
<widget class="LogWidgetText" name="widget" native="true"/>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="com_FileType">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>设置日志保存文件类型</string>
</property>
<item>
<property name="text">
<string>Log</string>
</property>
</item>
<item>
<property name="text">
<string>CSV</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>553</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<customwidgets>
......
README.assets/QLog.gif

166.5 KB | W: | H:

README.assets/QLog.gif

2.5 MB | W: | H:

README.assets/QLog.gif
README.assets/QLog.gif
README.assets/QLog.gif
README.assets/QLog.gif
  • 2-up
  • Swipe
  • Onion skin
......@@ -64,7 +64,8 @@ Qt常用功能Demo
* 可选择日志显示到文本窗口并保存、不显示只保存两种使用方式;
* 选择显示日志级别;
* 可设置不同级别日志显示颜色;
* 将日志信息保存到txt文本;
* 支持将日志信息保存到纯文本Log文件中;
* 支持将日志信息保存到纯文本CSV文件中,便于阅读、查找和分类日志信息,可用于将CSV中的日志信息导入数据库;
* 支持按12小时、24小时、按文件大小、日志行数创建新日志文件;
* 无任何第三方依赖,支持任意编译器,任意系统;
* 保留日志存储接口、日志显示接口,便于后续扩展日志存储、显示方式,如存储到数据库等;
......@@ -76,6 +77,8 @@ Qt常用功能Demo
![log](README.assets/log.PNG)
![image-20220408223533219](README.assets/image-20220408223533219.png)
### 2.4 QMPlayer
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册