From 3c05b5816aa0fb978686b0ed16a02336e0981a0e Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 7 Jul 2016 23:40:52 +0200 Subject: sinksh trace command including autocompletion The sinksh command allows to easily turn tracing for certain areas on or off. --- common/log.cpp | 69 ++++++++++++++++++++++++++++++------ common/log.h | 1 + sinksh/sinksh_utils.cpp | 6 ++-- sinksh/syntax_modules/sink_trace.cpp | 44 ++++++++++++++--------- 4 files changed, 90 insertions(+), 30 deletions(-) diff --git a/common/log.cpp b/common/log.cpp index 821df06..a3df04c 100644 --- a/common/log.cpp +++ b/common/log.cpp @@ -6,8 +6,11 @@ #include #include #include +#include +#include #include #include +#include using namespace Sink::Log; @@ -218,9 +221,63 @@ static QByteArray getProgramName() } } +static QSharedPointer debugAreasConfig() +{ + return QSharedPointer::create(QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/sink/debugAreas.ini", QSettings::IniFormat); +} + +class DebugAreaCollector { +public: + DebugAreaCollector() + { + QMutexLocker locker(&mutex); + mDebugAreas = debugAreasConfig()->value("areas").value().split(';').toSet(); + } + + ~DebugAreaCollector() + { + QMutexLocker locker(&mutex); + mDebugAreas += debugAreasConfig()->value("areas").value().split(';').toSet(); + debugAreasConfig()->setValue("areas", QVariant::fromValue(mDebugAreas.toList().join(';'))); + } + + void add(const QString &area) + { + QMutexLocker locker(&mutex); + mDebugAreas << area; + } + + QSet debugAreas() + { + QMutexLocker locker(&mutex); + return mDebugAreas; + } + + QMutex mutex; + QSet mDebugAreas; +}; + +static auto sDebugAreaCollector = std::unique_ptr(new DebugAreaCollector); + +QSet Sink::Log::debugAreas() +{ + return sDebugAreaCollector->debugAreas(); +} + +static void collectDebugArea(const QString &debugArea) +{ + sDebugAreaCollector->add(debugArea); +} + static bool containsItemStartingWith(const QByteArray &pattern, const QByteArrayList &list) { for (const auto &item : list) { + if (item.startsWith('*')) { + auto stripped = item.mid(1); + if (pattern.contains(stripped)) { + return true; + } + } if (pattern.startsWith(item)) { return true; } @@ -248,9 +305,9 @@ QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, if (sPrimaryComponent.isEmpty()) { sPrimaryComponent = getProgramName(); } - QString fullDebugArea = sPrimaryComponent + "."+ QString::fromLatin1(debugComponent) + "." + QString::fromLatin1(debugArea); + QString fullDebugArea = sPrimaryComponent + "." + (debugComponent ? (QString::fromLatin1(debugComponent) + ".") : "") + (debugArea ? QString::fromLatin1(debugArea) : ""); - //TODO add to autocompletion + collectDebugArea(fullDebugArea); auto areas = debugOutputFilter(Sink::Log::Area); if (!areas.isEmpty()) { @@ -258,14 +315,6 @@ QDebug Sink::Log::debugStream(DebugLevel debugLevel, int line, const char *file, return QDebug(&nullstream); } } - // static QByteArray programName = getProgramName(); - // - // auto filter = debugOutputFilter(Sink::Log::ApplicationName); - // if (!filter.isEmpty() && !filter.contains(programName)) { - // if (!containsItemStartingWith(programName, filter)) { - // return QDebug(&nullstream); - // } - // } QString prefix; int prefixColorCode = ANSI_Colors::DoNothing; diff --git a/common/log.h b/common/log.h index d801ed9..f47a3ae 100644 --- a/common/log.h +++ b/common/log.h @@ -15,6 +15,7 @@ enum DebugLevel }; void SINK_EXPORT setPrimaryComponent(const QString &component); +QSet SINK_EXPORT debugAreas(); QByteArray SINK_EXPORT debugLevelName(DebugLevel debugLevel); DebugLevel SINK_EXPORT debugLevelFromName(const QByteArray &name); diff --git a/sinksh/sinksh_utils.cpp b/sinksh/sinksh_utils.cpp index 2a6f628..14b0aab 100644 --- a/sinksh/sinksh_utils.cpp +++ b/sinksh/sinksh_utils.cpp @@ -21,6 +21,7 @@ #include "sinksh_utils.h" #include "common/store.h" +#include "common/log.h" #include "utils.h" @@ -115,10 +116,7 @@ QStringList resourceIds(State &state) QStringList debugareaCompleter(const QStringList &, const QString &fragment, State &state) { - QStringList list; - list << "foo.bar" << "tar.war" << "bluub"; - // return Utils::filteredCompletions(debugAreas(state), fragment); - return Utils::filteredCompletions(list, fragment); + return Utils::filteredCompletions(Sink::Log::debugAreas().toList(), fragment); } QStringList resourceCompleter(const QStringList &, const QString &fragment, State &state) diff --git a/sinksh/syntax_modules/sink_trace.cpp b/sinksh/syntax_modules/sink_trace.cpp index e7b92de..d480254 100644 --- a/sinksh/syntax_modules/sink_trace.cpp +++ b/sinksh/syntax_modules/sink_trace.cpp @@ -35,34 +35,46 @@ namespace SinkTrace { -bool trace(const QStringList &args, State &state) +bool traceOff(const QStringList &args, State &state) { - // if (args.isEmpty()) { - // state.printError(QObject::tr("Specifiy a debug area to trace.")); - // return false; - // } - // - // - qDebug() << "Trace arguments: " << args; - Sink::Log::setDebugOutputLevel(Sink::Log::Trace); - // Sink::Log::setDebugOutputFilter(Sink::Log::FilterType::Area, "filter"); - + Sink::Log::setDebugOutputLevel(Sink::Log::Log); + qDebug() << "Turned trace off: " << args; return true; } -bool traceOff(const QStringList &args, State &state) +bool traceOn(const QStringList &args, State &state) { - Sink::Log::setDebugOutputLevel(Sink::Log::Log); - qDebug() << "Turned trace off: " << args; + if (args.isEmpty()) { + state.printError(QObject::tr("Specifiy a debug area to trace: ") + Sink::Log::debugAreas().toList().join(", ")); + return false; + } + Sink::Log::setDebugOutputLevel(Sink::Log::Trace); + QByteArrayList filter; + for (const auto &arg : args) { + filter << arg.toLatin1(); + } + Sink::Log::setDebugOutputFilter(Sink::Log::Area, filter); return true; } +bool trace(const QStringList &args, State &state) +{ + return traceOn(args, state); +} + + Syntax::List syntax() { Syntax trace("trace", QObject::tr("Control trace debug output."), &SinkTrace::trace, Syntax::NotInteractive); - trace.completer = &SinkshUtils::debugareaCompleter; + trace.completer = &SinkshUtils::debugareaCompleter; + + Syntax traceOff("off", QObject::tr("Turns off trace output."), &SinkTrace::traceOff, Syntax::NotInteractive); + traceOff.completer = &SinkshUtils::debugareaCompleter; + trace.children << traceOff; - trace.children << Syntax("off", QObject::tr("Turns off trace output."), &SinkTrace::traceOff, Syntax::NotInteractive); + Syntax traceOn("on", QObject::tr("Turns on trace output."), &SinkTrace::traceOn, Syntax::NotInteractive); + traceOn.completer = &SinkshUtils::debugareaCompleter; + trace.children << traceOn; return Syntax::List() << trace; } -- cgit v1.2.3