/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * This file is part of guh. * * * * Guh is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, version 2 of the License. * * * * Guh is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with guh. If not, see . * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "logengine.h" #include "logging.h" #include #include #include #include #include #define DB_SCHEMA_VERSION 1 LogEngine::LogEngine(QObject *parent): QObject(parent) { m_db = QSqlDatabase::addDatabase("QSQLITE"); m_db.setDatabaseName("/tmp/guhd-logs.sqlite"); if (!m_db.open()) { qWarning() << "Error opening log database:" << m_db.lastError().driverText() << m_db.lastError().databaseText(); return; } initDB(); } QList LogEngine::logEntries() const { QList results; QSqlQuery query; query.exec("SELECT * FROM entries;"); while (query.next()) { LogEntry entry( QDateTime::fromMSecsSinceEpoch(query.value("timestamp").toLongLong()), (Logging::LoggingLevel)query.value("loggingLevel").toInt(), (Logging::LoggingSource)query.value("sourceType").toInt(), query.value("errorCode").toInt()); entry.setTypeId(query.value("typeId").toUuid()); entry.setDeviceId(DeviceId(query.value("deviceId").toString())); entry.setValue(query.value("value").toString()); if ((Logging::LoggingEventType)query.value("loggingEventType").toInt() == Logging::LoggingEventTypeActiveChange) { entry.setActive(query.value("active").toBool()); } results.append(entry); } return results; } void LogEngine::logSystemEvent(bool active, Logging::LoggingLevel level) { LogEntry entry(level, Logging::LoggingSourceSystem); entry.setActive(active); appendLogEntry(entry); emit logEntryAdded(entry); } void LogEngine::logEvent(const Event &event) { QStringList valueList; Logging::LoggingSource sourceType; if (event.isStateChangeEvent()) { sourceType = Logging::LoggingSourceStates; valueList << event.param("value").value().toString(); } else { sourceType = Logging::LoggingSourceEvents; foreach (const Param ¶m, event.params()) { valueList << param.value().toString(); } } LogEntry entry(sourceType); entry.setTypeId(event.eventTypeId()); entry.setDeviceId(event.deviceId()); entry.setValue(valueList.join(", ")); appendLogEntry(entry); emit logEntryAdded(entry); } void LogEngine::logAction(const Action &action, Logging::LoggingLevel level, int errorCode) { QStringList valueList; foreach (const Param ¶m, action.params()) { valueList << param.value().toString(); } LogEntry entry(level, Logging::LoggingSourceActions, errorCode); entry.setTypeId(action.actionTypeId()); entry.setDeviceId(action.deviceId()); entry.setValue(valueList.join(", ")); appendLogEntry(entry); emit logEntryAdded(entry); } void LogEngine::logRuleTriggered(const Rule &rule) { LogEntry entry(Logging::LoggingSourceRules); entry.setTypeId(rule.id()); appendLogEntry(entry); emit logEntryAdded(entry); } void LogEngine::logRuleActiveChanged(const Rule &rule) { LogEntry entry(Logging::LoggingSourceRules); entry.setTypeId(rule.id()); entry.setActive(rule.active()); appendLogEntry(entry); emit logEntryAdded(entry); } void LogEngine::appendLogEntry(const LogEntry &entry) { QString queryString = QString("INSERT INTO entries (timestamp, loggingEventType, loggingLevel, sourceType, typeId, deviceId, value, active, errorCode) values ('%1', '%2', '%3', '%4', '%5', '%6', '%7', '%8', '%9');") .arg(entry.timestamp().toMSecsSinceEpoch()) .arg(entry.eventType()) .arg(entry.level()) .arg(entry.source()) .arg(entry.typeId().toString()) .arg(entry.deviceId().toString()) .arg(entry.value()) .arg(entry.active()) .arg(entry.errorCode()); QSqlQuery query; query.exec(queryString); if (query.lastError().isValid()) { qWarning() << "Error writing log entry. Driver error:" << query.lastError().driverText() << "Database error:" << query.lastError().databaseText(); } } void LogEngine::initDB() { m_db.close(); m_db.open(); QSqlQuery query; if (!m_db.tables().contains("metadata")) { query.exec("CREATE TABLE metadata (key varchar(10), data varchar(40));"); query.exec(QString("INSERT INTO metadata (key, data) VALUES('version', '%1');").arg(DB_SCHEMA_VERSION)); } query.exec("SELECT data FROM metadata WHERE key = 'version';"); if (query.next()) { int version = query.value("data").toInt(); if (version != DB_SCHEMA_VERSION) { qWarning() << "Log schema version not matching! Schema upgrade not implemented yet. Logging might fail."; } else { qDebug() << "version matches"; } } else { qWarning() << "Broken log database. Version not found in metadata table."; } if (!m_db.tables().contains("sourceTypes")) { query.exec("CREATE TABLE sourceTypes (id int, name varchar(20), PRIMARY KEY(id));"); qDebug() << query.lastError().databaseText(); QMetaEnum logTypes = Logging::staticMetaObject.enumerator(Logging::staticMetaObject.indexOfEnumerator("LoggingSource")); Q_ASSERT_X(logTypes.isValid(), "LogEngine", "Logging has no enum LoggingSource"); for (int i = 0; i < logTypes.keyCount(); i++) { query.exec(QString("INSERT INTO sourceTypes (id, name) VALUES(%1, '%2');").arg(i).arg(logTypes.key(i))); } } if (!m_db.tables().contains("loggingEventTypes")) { query.exec("CREATE TABLE loggingEventTypes (id int, name varchar(20), PRIMARY KEY(id));"); qDebug() << query.lastError().databaseText(); QMetaEnum logTypes = Logging::staticMetaObject.enumerator(Logging::staticMetaObject.indexOfEnumerator("LoggingEventType")); Q_ASSERT_X(logTypes.isValid(), "LogEngine", "Logging has no enum LoggingEventType"); for (int i = 0; i < logTypes.keyCount(); i++) { query.exec(QString("INSERT INTO loggingEventTypes (id, name) VALUES(%1, '%2');").arg(i).arg(logTypes.key(i))); } } if (!m_db.tables().contains("entries")) { query.exec("CREATE TABLE entries " "(" "timestamp int," "loggingLevel int," "sourceType int," "typeId varchar(38)," "deviceId varchar(38)," "value varchar(100)," "loggingEventType int," "active bool," "errorCode int," "FOREIGN KEY(sourceType) REFERENCES sourceTypes(id)," "FOREIGN KEY(loggingEventType) REFERENCES loggingEventTypes(id)" ");"); if (query.lastError().isValid()) { qWarning() << "Error creating log table in database. Driver error:" << query.lastError().driverText() << "Database error:" << query.lastError().databaseText(); } } }