mirror of
https://github.com/chenx-dust/EZ4Connect.git
synced 2026-09-20 02:13:32 +08:00
refactor: 日志文件直接存整个软件的日志
This commit is contained in:
@@ -53,7 +53,7 @@ set(SOURCE_FILES
|
||||
infrastructure/coreprocess/coreoutputbuffer.cpp
|
||||
infrastructure/coreprocess/coreoutputparser.cpp
|
||||
core/connectionsessionstate.cpp
|
||||
infrastructure/logging/corelogfile.cpp
|
||||
infrastructure/logging/applicationlogfile.cpp
|
||||
infrastructure/platform/autostart.cpp
|
||||
infrastructure/platform/privileges.cpp
|
||||
infrastructure/settings/settingsprofileloader.cpp
|
||||
@@ -143,13 +143,13 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(applicationlogger_test Qt::Core)
|
||||
add_test(NAME applicationlogger_test COMMAND applicationlogger_test)
|
||||
|
||||
add_executable(corelogfile_test
|
||||
tests/corelogfile_test.cpp
|
||||
infrastructure/logging/corelogfile.cpp
|
||||
add_executable(applicationlogfile_test
|
||||
tests/applicationlogfile_test.cpp
|
||||
infrastructure/logging/applicationlogfile.cpp
|
||||
)
|
||||
target_include_directories(corelogfile_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(corelogfile_test Qt::Core)
|
||||
add_test(NAME corelogfile_test COMMAND corelogfile_test)
|
||||
target_include_directories(applicationlogfile_test PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(applicationlogfile_test Qt::Core)
|
||||
add_test(NAME applicationlogfile_test COMMAND applicationlogfile_test)
|
||||
|
||||
add_executable(corecommandbuilder_test
|
||||
tests/corecommandbuilder_test.cpp
|
||||
|
||||
76
infrastructure/logging/applicationlogfile.cpp
Normal file
76
infrastructure/logging/applicationlogfile.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "applicationlogfile.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDateTime>
|
||||
#include <QMetaObject>
|
||||
#include <QThread>
|
||||
|
||||
namespace
|
||||
{
|
||||
QString currentTimestamp()
|
||||
{
|
||||
return QDateTime::currentDateTime().toString("yyyy/MM/dd hh:mm:ss");
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationLogFile::ApplicationLogFile(const QString &filePath, QObject *parent)
|
||||
: QObject(parent),
|
||||
file(filePath)
|
||||
{
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
|
||||
{
|
||||
stream.setDevice(&file);
|
||||
stream.setEncoding(QStringConverter::Utf8);
|
||||
appendEntry(
|
||||
"=== Log started at " + currentTimestamp()
|
||||
+ " with " + QCoreApplication::applicationName()
|
||||
+ " " + QCoreApplication::applicationVersion()
|
||||
+ " ==="
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationLogFile::~ApplicationLogFile()
|
||||
{
|
||||
if (file.isOpen())
|
||||
{
|
||||
appendEntry("=== Log ended at " + currentTimestamp() + " ===");
|
||||
stream.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
QString ApplicationLogFile::filePath() const
|
||||
{
|
||||
return file.fileName();
|
||||
}
|
||||
|
||||
bool ApplicationLogFile::isOpen() const
|
||||
{
|
||||
return file.isOpen();
|
||||
}
|
||||
|
||||
void ApplicationLogFile::appendEntry(const QString &entry)
|
||||
{
|
||||
if (QThread::currentThread() != thread())
|
||||
{
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this, entry]() { appendEntry(entry); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.isOpen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stream << entry;
|
||||
if (!entry.endsWith('\n'))
|
||||
{
|
||||
stream << '\n';
|
||||
}
|
||||
stream.flush();
|
||||
}
|
||||
26
infrastructure/logging/applicationlogfile.h
Normal file
26
infrastructure/logging/applicationlogfile.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef APPLICATIONLOGFILE_H
|
||||
#define APPLICATIONLOGFILE_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QTextStream>
|
||||
|
||||
class ApplicationLogFile : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ApplicationLogFile(const QString &filePath, QObject *parent = nullptr);
|
||||
~ApplicationLogFile() override;
|
||||
|
||||
QString filePath() const;
|
||||
bool isOpen() const;
|
||||
|
||||
void appendEntry(const QString &entry);
|
||||
|
||||
private:
|
||||
QFile file;
|
||||
QTextStream stream;
|
||||
};
|
||||
|
||||
#endif // APPLICATIONLOGFILE_H
|
||||
@@ -1,59 +0,0 @@
|
||||
#include "corelogfile.h"
|
||||
|
||||
#include <QMetaObject>
|
||||
#include <QThread>
|
||||
|
||||
CoreLogFile::CoreLogFile(const QString &filePath, QObject *parent)
|
||||
: QObject(parent),
|
||||
file(filePath)
|
||||
{
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate))
|
||||
{
|
||||
stream.setDevice(&file);
|
||||
stream.setEncoding(QStringConverter::Utf8);
|
||||
}
|
||||
}
|
||||
|
||||
CoreLogFile::~CoreLogFile()
|
||||
{
|
||||
if (file.isOpen())
|
||||
{
|
||||
stream.flush();
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
QString CoreLogFile::filePath() const
|
||||
{
|
||||
return file.fileName();
|
||||
}
|
||||
|
||||
bool CoreLogFile::isOpen() const
|
||||
{
|
||||
return file.isOpen();
|
||||
}
|
||||
|
||||
void CoreLogFile::appendOutput(const QString &output)
|
||||
{
|
||||
if (QThread::currentThread() != thread())
|
||||
{
|
||||
QMetaObject::invokeMethod(
|
||||
this,
|
||||
[this, output]() { appendOutput(output); },
|
||||
Qt::QueuedConnection
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!file.isOpen())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
stream << output;
|
||||
if (!output.endsWith('\n'))
|
||||
{
|
||||
stream << '\n';
|
||||
}
|
||||
stream.flush();
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
#ifndef CORELOGFILE_H
|
||||
#define CORELOGFILE_H
|
||||
|
||||
#include <QFile>
|
||||
#include <QObject>
|
||||
#include <QTextStream>
|
||||
|
||||
class CoreLogFile : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit CoreLogFile(const QString &filePath, QObject *parent = nullptr);
|
||||
~CoreLogFile() override;
|
||||
|
||||
QString filePath() const;
|
||||
bool isOpen() const;
|
||||
|
||||
void appendOutput(const QString &output);
|
||||
|
||||
private:
|
||||
QFile file;
|
||||
QTextStream stream;
|
||||
};
|
||||
|
||||
#endif // CORELOGFILE_H
|
||||
@@ -43,5 +43,5 @@ QString ApplicationPaths::logFile()
|
||||
{
|
||||
logDirectory.mkpath(".");
|
||||
}
|
||||
return logDirectory.filePath("zjuconnect.log");
|
||||
return logDirectory.filePath("ez4connect.log");
|
||||
}
|
||||
|
||||
11
main.cpp
11
main.cpp
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "application/applicationlogger.h"
|
||||
#include "application/applicationconstants.h"
|
||||
#include "infrastructure/logging/applicationlogfile.h"
|
||||
#include "infrastructure/storage/applicationpaths.h"
|
||||
#include "presentation/main/mainwindow.h"
|
||||
|
||||
#ifndef PROJ_VER
|
||||
@@ -22,7 +24,14 @@ int main(int argc, char *argv[])
|
||||
QApplication::setApplicationVersion(PROJ_VER);
|
||||
QLocale::setDefault(QLocale(QLocale::Chinese, QLocale::SimplifiedChineseScript, QLocale::China));
|
||||
|
||||
ApplicationLogFile applicationLogFile(ApplicationPaths::logFile());
|
||||
ApplicationLogger applicationLogger;
|
||||
QObject::connect(
|
||||
&applicationLogger,
|
||||
&ApplicationLogger::entryAdded,
|
||||
&applicationLogFile,
|
||||
&ApplicationLogFile::appendEntry
|
||||
);
|
||||
|
||||
#if defined(Q_OS_WINDOWS)
|
||||
QApplication::setFont(QFont("Microsoft YaHei UI", QApplication::font().pointSize()));
|
||||
@@ -42,7 +51,7 @@ int main(int argc, char *argv[])
|
||||
else
|
||||
qDebug() << "Failed to load transaction file for" << translateModule;
|
||||
|
||||
MainWindow mainWindow(&applicationLogger);
|
||||
MainWindow mainWindow(&applicationLogger, &applicationLogFile);
|
||||
|
||||
QObject::connect(&app, &SingleApplication::aboutToQuit, &mainWindow, &MainWindow::cleanUpWhenQuit);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "application/connectionsession.h"
|
||||
#include "application/systemproxysession.h"
|
||||
#include "infrastructure/coreprocess/coreexecutable.h"
|
||||
#include "infrastructure/logging/corelogfile.h"
|
||||
#include "infrastructure/platform/privileges.h"
|
||||
#include "infrastructure/settings/settingsprofileloader.h"
|
||||
#include "presentation/coordinators/authdialogcoordinator.h"
|
||||
@@ -29,7 +28,6 @@ ConnectionUiController::ConnectionUiController(
|
||||
SystemProxySession *systemProxySession,
|
||||
AuthDialogCoordinator *authenticationDialogs,
|
||||
ApplicationLogger *applicationLogger,
|
||||
CoreLogFile *coreLogFile,
|
||||
SettingsProvider settingsProvider,
|
||||
ProfileIdProvider profileIdProvider,
|
||||
NotificationHandler notificationHandler,
|
||||
@@ -58,12 +56,6 @@ ConnectionUiController::ConnectionUiController(
|
||||
applicationLogger,
|
||||
&ApplicationLogger::appendCoreOutput
|
||||
);
|
||||
connect(
|
||||
connectionSession,
|
||||
&ConnectionSession::outputRead,
|
||||
coreLogFile,
|
||||
&CoreLogFile::appendOutput
|
||||
);
|
||||
connect(
|
||||
connectionSession,
|
||||
&ConnectionSession::savedSudoPasswordRejected,
|
||||
|
||||
@@ -12,7 +12,6 @@ class QAction;
|
||||
class ApplicationLogger;
|
||||
class AuthDialogCoordinator;
|
||||
class ConnectionSession;
|
||||
class CoreLogFile;
|
||||
class QPushButton;
|
||||
class QSettings;
|
||||
class SystemProxySession;
|
||||
@@ -40,7 +39,6 @@ public:
|
||||
SystemProxySession *systemProxySession,
|
||||
AuthDialogCoordinator *authenticationDialogs,
|
||||
ApplicationLogger *applicationLogger,
|
||||
CoreLogFile *coreLogFile,
|
||||
SettingsProvider settingsProvider,
|
||||
ProfileIdProvider profileIdProvider,
|
||||
NotificationHandler notificationHandler,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "application/commandlineoptions.h"
|
||||
#include "application/settingsmigrator.h"
|
||||
#include "infrastructure/coreprocess/devicetrust.h"
|
||||
#include "infrastructure/logging/corelogfile.h"
|
||||
#include "infrastructure/logging/applicationlogfile.h"
|
||||
#include "infrastructure/storage/applicationpaths.h"
|
||||
#include "infrastructure/update/updatechecker.h"
|
||||
#include "presentation/coordinators/connectionuicontroller.h"
|
||||
@@ -25,10 +25,15 @@
|
||||
#include "presentation/presentationhelpers.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
MainWindow::MainWindow(ApplicationLogger *logger, QWidget *parent) :
|
||||
MainWindow::MainWindow(
|
||||
ApplicationLogger *logger,
|
||||
ApplicationLogFile *logFile,
|
||||
QWidget *parent
|
||||
) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow),
|
||||
applicationLogger(logger)
|
||||
applicationLogger(logger),
|
||||
applicationLogFile(logFile)
|
||||
{
|
||||
const QString overrideConfigPath =
|
||||
CommandLineOptions::value(QCoreApplication::arguments(), "--config-path");
|
||||
@@ -45,7 +50,6 @@ MainWindow::MainWindow(ApplicationLogger *logger, QWidget *parent) :
|
||||
authenticationDialogs = coordinator->authenticationDialogs();
|
||||
connectionSession = coordinator->connection();
|
||||
systemProxySession = coordinator->systemProxy();
|
||||
coreLogFile = new CoreLogFile(ApplicationPaths::logFile(), this);
|
||||
updateChecker = coordinator->updates();
|
||||
connect(updateChecker, &UpdateChecker::versionInfoChanged, this,
|
||||
[this](const VersionInfo &) { updateVersionInfo(); });
|
||||
@@ -128,7 +132,7 @@ MainWindow::MainWindow(ApplicationLogger *logger, QWidget *parent) :
|
||||
connect(ui->openLogAction, &QAction::triggered, this,
|
||||
[this]()
|
||||
{
|
||||
const QString logFilePath = coreLogFile->filePath();
|
||||
const QString logFilePath = applicationLogFile->filePath();
|
||||
QFileInfo logFileInfo(logFilePath);
|
||||
|
||||
if (logFileInfo.exists())
|
||||
@@ -280,7 +284,6 @@ MainWindow::MainWindow(ApplicationLogger *logger, QWidget *parent) :
|
||||
systemProxySession,
|
||||
authenticationDialogs,
|
||||
applicationLogger,
|
||||
coreLogFile,
|
||||
[this]() { return settings; },
|
||||
[this]() { return currentProfileId; },
|
||||
[this](
|
||||
|
||||
@@ -20,8 +20,8 @@ namespace Ui
|
||||
}
|
||||
|
||||
class ApplicationLogger;
|
||||
class ApplicationLogFile;
|
||||
class ConnectionUiController;
|
||||
class CoreLogFile;
|
||||
class UpdateChecker;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
@@ -29,7 +29,11 @@ class MainWindow : public QMainWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(ApplicationLogger *logger, QWidget *parent = nullptr);
|
||||
explicit MainWindow(
|
||||
ApplicationLogger *logger,
|
||||
ApplicationLogFile *logFile,
|
||||
QWidget *parent = nullptr
|
||||
);
|
||||
|
||||
~MainWindow() override;
|
||||
|
||||
@@ -98,7 +102,7 @@ private:
|
||||
ConnectionUiController *connectionUiController;
|
||||
MainWindowCoordinator *coordinator;
|
||||
ApplicationLogger *applicationLogger;
|
||||
CoreLogFile *coreLogFile = nullptr;
|
||||
ApplicationLogFile *applicationLogFile;
|
||||
UpdateChecker *updateChecker;
|
||||
QSettings *settings;
|
||||
ProfileService *profileService;
|
||||
|
||||
@@ -251,7 +251,7 @@ Line3</string>
|
||||
<string>打开日志文件</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>打开核心程序的日志文件</string>
|
||||
<string>打开应用日志文件</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="clearClientDataAction">
|
||||
|
||||
59
tests/applicationlogfile_test.cpp
Normal file
59
tests/applicationlogfile_test.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
#include "infrastructure/logging/applicationlogfile.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool writesApplicationLogEntries()
|
||||
{
|
||||
QTemporaryDir temporaryDirectory;
|
||||
if (!temporaryDirectory.isValid())
|
||||
{
|
||||
qCritical() << "Unable to create temporary directory";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString logPath = temporaryDirectory.filePath("core.log");
|
||||
{
|
||||
ApplicationLogFile logFile(logPath);
|
||||
if (!logFile.isOpen() || logFile.filePath() != logPath)
|
||||
{
|
||||
qCritical() << "Application log file did not open the requested path";
|
||||
return false;
|
||||
}
|
||||
|
||||
logFile.appendEntry("[INFO] application event");
|
||||
logFile.appendEntry("[CORE] standard output\n[CORE] continued standard output");
|
||||
}
|
||||
|
||||
QFile logFile(logPath);
|
||||
if (!logFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
qCritical() << "Unable to read generated application log";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString contents = QString::fromUtf8(logFile.readAll());
|
||||
if (!contents.contains("=== Log started at ")
|
||||
|| !contents.contains(" with LogFileTest 1.0 ===\n")
|
||||
|| !contents.contains("[INFO] application event\n")
|
||||
|| !contents.contains("[CORE] standard output\n[CORE] continued standard output\n")
|
||||
|| !contents.contains("=== Log ended at "))
|
||||
{
|
||||
qCritical().noquote() << "writesApplicationLogEntries failed:\n" << contents;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
QCoreApplication::setApplicationName("LogFileTest");
|
||||
QCoreApplication::setApplicationVersion("1.0");
|
||||
return writesApplicationLogEntries() ? 0 : 1;
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QTemporaryDir>
|
||||
|
||||
#include "infrastructure/logging/corelogfile.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
bool writesOnlyRawCoreOutput()
|
||||
{
|
||||
QTemporaryDir temporaryDirectory;
|
||||
if (!temporaryDirectory.isValid())
|
||||
{
|
||||
qCritical() << "Unable to create temporary directory";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString logPath = temporaryDirectory.filePath("core.log");
|
||||
{
|
||||
CoreLogFile logFile(logPath);
|
||||
if (!logFile.isOpen() || logFile.filePath() != logPath)
|
||||
{
|
||||
qCritical() << "Core log file did not open the requested path";
|
||||
return false;
|
||||
}
|
||||
|
||||
logFile.appendOutput("standard output\ncontinued standard output");
|
||||
logFile.appendOutput("error output");
|
||||
}
|
||||
|
||||
QFile logFile(logPath);
|
||||
if (!logFile.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
qCritical() << "Unable to read generated core log";
|
||||
return false;
|
||||
}
|
||||
|
||||
const QString contents = QString::fromUtf8(logFile.readAll());
|
||||
if (contents != "standard output\ncontinued standard output\nerror output\n")
|
||||
{
|
||||
qCritical().noquote() << "writesOnlyRawCoreOutput failed:\n" << contents;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
return writesOnlyRawCoreOutput() ? 0 : 1;
|
||||
}
|
||||
Reference in New Issue
Block a user