From 219a440a9718a2bacbf34a8d08af6d2119af8d87 Mon Sep 17 00:00:00 2001 From: Michael Jackson Date: Wed, 8 Mar 2023 13:17:22 -0500 Subject: [PATCH] PipelineRunner: Add logging support to PipelineRunner. use the --logfile or -l [LOG FILE NAME] to log all output to a file. Signed-off-by: Michael Jackson --- Source/PipelineRunner/PipelineRunner.cpp | 92 ++++++++++++++++++++++-- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/Source/PipelineRunner/PipelineRunner.cpp b/Source/PipelineRunner/PipelineRunner.cpp index 2571d3eae..212f77ff0 100644 --- a/Source/PipelineRunner/PipelineRunner.cpp +++ b/Source/PipelineRunner/PipelineRunner.cpp @@ -38,6 +38,7 @@ #include // C++ Includes +#include #include // Qt Includes @@ -55,6 +56,7 @@ #include "SIMPLib/SIMPLib.h" #include "SIMPLib/SIMPLibVersion.h" #include "SIMPLib/Common/Constants.h" +// #include "SIMPLib/Common/LogFileObserver.h" #include "SIMPLib/FilterParameters/H5FilterParametersReader.h" #include "SIMPLib/FilterParameters/JsonFilterParametersReader.h" #include "SIMPLib/Filtering/FilterFactory.hpp" @@ -68,11 +70,42 @@ #include "SIMPLib/Python/PythonLoader.h" #endif -// ----------------------------------------------------------------------------- -// +QFile s_LogFile; +QTextStream s_LogStream(&s_LogFile); + +/** + * @brief MessageToLogFileHandler + * @param type + * @param msg + */ +void MessageToLogFileHandler(QtMsgType type, const QMessageLogContext&, const QString& msg) +{ + QString txt; + switch(type) + { + case QtDebugMsg: + txt = QString("Debug: %1").arg(msg); + break; + case QtWarningMsg: + txt = QString("Warning: %1").arg(msg); + break; + case QtCriticalMsg: + txt = QString("Critical: %1").arg(msg); + break; + case QtFatalMsg: + txt = QString("Fatal: %1").arg(msg); + break; + case QtInfoMsg: + txt = QString("Info: %1").arg(msg); + break; + } + s_LogStream << txt << "\n"; +} + // ----------------------------------------------------------------------------- int main(int argc, char* argv[]) { + #ifdef DREAM3D_ANACONDA { constexpr const char k_PYTHONHOME[] = "PYTHONHOME"; @@ -121,17 +154,52 @@ int main(int argc, char* argv[]) "Pipeline File as a JSON file.", "file"); parser.addOption(pipelineFileArg); + QCommandLineOption logFileOption(QStringList() << "l" + << "logfile", + "Save output to file", "log"); + parser.addOption(logFileOption); // Process the actual command line arguments given by the user parser.process(app); QString pipelineFile = parser.value(pipelineFileArg); + QString logFile = parser.value(logFileOption); - std::cout << "PipelineRunner " << SIMPLib::Version::PackageComplete().toStdString() << std::endl; - std::cout << "Input File: " << pipelineFile.toStdString() << std::endl; - + if(!logFile.isEmpty()) + { + s_LogFile.setFileName(logFile); + s_LogFile.open(QIODevice::WriteOnly | QIODevice::Truncate); + qInstallMessageHandler(MessageToLogFileHandler); + qDebug() << QDateTime::currentDateTime(); + } // Register all the filters including trying to load those from Plugins FilterManager* fm = FilterManager::Instance(); SIMPLibPluginLoader::LoadPluginFilters(fm); + if(!logFile.isEmpty()) + { + s_LogFile.close(); + } + + // Now hand off to the C++ streams for logging + std::ofstream logFileStream; + std::streambuf* stdCoutBuf = std::cout.rdbuf(); + + if(!logFile.isEmpty()) + { + logFileStream.open(logFile.toStdString(), std::ios_base::out | std::ios_base::app); + if(!logFileStream.is_open()) + { + std::cout << "Error opening log file '" << logFile.toStdString() << "'" << std::endl; + return 1; + } + std::cout.rdbuf(logFileStream.rdbuf()); + } + + std::cout << "PipelineRunner " << SIMPLib::Version::PackageComplete().toStdString() << std::endl; + std::cout << "Input File: " << pipelineFile.toStdString() << std::endl; + if(!logFile.isEmpty()) + { + std::cout << "Log File: " << logFile.toStdString() << std::endl; + } #ifdef SIMPL_EMBED_PYTHON if(hasPythonHome) @@ -207,7 +275,16 @@ int main(int argc, char* argv[]) std::cout << "Pipeline Count: " << pipeline->size() << std::endl; Observer obs; // Create an Observer to report errors/progress from the executing pipeline - pipeline->addMessageReceiver(&obs); + + // if(logFile.isEmpty()) + { + pipeline->addMessageReceiver(&obs); + } + // else + // { + // pipeline->addMessageReceiver(logFileObserver); + // } + // Preflight the pipeline int err = -1; try @@ -241,5 +318,8 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } + // Return std::cout back to normal + std::cout.rdbuf(stdCoutBuf); + return EXIT_SUCCESS; }