diff --git a/src/libcalamares/JobQueue.cpp b/src/libcalamares/JobQueue.cpp index b5bdf0543..339fd8457 100644 --- a/src/libcalamares/JobQueue.cpp +++ b/src/libcalamares/JobQueue.cpp @@ -54,7 +54,7 @@ public: for( auto job : m_jobs ) { emitProgress(); - cLog() << "Starting job" << job->prettyName(); + cDebug() << "Starting job" << job->prettyName(); connect( job.data(), &Job::progress, this, &JobThread::emitProgress ); JobResult result = job->exec(); if ( !result ) diff --git a/src/libcalamares/utils/Logger.cpp b/src/libcalamares/utils/Logger.cpp index 5c17cdddc..0a13881d3 100644 --- a/src/libcalamares/utils/Logger.cpp +++ b/src/libcalamares/utils/Logger.cpp @@ -86,7 +86,7 @@ log( const char* msg, unsigned int debugLevel, bool toDisk = true ) } -void +static void CalamaresLogHandler( QtMsgType type, const QMessageLogContext& context, const QString& msg ) { static QMutex s_mutex; @@ -116,7 +116,7 @@ CalamaresLogHandler( QtMsgType type, const QMessageLogContext& context, const QS } -QString +static QString logFile() { return CalamaresUtils::appLogDir().filePath( "session.log" ); @@ -177,4 +177,22 @@ CDebug::~CDebug() { } +const char* continuation = "\n "; + +QString toString( const QVariant& v ) +{ + auto t = v.type(); + + if ( t == QVariant::List ) + { + QStringList s; + auto l = v.toList(); + for ( auto lit = l.constBegin(); lit != l.constEnd(); ++lit ) + s << lit->toString(); + return s.join(", "); + } + else + return v.toString(); +} + } // namespace diff --git a/src/libcalamares/utils/Logger.h b/src/libcalamares/utils/Logger.h index b6211c4fe..5db7253bb 100644 --- a/src/libcalamares/utils/Logger.h +++ b/src/libcalamares/utils/Logger.h @@ -2,7 +2,7 @@ * * Copyright 2010-2011, Christian Muehlhaeuser * Copyright 2014, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017-2018, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,6 +27,8 @@ namespace Logger { + extern const char* continuation; + enum { LOG_DISABLE = 0, @@ -41,7 +43,7 @@ namespace Logger class DLLEXPORT CLog : public QDebug { public: - CLog( unsigned int debugLevel = 0 ); + explicit CLog( unsigned int debugLevel ); virtual ~CLog(); private: @@ -58,9 +60,14 @@ namespace Logger virtual ~CDebug(); }; - DLLEXPORT void CalamaresLogHandler( QtMsgType type, const QMessageLogContext& context, const QString& msg ); + /** + * @brief Start logging to the log file. + * + * Call this (once) to start logging to the log file (usually + * ~/.cache/calamares/session.log ). An existing log file is + * rolled over if it is too large. + */ DLLEXPORT void setupLogfile(); - DLLEXPORT QString logFile(); /** * @brief Set a log level for future logging. @@ -72,9 +79,99 @@ namespace Logger * Practical values are 0, 1, 2, and 6. */ DLLEXPORT void setupLogLevel( unsigned int level ); + + /** + * @brief Row-oriented formatted logging. + * + * Use DebugRow to produce multiple rows of 2-column output + * in a debugging statement. For instance, + * cDebug() << DebugRow(1,12) + * << DebugRow(2,24) + * will produce a single timestamped debug line with continuations. + * Each DebugRow produces one line of output, with the two values. + */ + template + struct DebugRow + { + public: + explicit DebugRow(const T& t, const U& u) + : first(t) + , second(u) + {} + + const T& first; + const U& second; + } ; + + /** + * @brief List-oriented formatted logging. + * + * Use DebugList to produce multiple rows of output in a debugging + * statement. For instance, + * cDebug() << DebugList( QStringList() << "foo" << "bar" ) + * will produce a single timestamped debug line with continuations. + * Each element of the list of strings will be logged on a separate line. + */ + struct DebugList + { + explicit DebugList( const QStringList& l ) + : list(l) + {} + + const QStringList& list; + } ; + + /** + * @brief Map-oriented formatted logging. + * + * Use DebugMap to produce multiple rows of output in a debugging + * statement from a map. The output is intentionally a bit-yaml-ish. + * cDebug() << DebugMap( map ) + * will produce a single timestamped debug line with continuations. + * The continued lines will have a key (from the map) and a value + * on each line. + */ + struct DebugMap + { + public: + explicit DebugMap(const QVariantMap& m) + : map( m ) + {} + + const QVariantMap& map; + } ; + + /** @brief output operator for DebugRow */ + template + inline QDebug& + operator <<( QDebug& s, const DebugRow& t ) + { + s << continuation << t.first << ':' << ' ' << t.second; + return s; + } + + /** @brief output operator for DebugList */ + inline QDebug& + operator <<( QDebug& s, const DebugList& c ) + { + for( const auto& i : c.list ) + s << continuation << i; + return s; + } + + /** @brief supporting method for outputting a DebugMap */ + QString toString( const QVariant& v ); + + /** @brief output operator for DebugMap */ + inline QDebug& + operator <<( QDebug& s, const DebugMap& t ) + { + for ( auto it = t.map.constBegin(); it != t.map.constEnd(); ++it ) + s << continuation << it.key().toUtf8().constData() << ':' << ' ' << toString( it.value() ).toUtf8().constData(); + return s; + } } -#define cLog Logger::CLog #define cDebug Logger::CDebug #define cWarning() Logger::CDebug(Logger::LOGWARNING) << "WARNING:" #define cError() Logger::CDebug(Logger::LOGERROR) << "ERROR:" diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/ExecutionViewStep.cpp index 0a9850fd7..109bd1384 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/ExecutionViewStep.cpp @@ -2,6 +2,7 @@ * * Copyright 2014, Aurélien Gâteau * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2018, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -64,7 +65,7 @@ ExecutionViewStep::ExecutionViewStep( QObject* parent ) innerLayout->addWidget( m_progressBar ); innerLayout->addWidget( m_label ); - cDebug() << "QML import paths:" << m_slideShow->engine()->importPathList(); + cDebug() << "QML import paths:" << Logger::DebugList( m_slideShow->engine()->importPathList() ); connect( JobQueue::instance(), &JobQueue::progress, this, &ExecutionViewStep::updateFromJobQueue ); diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 2be3e3832..e597bf6a3 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -150,9 +150,9 @@ ViewManager::insertViewStep( int before, ViewStep* step ) void ViewManager::onInstallationFailed( const QString& message, const QString& details ) { - cLog() << "Installation failed:"; - cLog() << "- message:" << message; - cLog() << "- details:" << details; + cError() << "Installation failed:"; + cDebug() << "- message:" << message; + cDebug() << "- details:" << details; QMessageBox* msgBox = new QMessageBox(); msgBox->setIcon( QMessageBox::Critical ); @@ -167,7 +167,7 @@ ViewManager::onInstallationFailed( const QString& message, const QString& detail msgBox->setInformativeText( text ); connect( msgBox, &QMessageBox::buttonClicked, qApp, &QApplication::quit ); - cLog() << "Calamares will quit when the dialog closes."; + cDebug() << "Calamares will quit when the dialog closes."; msgBox->show(); } diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index 91642f415..f80f4d48b 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -72,8 +72,7 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, if ( typeString.isEmpty() || intfString.isEmpty() ) { - cLog() << Q_FUNC_INFO << "bad module descriptor format" - << instanceId; + cError() << "Bad module descriptor format" << instanceId; return nullptr; } if ( ( typeString == "view" ) || ( typeString == "viewmodule" ) ) @@ -87,11 +86,11 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, #ifdef WITH_PYTHONQT m = new PythonQtViewModule(); #else - cLog() << "PythonQt modules are not supported in this version of Calamares."; + cError() << "PythonQt modules are not supported in this version of Calamares."; #endif } else - cLog() << "Bad interface" << intfString << "for module type" << typeString; + cError() << "Bad interface" << intfString << "for module type" << typeString; } else if ( typeString == "job" ) { @@ -108,18 +107,18 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, #ifdef WITH_PYTHON m = new PythonJobModule(); #else - cLog() << "Python modules are not supported in this version of Calamares."; + cError() << "Python modules are not supported in this version of Calamares."; #endif } else - cLog() << "Bad interface" << intfString << "for module type" << typeString; + cError() << "Bad interface" << intfString << "for module type" << typeString; } else - cLog() << "Bad module type" << typeString; + cError() << "Bad module type" << typeString; if ( !m ) { - cLog() << "Bad module type (" << typeString + cDebug() << "Bad module type (" << typeString << ") or interface string (" << intfString << ") for module " << instanceId; return nullptr; @@ -130,8 +129,8 @@ Module::fromDescriptor( const QVariantMap& moduleDescriptor, m->m_directory = moduleDir.absolutePath(); else { - cLog() << Q_FUNC_INFO << "bad module directory" - << instanceId; + cError() << "Bad module directory" << moduleDirectory + << "for" << instanceId; delete m; return nullptr; } diff --git a/src/modules/partition/core/PartitionModel.cpp b/src/modules/partition/core/PartitionModel.cpp index bf61843d0..0265da29d 100644 --- a/src/modules/partition/core/PartitionModel.cpp +++ b/src/modules/partition/core/PartitionModel.cpp @@ -115,7 +115,7 @@ PartitionModel::parent( const QModelIndex& child ) const return createIndex( row, 0, parentNode ); ++row; } - cLog() << "No parent found!"; + cWarning() << "No parent found!"; return QModelIndex(); } diff --git a/src/modules/users/SetHostNameJob.cpp b/src/modules/users/SetHostNameJob.cpp index 948f78d17..87c89c3b8 100644 --- a/src/modules/users/SetHostNameJob.cpp +++ b/src/modules/users/SetHostNameJob.cpp @@ -57,21 +57,21 @@ Calamares::JobResult SetHostNameJob::exec() if ( !gs || !gs->contains( "rootMountPoint" ) ) { - cLog() << "No rootMountPoint in global storage"; + cError() << "No rootMountPoint in global storage"; return Calamares::JobResult::error( tr( "Internal Error" ) ); } QString destDir = gs->value( "rootMountPoint" ).toString(); if ( !QDir( destDir ).exists() ) { - cLog() << "rootMountPoint points to a dir which does not exist"; + cError() << "rootMountPoint points to a dir which does not exist"; return Calamares::JobResult::error( tr( "Internal Error" ) ); } QFile hostfile( destDir + "/etc/hostname" ); if ( !hostfile.open( QFile::WriteOnly ) ) { - cLog() << "Can't write to hostname file"; + cError() << "Can't write to hostname file"; return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) ); } @@ -82,7 +82,7 @@ Calamares::JobResult SetHostNameJob::exec() QFile hostsfile( destDir + "/etc/hosts" ); if ( !hostsfile.open( QFile::WriteOnly ) ) { - cLog() << "Can't write to hosts file"; + cError() << "Can't write to hosts file"; return Calamares::JobResult::error( tr( "Cannot write hostname to target system" ) ); } diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/RequirementsChecker.cpp index 9ccdfae33..a5255058d 100644 --- a/src/modules/welcome/checker/RequirementsChecker.cpp +++ b/src/modules/welcome/checker/RequirementsChecker.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2017, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017-2018, Adriaan de Groot * Copyright 2017, Gabriel Craciunescu * * Calamares is free software: you can redistribute it and/or modify @@ -100,12 +100,14 @@ RequirementsChecker::RequirementsChecker( QObject* parent ) if ( m_entriesToCheck.contains( "root" ) ) isRoot = checkIsRoot(); + using TR = Logger::DebugRow; + cDebug() << "RequirementsChecker output:" - << " enoughStorage:" << enoughStorage - << " enoughRam:" << enoughRam - << " hasPower:" << hasPower - << " hasInternet:" << hasInternet - << " isRoot:" << isRoot; + << TR("enoughStorage", enoughStorage) + << TR("enoughRam", enoughRam) + << TR("hasPower", hasPower) + << TR("hasInternet", hasInternet) + << TR("isRoot", isRoot); QList< PrepareEntry > checkEntries; foreach ( const QString& entry, m_entriesToCheck ) @@ -305,7 +307,9 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } if ( incompleteConfiguration ) - cWarning() << "RequirementsChecker configuration map:\n" << configurationMap; + { + cWarning() << "RequirementsChecker configuration map:" << Logger::DebugMap( configurationMap ); + } }