Merge PR #241: Improve log DB housekeeping performance
This commit is contained in:
commit
2d08e7a028
@ -155,14 +155,10 @@ LogEngine::LogEngine(const QString &driver, const QString &dbName, const QString
|
|||||||
m_db = QSqlDatabase::addDatabase(driver, "logs");
|
m_db = QSqlDatabase::addDatabase(driver, "logs");
|
||||||
m_db.setDatabaseName(dbName);
|
m_db.setDatabaseName(dbName);
|
||||||
m_db.setHostName(hostname);
|
m_db.setHostName(hostname);
|
||||||
m_overflow = 100;
|
m_trimSize = qRound(0.01 * m_dbMaxSize);
|
||||||
|
m_maxQueueLength = 1000;
|
||||||
|
|
||||||
if (QCoreApplication::instance()->organizationName() == "nymea-test") {
|
qCDebug(dcLogEngine) << "Opening logging database" << m_db.databaseName() << "(Max size:" << m_dbMaxSize << "trim size:" << m_trimSize << ")";
|
||||||
m_dbMaxSize = 20;
|
|
||||||
qCDebug(dcLogEngine) << "Set logging dab max size to" << m_dbMaxSize << "for testing.";
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(dcLogEngine) << "Opening logging database" << m_db.databaseName();
|
|
||||||
|
|
||||||
if (!m_db.isValid()) {
|
if (!m_db.isValid()) {
|
||||||
qCWarning(dcLogEngine) << "Database not valid:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
|
qCWarning(dcLogEngine) << "Database not valid:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
|
||||||
@ -175,12 +171,12 @@ LogEngine::LogEngine(const QString &driver, const QString &dbName, const QString
|
|||||||
rotate(m_db.databaseName());
|
rotate(m_db.databaseName());
|
||||||
if (!initDB(username, password)) {
|
if (!initDB(username, password)) {
|
||||||
qCWarning(dcLogEngine()) << "Error fixing log database. Giving up. Logs can't be stored.";
|
qCWarning(dcLogEngine()) << "Error fixing log database. Giving up. Logs can't be stored.";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(&m_jobWatcher, SIGNAL(finished()), this, SLOT(handleJobFinished()));
|
connect(&m_jobWatcher, SIGNAL(finished()), this, SLOT(handleJobFinished()));
|
||||||
|
|
||||||
checkDBSize();
|
checkDBSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +217,7 @@ LogEntriesFetchJob *LogEngine::fetchLogEntries(const LogFilter &filter)
|
|||||||
DatabaseJob *job = new DatabaseJob(m_db, queryString, filter.values());
|
DatabaseJob *job = new DatabaseJob(m_db, queryString, filter.values());
|
||||||
LogEntriesFetchJob *fetchJob = new LogEntriesFetchJob(this);
|
LogEntriesFetchJob *fetchJob = new LogEntriesFetchJob(this);
|
||||||
|
|
||||||
connect(job, &DatabaseJob::finished, this, [this, job, fetchJob](){
|
connect(job, &DatabaseJob::finished, this, [job, fetchJob](){
|
||||||
fetchJob->deleteLater();
|
fetchJob->deleteLater();
|
||||||
if (job->error().isValid()) {
|
if (job->error().isValid()) {
|
||||||
qCWarning(dcLogEngine) << "Error fetching log entries. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
qCWarning(dcLogEngine) << "Error fetching log entries. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
||||||
@ -247,7 +243,7 @@ LogEntriesFetchJob *LogEngine::fetchLogEntries(const LogFilter &filter)
|
|||||||
fetchJob->finished();
|
fetchJob->finished();
|
||||||
});
|
});
|
||||||
|
|
||||||
enqueJob(job);
|
enqueJob(job, true);
|
||||||
|
|
||||||
return fetchJob;
|
return fetchJob;
|
||||||
}
|
}
|
||||||
@ -258,7 +254,7 @@ DevicesFetchJob *LogEngine::fetchDevices()
|
|||||||
|
|
||||||
DatabaseJob *job = new DatabaseJob(m_db, queryString);
|
DatabaseJob *job = new DatabaseJob(m_db, queryString);
|
||||||
DevicesFetchJob *fetchJob = new DevicesFetchJob(this);
|
DevicesFetchJob *fetchJob = new DevicesFetchJob(this);
|
||||||
connect(job, &DatabaseJob::finished, this, [this, job, fetchJob](){
|
connect(job, &DatabaseJob::finished, this, [job, fetchJob](){
|
||||||
fetchJob->deleteLater();
|
fetchJob->deleteLater();
|
||||||
if (job->error().type() != QSqlError::NoError) {
|
if (job->error().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Error fetching device entries from log database:" << job->error().driverText() << job->error().databaseText();
|
qCWarning(dcLogEngine()) << "Error fetching device entries from log database:" << job->error().driverText() << job->error().databaseText();
|
||||||
@ -271,6 +267,7 @@ DevicesFetchJob *LogEngine::fetchDevices()
|
|||||||
}
|
}
|
||||||
fetchJob->finished();
|
fetchJob->finished();
|
||||||
});
|
});
|
||||||
|
enqueJob(job, true);
|
||||||
return fetchJob;
|
return fetchJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,11 +276,11 @@ bool LogEngine::jobsRunning() const
|
|||||||
return !m_jobQueue.isEmpty() || m_currentJob;
|
return !m_jobQueue.isEmpty() || m_currentJob;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogEngine::setMaxLogEntries(int maxLogEntries, int overflow)
|
void LogEngine::setMaxLogEntries(int maxLogEntries, int trimSize)
|
||||||
{
|
{
|
||||||
m_dbMaxSize = maxLogEntries;
|
m_dbMaxSize = maxLogEntries;
|
||||||
m_overflow = overflow;
|
m_trimSize = trimSize;
|
||||||
checkDBSize();
|
trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Removes all entries from the database. This method will be used for the tests. */
|
/*! Removes all entries from the database. This method will be used for the tests. */
|
||||||
@ -298,7 +295,9 @@ void LogEngine::clearDatabase()
|
|||||||
connect(job, &DatabaseJob::finished, this, [this, job](){
|
connect(job, &DatabaseJob::finished, this, [this, job](){
|
||||||
if (job->error().type() != QSqlError::NoError) {
|
if (job->error().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcLogEngine) << "Could not clear logging database. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
qCWarning(dcLogEngine) << "Could not clear logging database. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
m_entryCount = 0;
|
||||||
emit logDatabaseUpdated();
|
emit logDatabaseUpdated();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -319,6 +318,7 @@ void LogEngine::logEvent(const Event &event)
|
|||||||
Logging::LoggingSource sourceType;
|
Logging::LoggingSource sourceType;
|
||||||
if (event.isStateChangeEvent()) {
|
if (event.isStateChangeEvent()) {
|
||||||
sourceType = Logging::LoggingSourceStates;
|
sourceType = Logging::LoggingSourceStates;
|
||||||
|
|
||||||
// There should only be one param
|
// There should only be one param
|
||||||
if (!event.params().isEmpty())
|
if (!event.params().isEmpty())
|
||||||
valueList << event.params().first().value();
|
valueList << event.params().first().value();
|
||||||
@ -430,9 +430,11 @@ void LogEngine::removeDeviceLogs(const DeviceId &deviceId)
|
|||||||
connect(job, &DatabaseJob::finished, this, [this, job, deviceId](){
|
connect(job, &DatabaseJob::finished, this, [this, job, deviceId](){
|
||||||
if (job->error().type() != QSqlError::NoError) {
|
if (job->error().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcLogEngine) << "Error deleting log entries from device" << deviceId.toString() << ". Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
qCWarning(dcLogEngine) << "Error deleting log entries from device" << deviceId.toString() << ". Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
||||||
} else {
|
return;
|
||||||
emit logDatabaseUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit logDatabaseUpdated();
|
||||||
|
checkDBSize();
|
||||||
});
|
});
|
||||||
|
|
||||||
enqueJob(job);
|
enqueJob(job);
|
||||||
@ -450,9 +452,11 @@ void LogEngine::removeRuleLogs(const RuleId &ruleId)
|
|||||||
|
|
||||||
if (job->error().type() != QSqlError::NoError) {
|
if (job->error().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcLogEngine) << "Error deleting log entries from rule" << ruleId.toString() << ". Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
qCWarning(dcLogEngine) << "Error deleting log entries from rule" << ruleId.toString() << ". Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
||||||
} else {
|
return;
|
||||||
emit logDatabaseUpdated();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit logDatabaseUpdated();
|
||||||
|
checkDBSize();
|
||||||
});
|
});
|
||||||
|
|
||||||
enqueJob(job);
|
enqueJob(job);
|
||||||
@ -473,8 +477,27 @@ void LogEngine::appendLogEntry(const LogEntry &entry)
|
|||||||
|
|
||||||
DatabaseJob *job = new DatabaseJob(m_db, queryString);
|
DatabaseJob *job = new DatabaseJob(m_db, queryString);
|
||||||
|
|
||||||
|
// Check for log flooding. If we are exceeding the queue we'll start flagging log events of a certain type.
|
||||||
|
// If we'll get more log events of the same type while the queue is still exceededd, we'll discard the old
|
||||||
|
// ones and queue up the new one instead. The most recent one is more important (i.e. we don't want to lose
|
||||||
|
// the last event in a series).
|
||||||
|
if (m_jobQueue.count() > m_maxQueueLength) {
|
||||||
|
qCDebug(dcLogEngine()) << "An excessive amount of data is being logged. (" << m_jobQueue.length() << "jobs in the queue)";
|
||||||
|
if (m_flaggedJobs.contains(entry.typeId().toString() + entry.deviceId().toString())) {
|
||||||
|
if (m_flaggedJobs.value(entry.typeId().toString() + entry.deviceId().toString()).count() > 10) {
|
||||||
|
qCWarning(dcLogEngine()) << "Discarding log entry because of excessive log flooding.";
|
||||||
|
DatabaseJob *job = m_flaggedJobs[entry.typeId().toString() + entry.deviceId().toString()].takeFirst();
|
||||||
|
int jobIdx = m_jobQueue.indexOf(job);
|
||||||
|
m_jobQueue.takeAt(jobIdx)->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_flaggedJobs[entry.typeId().toString() + entry.deviceId().toString()].append(job);
|
||||||
|
}
|
||||||
|
|
||||||
connect(job, &DatabaseJob::finished, this, [this, job, entry](){
|
connect(job, &DatabaseJob::finished, this, [this, job, entry](){
|
||||||
|
|
||||||
|
m_flaggedJobs[entry.typeId().toString() + entry.deviceId().toString()].removeAll(job);
|
||||||
|
|
||||||
if (job->error().type() != QSqlError::NoError) {
|
if (job->error().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcLogEngine) << "Error writing log entry. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
qCWarning(dcLogEngine) << "Error writing log entry. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
||||||
qCWarning(dcLogEngine) << entry;
|
qCWarning(dcLogEngine) << entry;
|
||||||
@ -482,11 +505,11 @@ void LogEngine::appendLogEntry(const LogEntry &entry)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
emit logEntryAdded(entry);
|
emit logEntryAdded(entry);
|
||||||
|
|
||||||
if (++m_entryCount > m_dbMaxSize + m_overflow) {
|
m_entryCount++;
|
||||||
checkDBSize();
|
trim();
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
enqueJob(job);
|
enqueJob(job);
|
||||||
@ -494,57 +517,52 @@ void LogEngine::appendLogEntry(const LogEntry &entry)
|
|||||||
|
|
||||||
void LogEngine::checkDBSize()
|
void LogEngine::checkDBSize()
|
||||||
{
|
{
|
||||||
if (m_dbMaxSize == -1) {
|
DatabaseJob *job = new DatabaseJob(m_db, "SELECT COUNT(*) FROM entries;");
|
||||||
// No tripping required
|
connect(job, &DatabaseJob::finished, this, [this, job](){
|
||||||
return;
|
|
||||||
}
|
|
||||||
QDateTime startTime = QDateTime::currentDateTime();
|
|
||||||
QString queryString = "SELECT COUNT(*) FROM entries;";
|
|
||||||
|
|
||||||
DatabaseJob *job = new DatabaseJob(m_db, queryString);
|
|
||||||
connect(job, &DatabaseJob::finished, this, [this, job, startTime](){
|
|
||||||
|
|
||||||
if (job->error().type() != QSqlError::NoError) {
|
if (job->error().type() != QSqlError::NoError) {
|
||||||
qCWarning(dcLogEngine()) << "Failed to query entry count in db:" << job->error().databaseText();
|
qCWarning(dcLogEngine()) << "Error fetching log DB size. Driver error:" << job->error().driverText() << "Database error:" << job->error().databaseText();
|
||||||
return;
|
m_entryCount = 0;
|
||||||
}
|
|
||||||
if (job->results().isEmpty()) {
|
|
||||||
qCWarning(dcLogEngine()) << "Failed retrieving entry count.";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_entryCount = job->results().first().value(0).toInt();
|
m_entryCount = job->results().first().value(0).toInt();
|
||||||
|
|
||||||
if (m_entryCount <= m_dbMaxSize) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// keep only the latest m_dbMaxSize entries
|
|
||||||
if (!m_trimWarningPrinted) {
|
|
||||||
qCDebug(dcLogEngine) << "Deleting oldest entries" << (m_entryCount - m_dbMaxSize) << "and keep only the latest" << m_dbMaxSize << "entries.";
|
|
||||||
m_trimWarningPrinted = true;
|
|
||||||
}
|
|
||||||
QString queryDeleteString = QString("DELETE FROM entries WHERE ROWID IN (SELECT ROWID FROM entries ORDER BY timestamp DESC LIMIT -1 OFFSET %1);").arg(QString::number(m_dbMaxSize));
|
|
||||||
|
|
||||||
DatabaseJob *deleteJob = new DatabaseJob(m_db, queryDeleteString);
|
|
||||||
|
|
||||||
connect(deleteJob, &DatabaseJob::finished, this, [this, deleteJob,startTime](){
|
|
||||||
if (deleteJob->error().type() != QSqlError::NoError) {
|
|
||||||
qCWarning(dcLogEngine) << "Error deleting oldest log entries to keep size. Driver error:" << deleteJob->error().driverText() << "Database error:" << deleteJob->error().databaseText();
|
|
||||||
}
|
|
||||||
m_entryCount = m_dbMaxSize;
|
|
||||||
qCDebug(dcLogEngine()) << "Ran housekeeping on log database in" << startTime.msecsTo(QDateTime::currentDateTime()) << "ms.";
|
|
||||||
|
|
||||||
emit logDatabaseUpdated();
|
|
||||||
});
|
|
||||||
enqueJob(deleteJob);
|
|
||||||
});
|
});
|
||||||
enqueJob(job);
|
enqueJob(job, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogEngine::enqueJob(DatabaseJob *job)
|
void LogEngine::trim()
|
||||||
{
|
{
|
||||||
m_jobQueue.append(job);
|
if (m_dbMaxSize == -1 || m_entryCount < m_dbMaxSize) {
|
||||||
|
// No trimming required
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QDateTime startTime = QDateTime::currentDateTime();
|
||||||
|
|
||||||
|
QString queryDeleteString = QString("DELETE FROM entries WHERE ROWID IN (SELECT ROWID FROM entries ORDER BY timestamp DESC LIMIT -1 OFFSET %1);").arg(QString::number(m_dbMaxSize - m_trimSize));
|
||||||
|
|
||||||
|
DatabaseJob *deleteJob = new DatabaseJob(m_db, queryDeleteString);
|
||||||
|
|
||||||
|
connect(deleteJob, &DatabaseJob::finished, this, [this, deleteJob, startTime](){
|
||||||
|
if (deleteJob->error().type() != QSqlError::NoError) {
|
||||||
|
qCWarning(dcLogEngine) << "Error deleting oldest log entries to keep size. Driver error:" << deleteJob->error().driverText() << "Database error:" << deleteJob->error().databaseText();
|
||||||
|
}
|
||||||
|
qCDebug(dcLogEngine()) << "Ran housekeeping on log database in" << startTime.msecsTo(QDateTime::currentDateTime()) << "ms. (Deleted" << m_entryCount - (m_dbMaxSize - m_trimSize) << "entries)";
|
||||||
|
m_entryCount = m_dbMaxSize - m_trimSize;
|
||||||
|
|
||||||
|
emit logDatabaseUpdated();
|
||||||
|
});
|
||||||
|
|
||||||
|
qCDebug(dcLogEngine()) << "Scheduling housekeeping job.";
|
||||||
|
enqueJob(deleteJob, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogEngine::enqueJob(DatabaseJob *job, bool priority)
|
||||||
|
{
|
||||||
|
if (priority) {
|
||||||
|
m_jobQueue.prepend(job);
|
||||||
|
} else {
|
||||||
|
m_jobQueue.append(job);
|
||||||
|
}
|
||||||
|
qCDebug(dcLogEngine()) << "Scheduled job at position" << (priority ? 0 : m_jobQueue.count() - 1) << "(" << m_jobQueue.count() << "jobs in the queue)";
|
||||||
processQueue();
|
processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -569,7 +587,9 @@ void LogEngine::processQueue()
|
|||||||
m_dbMalformed = false;
|
m_dbMalformed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DatabaseJob *job = m_jobQueue.takeFirst();
|
DatabaseJob *job = m_jobQueue.takeFirst();
|
||||||
|
qCDebug(dcLogEngine()) << "Processing DB queue. (" << m_jobQueue.count() << "jobs left in queue," << m_entryCount << "entries in DB)";
|
||||||
m_currentJob = job;
|
m_currentJob = job;
|
||||||
|
|
||||||
QFuture<DatabaseJob*> future = QtConcurrent::run([job](){
|
QFuture<DatabaseJob*> future = QtConcurrent::run([job](){
|
||||||
@ -603,6 +623,8 @@ void LogEngine::handleJobFinished()
|
|||||||
job->finished();
|
job->finished();
|
||||||
job->deleteLater();
|
job->deleteLater();
|
||||||
m_currentJob = nullptr;
|
m_currentJob = nullptr;
|
||||||
|
|
||||||
|
qCDebug(dcLogEngine()) << "DB job finished. (" << m_entryCount << "entries in DB)";
|
||||||
processQueue();
|
processQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -56,7 +56,7 @@ public:
|
|||||||
|
|
||||||
bool jobsRunning() const;
|
bool jobsRunning() const;
|
||||||
|
|
||||||
void setMaxLogEntries(int maxLogEntries, int overflow);
|
void setMaxLogEntries(int maxLogEntries, int trimSize);
|
||||||
void clearDatabase();
|
void clearDatabase();
|
||||||
|
|
||||||
void logSystemEvent(const QDateTime &dateTime, bool active, Logging::LoggingLevel level = Logging::LoggingLevelInfo);
|
void logSystemEvent(const QDateTime &dateTime, bool active, Logging::LoggingLevel level = Logging::LoggingLevelInfo);
|
||||||
@ -88,8 +88,9 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void checkDBSize();
|
void checkDBSize();
|
||||||
|
void trim();
|
||||||
|
|
||||||
void enqueJob(DatabaseJob *job);
|
void enqueJob(DatabaseJob *job, bool priority = false);
|
||||||
void processQueue();
|
void processQueue();
|
||||||
void handleJobFinished();
|
void handleJobFinished();
|
||||||
|
|
||||||
@ -98,11 +99,14 @@ private:
|
|||||||
QString m_username;
|
QString m_username;
|
||||||
QString m_password;
|
QString m_password;
|
||||||
int m_dbMaxSize;
|
int m_dbMaxSize;
|
||||||
int m_overflow;
|
int m_trimSize;
|
||||||
bool m_trimWarningPrinted = false;
|
|
||||||
int m_entryCount = 0;
|
int m_entryCount = 0;
|
||||||
bool m_dbMalformed = false;
|
bool m_dbMalformed = false;
|
||||||
|
|
||||||
|
// When maxQueueLength is exceeded, jobs will be flagged and discarded if this source logs more events
|
||||||
|
int m_maxQueueLength;
|
||||||
|
QHash<QString, QList<DatabaseJob*>> m_flaggedJobs;
|
||||||
|
|
||||||
QList<DatabaseJob*> m_jobQueue;
|
QList<DatabaseJob*> m_jobQueue;
|
||||||
DatabaseJob *m_currentJob = nullptr;
|
DatabaseJob *m_currentJob = nullptr;
|
||||||
QFutureWatcher<DatabaseJob*> m_jobWatcher;
|
QFutureWatcher<DatabaseJob*> m_jobWatcher;
|
||||||
|
|||||||
@ -946,7 +946,7 @@ void NymeaCore::deviceManagerLoaded()
|
|||||||
qCDebug(dcApplication()) << "Starting housekeeping...";
|
qCDebug(dcApplication()) << "Starting housekeeping...";
|
||||||
QDateTime startTime = QDateTime::currentDateTime();
|
QDateTime startTime = QDateTime::currentDateTime();
|
||||||
DevicesFetchJob *job = m_logger->fetchDevices();
|
DevicesFetchJob *job = m_logger->fetchDevices();
|
||||||
connect(job, &DevicesFetchJob::finished, this, [this, job, startTime](){
|
connect(job, &DevicesFetchJob::finished, m_deviceManager, [this, job, startTime](){
|
||||||
foreach (const DeviceId &deviceId, job->results()) {
|
foreach (const DeviceId &deviceId, job->results()) {
|
||||||
if (!m_deviceManager->findConfiguredDevice(deviceId)) {
|
if (!m_deviceManager->findConfiguredDevice(deviceId)) {
|
||||||
qCDebug(dcApplication()) << "Cleaning stale device entries from log DB for device id" << deviceId;
|
qCDebug(dcApplication()) << "Cleaning stale device entries from log DB for device id" << deviceId;
|
||||||
|
|||||||
@ -41,6 +41,11 @@ private:
|
|||||||
inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) {
|
inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) {
|
||||||
verifyError(response, "deviceError", enumValueName(error));
|
verifyError(response, "deviceError", enumValueName(error));
|
||||||
}
|
}
|
||||||
|
inline void waitForDBSync() {
|
||||||
|
while (NymeaCore::instance()->logEngine()->jobsRunning()) {
|
||||||
|
qApp->processEvents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
@ -80,7 +85,8 @@ void TestLogging::initTestCase()
|
|||||||
"LogEngine.debug=true\n"
|
"LogEngine.debug=true\n"
|
||||||
"Tests.debug=true\n"
|
"Tests.debug=true\n"
|
||||||
"MockDevice.debug=true\n"
|
"MockDevice.debug=true\n"
|
||||||
"DeviceManager.debug=true\n");
|
"DeviceManager.debug=true\n"
|
||||||
|
"Application.debug=true\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestLogging::initLogs()
|
void TestLogging::initLogs()
|
||||||
@ -101,6 +107,7 @@ void TestLogging::initLogs()
|
|||||||
QVERIFY(logEntries.count() == 0);
|
QVERIFY(logEntries.count() == 0);
|
||||||
|
|
||||||
restartServer();
|
restartServer();
|
||||||
|
NymeaCore::instance()->logEngine()->setMaxLogEntries(1000, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestLogging::databaseSerializationTest_data()
|
void TestLogging::databaseSerializationTest_data()
|
||||||
@ -158,6 +165,8 @@ void TestLogging::systemLogs()
|
|||||||
qWarning() << "Clearing logging DB";
|
qWarning() << "Clearing logging DB";
|
||||||
clearLoggingDatabase();
|
clearLoggingDatabase();
|
||||||
|
|
||||||
|
waitForDBSync();
|
||||||
|
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceSystem));
|
params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceSystem));
|
||||||
params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeActiveChange));
|
params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeActiveChange));
|
||||||
@ -610,6 +619,8 @@ void TestLogging::testHouseKeeping()
|
|||||||
connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));
|
connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));
|
||||||
spy.wait();
|
spy.wait();
|
||||||
|
|
||||||
|
waitForDBSync();
|
||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.insert("deviceIds", QVariantList() << deviceId);
|
params.insert("deviceIds", QVariantList() << deviceId);
|
||||||
response = injectAndWait("Logging.GetLogEntries", params);
|
response = injectAndWait("Logging.GetLogEntries", params);
|
||||||
@ -623,15 +634,13 @@ void TestLogging::testHouseKeeping()
|
|||||||
|
|
||||||
restartServer();
|
restartServer();
|
||||||
|
|
||||||
// Wait for the mock device to complete the setup
|
waitForDBSync();
|
||||||
do {
|
|
||||||
qApp->processEvents();
|
|
||||||
params.clear();
|
|
||||||
params.insert("deviceId", m_mockDeviceId);
|
|
||||||
response = injectAndWait("Devices.GetConfiguredDevices", params);
|
|
||||||
} while (!response.toMap().value("params").toMap().value("devices").toList().first().toMap().value("setupComplete").toBool());
|
|
||||||
|
|
||||||
|
params.clear();
|
||||||
|
params.insert("deviceIds", QVariantList() << deviceId);
|
||||||
response = injectAndWait("Logging.GetLogEntries", params);
|
response = injectAndWait("Logging.GetLogEntries", params);
|
||||||
|
qCDebug(dcTests()) << qUtf8Printable(QJsonDocument::fromVariant(response).toJson());
|
||||||
|
QVERIFY2(response.toMap().value("status").toString() == QString("success"), "GetLogEntries failed");
|
||||||
QVERIFY2(response.toMap().value("params").toMap().value("logEntries").toList().count() == 0, "Device state change event still in log. Should've been cleaned by housekeeping.");
|
QVERIFY2(response.toMap().value("params").toMap().value("logEntries").toList().count() == 0, "Device state change event still in log. Should've been cleaned by housekeeping.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,6 +669,8 @@ void TestLogging::testLimits()
|
|||||||
verifyDeviceError(response);
|
verifyDeviceError(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waitForDBSync();
|
||||||
|
|
||||||
QVariantMap params;
|
QVariantMap params;
|
||||||
QVariantMap response;
|
QVariantMap response;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user