first working filter version

This commit is contained in:
Simon Stürz 2015-07-01 22:27:20 +02:00 committed by Michael Zanetti
parent 12a93c0898
commit 21ac449b3d
11 changed files with 521 additions and 12 deletions

View File

@ -751,6 +751,55 @@ StateDescriptor JsonTypes::unpackStateDescriptor(const QVariantMap &stateDescrip
return stateDescriptor;
}
LogFilter JsonTypes::unpackLogFilter(const QVariantMap &logFilterMap)
{
LogFilter filter;
if (logFilterMap.contains("startTime")) {
filter.setStartDate(QDateTime::fromMSecsSinceEpoch(logFilterMap.value("startTime").toInt()));
}
if (logFilterMap.contains("endTime")) {
filter.setEndDate(QDateTime::fromMSecsSinceEpoch(logFilterMap.value("endTime").toInt()));
}
if (logFilterMap.contains("loggingSources")) {
QVariantList loggingSources = logFilterMap.value("loggingSources").toList();
foreach (const QVariant &source, loggingSources) {
filter.addLoggingSource((Logging::LoggingSource)s_loggingSource.indexOf(source.toString()));
}
}
if (logFilterMap.contains("loggingLevels")) {
QVariantList loggingLevels = logFilterMap.value("loggingLevels").toList();
foreach (const QVariant &level, loggingLevels) {
filter.addLoggingLevel((Logging::LoggingLevel)s_loggingLevel.indexOf(level.toString()));
}
}
if (logFilterMap.contains("eventTypes")) {
QVariantList eventTypes = logFilterMap.value("eventTypes").toList();
foreach (const QVariant &eventType, eventTypes) {
filter.addLoggingEventType((Logging::LoggingEventType)s_loggingEventType.indexOf(eventType.toString()));
}
}
if (logFilterMap.contains("typeIds")) {
QVariantList typeIds = logFilterMap.value("typeIds").toList();
foreach (const QVariant &typeId, typeIds) {
filter.addTypeId(typeId.toUuid());
}
}
if (logFilterMap.contains("deviceIds")) {
QVariantList deviceIds = logFilterMap.value("deviceIds").toList();
foreach (const QVariant &deviceId, deviceIds) {
filter.addDeviceId(DeviceId(deviceId.toString()));
}
}
if (logFilterMap.contains("values")) {
QVariantList values = logFilterMap.value("values").toList();
foreach (const QVariant &value, values) {
filter.addValue(value.toString());
}
}
return filter;
}
QPair<bool, QString> JsonTypes::validateMap(const QVariantMap &templateMap, const QVariantMap &map)
{
s_lastError.clear();

View File

@ -37,6 +37,7 @@
#include "logging/logging.h"
#include "logging/logentry.h"
#include "logging/logfilter.h"
#include <QObject>
@ -166,6 +167,7 @@ public:
static EventDescriptor unpackEventDescriptor(const QVariantMap &eventDescriptorMap);
static StateEvaluator unpackStateEvaluator(const QVariantMap &stateEvaluatorMap);
static StateDescriptor unpackStateDescriptor(const QVariantMap &stateDescriptorMap);
static LogFilter unpackLogFilter(const QVariantMap &logFilterMap);
static QPair<bool, QString> validateMap(const QVariantMap &templateMap, const QVariantMap &map);
static QPair<bool, QString> validateProperty(const QVariant &templateValue, const QVariant &value);

View File

@ -21,8 +21,9 @@
#include "logginghandler.h"
#include "logging/logengine.h"
#include "guhcore.h"
#include "logging/logfilter.h"
#include "loggingcategories.h"
#include "guhcore.h"
namespace guhserver {
@ -40,7 +41,16 @@ LoggingHandler::LoggingHandler(QObject *parent) :
params.clear(); returns.clear();
setDescription("GetLogEntries", "Get the LogEntries matching the given filter.");
// params.insert("eventTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:startTime", JsonTypes::basicTypeToString(JsonTypes::Int));
params.insert("o:endTime", JsonTypes::basicTypeToString(JsonTypes::Int));
params.insert("o:loggingSources", QVariantList() << JsonTypes::loggingSourceRef());
params.insert("o:loggingLevels", QVariantList() << JsonTypes::loggingLevelRef());
params.insert("o:eventTypes", QVariantList() << JsonTypes::loggingEventTypeRef());
params.insert("o:typeIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:deviceIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:values", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Variant));
setParams("GetLogEntries", params);
returns.insert("loggingError", JsonTypes::loggingErrorRef());
returns.insert("o:logEntries", QVariantList() << JsonTypes::logEntryRef());
@ -64,8 +74,11 @@ void LoggingHandler::logEntryAdded(const LogEntry &logEntry)
JsonReply* LoggingHandler::GetLogEntries(const QVariantMap &params) const
{
qCDebug(dcJsonRpc) << "asked for log entries" << params;
LogFilter filter = JsonTypes::unpackLogFilter(params);
QVariantList entries;
foreach (const LogEntry &entry, GuhCore::instance()->logEngine()->logEntries()) {
foreach (const LogEntry &entry, GuhCore::instance()->logEngine()->logEntries(filter)) {
entries.append(JsonTypes::packLogEntry(entry));
}
QVariantMap returns = statusToReply(Logging::LoggingErrorNoError);

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
@ -37,6 +38,12 @@ LogEngine::LogEngine(QObject *parent):
{
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName("/tmp/guhd-logs.sqlite");
if (!m_db.isValid()) {
qCWarning(dcLogEngine) << "Database not valid:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
return;
}
if (!m_db.open()) {
qCWarning(dcLogEngine) << "Error opening log database:" << m_db.lastError().driverText() << m_db.lastError().databaseText();
return;
@ -45,25 +52,38 @@ LogEngine::LogEngine(QObject *parent):
initDB();
}
QList<LogEntry> LogEngine::logEntries() const
QList<LogEntry> LogEngine::logEntries(const LogFilter &filter) const
{
qCDebug(dcLogEngine) << "Read logging database" << m_db.databaseName();
QList<LogEntry> results;
QSqlQuery query;
query.exec("SELECT * FROM entries;");
QString queryCall = "SELECT * FROM entries;";
if (filter.isEmpty()) {
query.exec(queryCall);
} else {
queryCall = QString("SELECT * FROM entries WHERE %1;").arg(filter.queryString());
query.exec(queryCall);
}
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());
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());
}
//qCDebug(dcLogEngine) << entry;
results.append(entry);
}
qCDebug(dcLogEngine) << "Fetched" << results.count() << "entries for db query:" << queryCall;
return results;
}

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
@ -22,6 +23,7 @@
#define LOGENGINE_H
#include "logentry.h"
#include "logfilter.h"
#include "types/event.h"
#include "types/action.h"
#include "rule.h"
@ -37,7 +39,7 @@ class LogEngine: public QObject
public:
LogEngine(QObject *parent = 0);
QList<LogEntry> logEntries() const;
QList<LogEntry> logEntries(const LogFilter &filter = LogFilter()) const;
signals:
void logEntryAdded(const LogEntry &logEntry);

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
@ -19,6 +20,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "logentry.h"
#include "jsonrpc/jsontypes.h"
#include <QDebug>
@ -57,11 +59,41 @@ Logging::LoggingLevel LogEntry::level() const
return m_level;
}
QString LogEntry::levelString() const
{
switch (m_level) {
case Logging::LoggingLevelAlert:
return "LoggingLevelAlert";
case Logging::LoggingLevelInfo:
return "LoggingLevelInfo";
default:
return "< Unknown >";
}
}
Logging::LoggingSource LogEntry::source() const
{
return m_source;
}
QString LogEntry::sourceString() const
{
switch (m_source) {
case Logging::LoggingSourceActions:
return "LoggingSourceActions";
case Logging::LoggingSourceEvents:
return "LoggingSourceEvents";
case Logging::LoggingSourceRules:
return "LoggingSourceRules";
case Logging::LoggingSourceStates:
return "LoggingSourceStates";
case Logging::LoggingSourceSystem:
return "LoggingSourceSystem";
default:
return "< Unknown >";
}
}
QUuid LogEntry::typeId() const
{
return m_typeId;
@ -96,6 +128,18 @@ Logging::LoggingEventType LogEntry::eventType() const
return m_eventType;
}
QString LogEntry::eventTypeString() const
{
switch (m_eventType) {
case Logging::LoggingEventTypeActiveChange:
return "LoggingEventTypeActiveChange";
case Logging::LoggingEventTypeTrigger:
return "LoggingEventTypeTrigger";
default:
return "< Unknown >";
}
}
bool LogEntry::active() const
{
return m_active;
@ -112,4 +156,18 @@ int LogEntry::errorCode() const
return m_errorCode;
}
QDebug operator<<(QDebug dbg, const LogEntry &entry)
{
dbg.nospace() << "LogEntry (count:" << entry.timestamp().toString() << endl;
dbg.nospace() << " DeviceId: " << entry.deviceId().toString() << endl;
dbg.nospace() << " type id: " << entry.typeId().toString() << endl;
dbg.nospace() << " source: " << entry.sourceString() << endl;
dbg.nospace() << " level: " << entry.levelString() << endl;
dbg.nospace() << " eventType: " << entry.eventTypeString() << endl;
dbg.nospace() << " error code: " << entry.errorCode() << endl;
dbg.nospace() << " active: " << entry.active() << endl;
dbg.nospace() << " value: " << entry.value() << endl;
return dbg.space();
}
}

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
@ -41,8 +42,11 @@ public:
// Valid for all LoggingSources
QDateTime timestamp() const;
Logging::LoggingLevel level() const;
QString levelString() const;
Logging::LoggingSource source() const;
QString sourceString() const;
Logging::LoggingEventType eventType() const;
QString eventTypeString() const;
// Valid for LoggingSourceStates, LoggingSourceEvents, LoggingSourceActions, LoggingSourceRules
QUuid typeId() const;
@ -77,6 +81,7 @@ private:
bool m_active;
int m_errorCode;
};
QDebug operator<<(QDebug dbg, const LogEntry &entry);
}

View File

@ -0,0 +1,306 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "logfilter.h"
namespace guhserver {
LogFilter::LogFilter()
{
}
QString LogFilter::queryString() const
{
if (isEmpty()) {
return QString();
}
QString query;
query.append(createDateString());
if (!query.isEmpty() && !m_sources.isEmpty()) {
query.append("AND ");
}
query.append(createSourcesString());
if (!query.isEmpty() && !m_levels.isEmpty()) {
query.append("AND ");
}
query.append(createLevelsString());
if (!query.isEmpty() && !m_eventTypes.isEmpty()) {
query.append("AND ");
}
query.append(createEventTypesString());
if (!query.isEmpty() && !m_typeIds.isEmpty()) {
query.append("AND ");
}
query.append(createTypeIdsString());
if (!query.isEmpty() && !m_deviceIds.isEmpty()) {
query.append("AND ");
}
query.append(createDeviceIdString());
if (!query.isEmpty() && !m_values.isEmpty()) {
query.append("AND ");
}
query.append(createValuesString());
return query;
}
void LogFilter::setStartDate(const QDateTime &startDate)
{
m_startDate = startDate;
}
QDateTime LogFilter::startDate() const
{
return m_startDate;
}
void LogFilter::setEndDate(const QDateTime &endDate)
{
m_endDate = endDate;
}
QDateTime LogFilter::endDate() const
{
return m_endDate;
}
void LogFilter::addLoggingSource(const Logging::LoggingSource &source)
{
if (!m_sources.contains(source))
m_sources.append(source);
}
QList<Logging::LoggingSource> LogFilter::loggingSources() const
{
return m_sources;
}
void LogFilter::addLoggingLevel(const Logging::LoggingLevel &level)
{
if (!m_levels.contains(level))
m_levels.append(level);
}
QList<Logging::LoggingLevel> LogFilter::loggingLevels() const
{
return m_levels;
}
void LogFilter::addLoggingEventType(const Logging::LoggingEventType &eventType)
{
if (!m_eventTypes.contains(eventType))
m_eventTypes.append(eventType);
}
QList<Logging::LoggingEventType> LogFilter::loggingEventTypes() const
{
return m_eventTypes;
}
void LogFilter::addTypeId(const QUuid &typeId)
{
if (!m_typeIds.contains(typeId))
m_typeIds.append(typeId);
}
QList<QUuid> LogFilter::typeIds() const
{
return m_typeIds;
}
void LogFilter::addDeviceId(const DeviceId &deviceId)
{
if (!m_deviceIds.contains(deviceId))
m_deviceIds.append(deviceId);
}
QList<DeviceId> LogFilter::deviceIds() const
{
return m_deviceIds;
}
void LogFilter::addValue(const QString &value)
{
if (!m_values.contains(value))
m_values.append(value);
}
QList<QString> LogFilter::values() const
{
return m_values;
}
bool LogFilter::isEmpty() const
{
return m_endDate.isNull() &&
m_startDate.isNull() &&
m_sources.isEmpty() &&
m_levels.isEmpty() &&
m_eventTypes.isEmpty() &&
m_typeIds.isEmpty() &&
m_deviceIds.isEmpty() &&
m_values.isEmpty();
}
QString LogFilter::createDateString() const
{
QString query;
if (m_startDate.isValid() && !m_endDate.isValid()) {
// only start date is valid
query.append(QString("timestamp BETWEEN '%1' AND '%2' ")
.arg(m_startDate.toMSecsSinceEpoch())
.arg(QDateTime::currentDateTime().toMSecsSinceEpoch()));
} else if (!m_startDate.isValid() && m_endDate.isValid()) {
// only end date is valid
query.append(QString("timestamp NOT BETWEEN '%1' AND '%2' ")
.arg(m_endDate.toMSecsSinceEpoch())
.arg(QDateTime::currentDateTime().toMSecsSinceEpoch()));
} else if (m_startDate.isValid() && m_endDate.isValid()) {
// both dates are valid
query.append(QString("timestamp BETWEEN '%1' AND '%2' ")
.arg(m_startDate.toMSecsSinceEpoch())
.arg(m_endDate.toMSecsSinceEpoch()));
}
return query;
}
QString LogFilter::createSourcesString() const
{
QString query;
if (!m_sources.isEmpty()) {
if (m_sources.count() == 1) {
query.append(QString("sourceType = '%1' ").arg(m_sources.first()));
} else {
query.append("( ");
foreach (const Logging::LoggingSource &source, m_sources) {
query.append(QString("sourceType = '%1' ").arg(source));
if (source != m_sources.last())
query.append("OR ");
}
query.append(") ");
}
}
return query;
}
QString LogFilter::createLevelsString() const
{
QString query;
if (!m_levels.isEmpty()) {
if (m_levels.count() == 1) {
query.append(QString("loggingLevel = '%1' ").arg(m_levels.first()));
} else {
query.append("( ");
foreach (const Logging::LoggingLevel &level, m_levels) {
query.append(QString("loggingLevel = '%1' ").arg(level));
if (level != m_levels.last())
query.append("OR ");
}
query.append(") ");
}
}
return query;
}
QString LogFilter::createEventTypesString() const
{
QString query;
if (!m_eventTypes.isEmpty()) {
if (m_eventTypes.count() == 1) {
query.append(QString("loggingEventType = '%1' ").arg(m_eventTypes.first()));
} else {
query.append("( ");
foreach (const Logging::LoggingEventType &eventType, m_eventTypes) {
query.append(QString("loggingEventType = '%1' ").arg(eventType));
if (eventType != m_eventTypes.last())
query.append("OR ");
}
query.append(") ");
}
}
return query;
}
QString LogFilter::createTypeIdsString() const
{
QString query;
if (!m_typeIds.isEmpty()) {
if (m_typeIds.count() == 1) {
query.append(QString("typeId = '%1' ").arg(m_typeIds.first().toString()));
} else {
query.append("( ");
foreach (const QUuid &typeId, m_typeIds) {
query.append(QString("typeId = '%1' ").arg(typeId.toString()));
if (typeId != m_typeIds.last())
query.append("OR ");
}
query.append(") ");
}
}
return query;
}
QString LogFilter::createDeviceIdString() const
{
QString query;
if (!m_deviceIds.isEmpty()) {
if (m_deviceIds.count() == 1) {
query.append(QString("deviceId = '%1' ").arg(m_deviceIds.first().toString()));
} else {
query.append("( ");
foreach (const DeviceId &deviceId, m_deviceIds) {
query.append(QString("deviceId = '%1' ").arg(deviceId.toString()));
if (deviceId != m_deviceIds.last())
query.append("OR ");
}
query.append(") ");
}
}
return query;
}
QString LogFilter::createValuesString() const
{
QString query;
if (!m_values.isEmpty()) {
if (m_values.count() == 1) {
query.append(QString("value = '%1' ").arg(m_values.first()));
} else {
query.append("( ");
foreach (const QString &value, m_values) {
query.append(QString("value = '%1' ").arg(value));
if (value != m_values.last())
query.append("OR ");
}
query.append(") ");
}
}
return query;
}
}

View File

@ -1,6 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2015 Simon Stuerz <simon.stuerz@guh.guru> *
* *
* This file is part of guh. *
* *
@ -23,13 +24,65 @@
#include <QDateTime>
#include "logging.h"
#include "typeutils.h"
namespace guhserver {
class LogFilter
{
public:
LogFilter();
QString queryString() const;
void setStartDate(const QDateTime &startDate);
QDateTime startDate() const;
void setEndDate(const QDateTime &endDate);
QDateTime endDate() const;
void addLoggingSource(const Logging::LoggingSource &source) ;
QList<Logging::LoggingSource> loggingSources() const;
void addLoggingLevel(const Logging::LoggingLevel &level);
QList<Logging::LoggingLevel> loggingLevels() const;
void addLoggingEventType(const Logging::LoggingEventType &eventType);
QList<Logging::LoggingEventType> loggingEventTypes() const;
// Valid for LoggingSourceStates, LoggingSourceEvents, LoggingSourceActions, LoggingSourceRules
void addTypeId(const QUuid &typeId);
QList<QUuid> typeIds() const;
// Valid for LoggingSourceStates, LoggingSourceEvents, LoggingSourceActions
void addDeviceId(const DeviceId &deviceId);
QList<DeviceId> deviceIds() const;
// Valid for LoggingSourceStates
void addValue(const QString &value);
QList<QString> values() const;
bool isEmpty() const;
private:
QDateTime m_startDate;
QDateTime m_endDate;
QList<Logging::LoggingSource> m_sources;
QList<Logging::LoggingLevel> m_levels;
QList<Logging::LoggingEventType> m_eventTypes;
QList<QUuid> m_typeIds;
QList<DeviceId> m_deviceIds;
QList<QString> m_values;
QString createDateString() const;
QString createSourcesString() const;
QString createLevelsString() const;
QString createEventTypesString() const;
QString createTypeIdsString() const;
QString createDeviceIdString() const;
QString createValuesString() const;
};
}

View File

@ -36,7 +36,8 @@ class Logging
public:
enum LoggingError {
LoggingErrorNoError,
LoggingErrorLogEntryNotFound
LoggingErrorLogEntryNotFound,
LoggingErrorInvalidFilterParameter
};
enum LoggingSource {

View File

@ -60,7 +60,7 @@ int main(int argc, char *argv[])
s_loggingFilters.insert("Warnings", true);
s_loggingFilters.insert("DeviceManager", true);
s_loggingFilters.insert("RuleEngine", true);
s_loggingFilters.insert("Connection", true);
s_loggingFilters.insert("Connection", false);
s_loggingFilters.insert("JsonRpc", false);
s_loggingFilters.insert("Hardware", false);
s_loggingFilters.insert("LogEngine", false);