From 278a55b031be999fdecb3696e1bf5d02a7b1b23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Cerveau?= Date: Tue, 17 Oct 2017 22:50:43 +0200 Subject: [PATCH] Enhance logger to comply with GST --- src/ElementProperties.cpp | 6 +-- src/GraphDisplay.cpp | 6 +-- src/Logger.cpp | 85 ++++++++++++++++++++++++++++++++++++++- src/Logger.h | 42 ++++++++++++++++++- src/MainWindow.cpp | 12 +++--- src/PipelineIE.cpp | 11 ++--- src/PluginsList.cpp | 18 ++++----- 7 files changed, 149 insertions(+), 31 deletions(-) diff --git a/src/ElementProperties.cpp b/src/ElementProperties.cpp index e530ef9..18fab7d 100644 --- a/src/ElementProperties.cpp +++ b/src/ElementProperties.cpp @@ -187,7 +187,7 @@ ElementProperties::addParamSimple (GParamSpec *param, GstElement *element, default: { skip = true; - LOG_INFO("property " + propertyName + " not supported"); + LOG_INFO("property %s not supported", propertyName.toStdString ().c_str ()); break; } }; @@ -282,7 +282,7 @@ ElementProperties::applyClicked () G_OBJECT_GET_CLASS (element), itr.key ().toStdString ().c_str ()); if (!param) { - LOG_INFO("problem with setting " + itr.key () + " property"); + LOG_INFO("problem with setting %s property", itr.key ().toStdString ().c_str ()); continue; } @@ -372,7 +372,7 @@ ElementProperties::applyClicked () break; } default: { - LOG_INFO("property " + itr.key () + " not supported"); + LOG_INFO("property %s not supported", itr.key ()); break; } }; diff --git a/src/GraphDisplay.cpp b/src/GraphDisplay.cpp index cf60a46..f647cb1 100644 --- a/src/GraphDisplay.cpp +++ b/src/GraphDisplay.cpp @@ -364,8 +364,7 @@ GraphDisplay::mouseReleaseEvent (QMouseEvent *event) assert(srcPad != NULL && dstPad != NULL); - LOG_INFO("Connection from " + QString(infoSrc.m_name.c_str ()) + ":" - + srcPad + " to " + QString(infoDst.m_name.c_str ()) + ":" + dstPad); + LOG_INFO("Connection from %s:%s to %s:%s", infoSrc.m_name.c_str (), srcPad, infoDst.m_name.c_str (), dstPad); if (!m_pGraph->Connect (infoSrc.m_name.c_str (), srcPad, infoDst.m_name.c_str (), dstPad)) { @@ -767,8 +766,7 @@ GraphDisplay::disconnect (size_t elementId, size_t padId) } } - LOG_INFO("Disconnect " + QString(src.c_str ()) + ":" + srcPad.c_str() - + " <-> " + dst.c_str () + ":" + dstPad.c_str ()); + LOG_INFO("Disconnect %s:%s <-> %s,%s", src.c_str (), srcPad.c_str(), dst.c_str (), dstPad.c_str ()); if (src.empty () || dst.empty () || srcPad.empty () || dstPad.empty ()) return; diff --git a/src/Logger.cpp b/src/Logger.cpp index bcfc220..e46a5f6 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -11,6 +11,19 @@ #include #include +#include +#include +#include +#include +#include +#include + +G_LOCK_DEFINE_STATIC(logger); + +static long int getThreadID() { + return syscall(SYS_gettid); +} + void Logger::configure_logger () { @@ -22,7 +35,8 @@ Logger::configure_logger () Logger::Logger() : QThread(), -m_fExit(false) +m_fExit(false), +m_level(MAX_LOG_LEVEL) { } @@ -38,6 +52,75 @@ void Logger::Quit() wait(); } +void Logger::createLog(TimeStampFlag flag, const char* format, ...) +{ + // first check if we should add the timestamp before the string + char* new_fmt = NULL; + if (flag == Logger::UseTimeStamp) { + const char* fmt_template = "%02d:%02d:%02d:%06ld %d 0x%x %s"; + struct timeval tv; + struct timezone tz; + struct tm t; + gettimeofday(&tv, &tz); + localtime_r(&(tv.tv_sec), &t); + int len = snprintf(NULL, 0, fmt_template, t.tm_hour,t.tm_min,t.tm_sec, tv.tv_usec, getThreadID(), std::this_thread::get_id(), format); + if (len < 0) { + // cannot parse the string + return; + } + len++; // add 1 byte for the additional terminating null character + new_fmt = static_cast(malloc(sizeof(char) * len)); + snprintf(new_fmt, len, fmt_template, t.tm_hour,t.tm_min,t.tm_sec, tv.tv_usec, getThreadID(), std::this_thread::get_id(), format); + } + + // create the actual string (timestamp + format...) + const char* formatString = new_fmt ? new_fmt : format; + assert(formatString); + + va_list aptr; + va_start(aptr, format); + va_list argcopy; // copy the va_list and use vsnprintf to get the length of the final string + va_copy(argcopy, aptr); + int len = vsnprintf(NULL, 0, formatString , argcopy); + va_end(argcopy); + if (len < 0) { + // cannot parse the string + g_free(new_fmt); + va_end(aptr); + return; + } + + len++; // add 1 byte for the additional terminating null character. + char* buffer = static_cast(malloc(sizeof(char) * len)); + int actualLen = vsprintf(buffer, formatString, aptr); + va_end(aptr); + formatString = 0; + g_free (new_fmt); + if (actualLen < 0) { + g_free (buffer); + return; + } + // if lengths are different, our code is bugged + assert((actualLen + 1) == len); + + // dump the final string + G_LOCK(logger); + processLog(buffer); + G_UNLOCK(logger); + + // free the buffer and flush the logs + g_free(buffer); +} + +void Logger::incrementLogLevel() { + m_level++; + if (m_level > MAX_LOG_LEVEL) + m_level = MAX_LOG_LEVEL; + char buffer[32]; + sprintf(buffer,"logger log level %d\n",m_level); + processLog(buffer); +} + void Logger::processLog(const QString& line) { emit sendLog(line,eLOG_CATEGORY_INTERNAL); diff --git a/src/Logger.h b/src/Logger.h index 64d4183..3590427 100644 --- a/src/Logger.h +++ b/src/Logger.h @@ -17,11 +17,25 @@ enum eLogCategory { eLOG_CATEGORY_EVENTS, }; -#define LOG_INFO(x) Logger::instance().processLog(x) +#ifndef LOG_LEVEL +# define LOG_LEVEL 1 +#endif + +#define MAX_LOG_LEVEL 3 + +#ifndef CLASS_LOGGER_TAG +# define CLASS_LOGGER_TAG __BASE_FILE__ +#endif + class Logger : public QThread { Q_OBJECT public: + enum TimeStampFlag { + UseTimeStamp = 0, + NoTimeStamp, + }; + Logger(); void configure_logger(); @@ -29,6 +43,9 @@ public: void Quit(); void processLog(const QString& line); + void createLog(Logger::TimeStampFlag, const char* format, ...); + int getLevel() const { return m_level; } + void incrementLogLevel(); protected: void processGstLog(gchar* line); @@ -41,6 +58,29 @@ signals: private: void run(); bool m_fExit; + int m_level; }; +#define log_debug(LEVEL,TYPE,FMT, ARGS...) do { \ + if (LEVEL <= Logger::instance().getLevel()) \ + Logger::instance().createLog(Logger::UseTimeStamp, "" TYPE ": " FMT "", ## ARGS); \ + } while (0) +#define log_debug_no_time_stderr(LEVEL,TYPE,FMT, ARGS...) do { \ + Logger::instance().createLog(Logger::NoTimeStamp, "" FMT "", ## ARGS); \ + } while (0) + +#define LOG_IMPORTANT(FMT, ARGS...) log_debug_no_time_stderr(0, "",FMT ,## ARGS) + +#ifndef DISABLE_LOG +# define LOG_ERROR(FMT, ARGS...) log_debug(0, "ERROR\t" CLASS_LOGGER_TAG ":%d:%s", FMT,__LINE__, __func__, ## ARGS) +# define LOG_WARNING(FMT, ARGS...) log_debug(1, "WARN\t" CLASS_LOGGER_TAG ":%d:%s", FMT, __LINE__, __func__, ## ARGS) +# define LOG_INFO(FMT, ARGS...) log_debug(2, "INFO\t" CLASS_LOGGER_TAG ":%d:%s", FMT, __LINE__, __func__, ## ARGS) +# define LOG_DEBUG(FMT, ARGS...) log_debug(3, "DEBUG\t" CLASS_LOGGER_TAG ":%d:%s", FMT, __LINE__, __func__, ## ARGS) +#else +# define LOG_ERROR(FMT, ARGS...) +# define LOG_WARNING(FMT, ARGS...) +# define LOG_INFO(FMT, ARGS...) +# define LOG_DEBUG(FMT, ARGS...) +#endif + #endif /* LOGGER_H_ */ diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 061404f..30c30b1 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -231,13 +231,13 @@ void MainWindow::RemovePluginToFavorites(const QString& plugin_name) void MainWindow::onFavoriteListItemDoubleClicked(QListWidgetItem* pitem) { - LOG_INFO("onFavoriteListItemDoubleClicked: " + pitem->text()); + LOG_INFO("onFavoriteListItemDoubleClicked: %s", pitem->text().toStdString ().c_str ()); if (!m_pGraph || !m_pGraph->AddPlugin (pitem->text ().toStdString ().c_str (), NULL)) { QMessageBox::warning ( this, "Plugin addition problem", "Plugin `" + pitem->text () + "` insertion was FAILED"); - LOG_INFO("Plugin `" + pitem->text () + "` insertion FAILED"); + LOG_INFO("Plugin '%s' insertion FAILED", pitem->text ().toStdString ().c_str ()); return; } } @@ -249,7 +249,7 @@ void MainWindow::ProvideContextMenu(const QPoint &pos) submenu.addAction("Delete"); QAction* rightClickItem = submenu.exec(item); if (rightClickItem && rightClickItem->text().contains("Delete") ) { - LOG_INFO("Delete item: " + m_favoriteList->currentItem()->text()); + LOG_INFO("Delete item: %s", m_favoriteList->currentItem()->text().toStdString ().c_str ()); RemovePluginToFavorites(m_favoriteList->currentItem()->text()); } } @@ -303,7 +303,7 @@ MainWindow::OpenMediaFile () if (!path.isEmpty ()) { gchar *uri = gst_filename_to_uri (path.toStdString ().c_str (), NULL); if (uri) { - LOG_INFO("Open Source file: " + path); + LOG_INFO("Open Source file: %s", path.toStdString ().c_str ()); m_pGraph->OpenUri (uri, NULL); g_free (uri); @@ -323,7 +323,7 @@ MainWindow::OpenMediaUri () QString uri = QInputDialog::getText (this, "Open Uri...", "Uri:"); if (!uri.isEmpty ()) { - LOG_INFO("Open uri: "+ uri); + LOG_INFO("Open uri: %s", uri.toStdString ().c_str ()); m_pGraph->OpenUri (uri.toStdString ().c_str (), NULL); std::vector info = m_pGraph->GetInfo (); @@ -380,7 +380,7 @@ void MainWindow::Seek (int val) { if (m_pGraph->SetPosition ((double) (val) / m_pslider->maximum ())) - LOG_INFO("Seek to" + val); + LOG_INFO("Seek to %d", val); else LOG_INFO("Seek FAILED"); } diff --git a/src/PipelineIE.cpp b/src/PipelineIE.cpp index 88001a3..9bc2d6d 100644 --- a/src/PipelineIE.cpp +++ b/src/PipelineIE.cpp @@ -141,8 +141,7 @@ writeProperties (QXmlStreamWriter &xmlWriter, const GstElement *element) } default: { gchar *elementName = gst_element_get_name (element); - LOG_INFO(QString("property `" + propertyName + "` for `" - + elementName + "` not supported")); + LOG_INFO("property `%s` for `%s` not supported", propertyName.toStdString ().c_str (), elementName); g_free (elementName); skip = true; @@ -181,8 +180,7 @@ loadProperties (QDomElement node, GstElement *element) if (!param) { gchar *elementName = gst_element_get_name (element); - LOG_INFO(QString("problem with setting property `" + name + "` for `" - + elementName + "`")); + LOG_INFO("problem with setting property `%s` for `%s`", name.toStdString ().c_str (), elementName); g_free (elementName); continue; } @@ -245,8 +243,7 @@ loadProperties (QDomElement node, GstElement *element) } default: { gchar *elementName = gst_element_get_name (element); - LOG_INFO(QString("property `" + name + "` for `" - + QString (elementName) + "` not supported")); + LOG_INFO("property `%s` for `%s` not supported", propName, elementName); g_free (elementName); break; } @@ -328,7 +325,7 @@ PipelineIE::Export (QSharedPointer pgraph, GST_PAD_TEMPLATE_NAME_TEMPLATE (templ)); } else { - LOG_INFO(QString("Unable to find a template for") + QString(info[i].m_pads[j].m_name.c_str())); + LOG_INFO("Unable to find a template for %s", info[i].m_pads[j].m_name.c_str()); xmlWriter.writeAttribute ("presence", "always"); xmlWriter.writeAttribute ("template-name", ""); } diff --git a/src/PluginsList.cpp b/src/PluginsList.cpp index 8779424..b686d9a 100644 --- a/src/PluginsList.cpp +++ b/src/PluginsList.cpp @@ -20,7 +20,7 @@ plugins_sort_cb (gconstpointer a, gconstpointer b) { Plugin* p1 = (Plugin*) a; Plugin* p2 = (Plugin*) b; - LOG_INFO("Sort p1: " + p1->getName () + " and p2: " + p2->getName ()); + LOG_INFO("Sort p1: %s and p2: ", p1->getName ().toStdString ().c_str (),p2->getName ().toStdString ().c_str ()); if (p1->getRank () > p2->getRank ()) return 1; else if (p1->getRank () == p2->getRank ()) { @@ -193,7 +193,7 @@ PluginsListDialog::showInfo (QListWidgetItem *pitem, QListWidgetItem *previous) { Q_UNUSED(previous); - LOG_INFO("Show Info: " + pitem->text ()); + LOG_INFO("Show Info: %s", pitem->text ().toStdString ().c_str ()); m_plblInfo->clear (); QString descr; descr += "Plugin details
"; @@ -206,14 +206,14 @@ PluginsListDialog::showInfo (QListWidgetItem *pitem, QListWidgetItem *previous) GstElementFactory *factory = gst_element_factory_find ( pitem->text ().toStdString ().c_str ()); if (!factory) { - LOG_INFO("warning: " + pitem->text () + " Not Found"); + LOG_INFO("warning: %s not found",pitem->text ().toStdString ().c_str ()); return; } factory = GST_ELEMENT_FACTORY ( gst_plugin_feature_load (GST_PLUGIN_FEATURE (factory))); if (!factory) { - LOG_INFO("warning: " + pitem->text () + " Not Found"); + LOG_INFO("warning: %s not found",pitem->text ().toStdString ().c_str ()); return; } #if GST_VERSION_MAJOR >= 1 @@ -226,7 +226,7 @@ PluginsListDialog::showInfo (QListWidgetItem *pitem, QListWidgetItem *previous) GstPlugin* plugin = gst_default_registry_find_plugin (plugin_name); #endif if (!plugin) { - LOG_INFO("warning: " + pitem->text () + " Not Found"); + LOG_INFO("warning: %s not found",pitem->text ().toStdString ().c_str ()); return; } @@ -286,14 +286,14 @@ PluginsListDialog::insert (QListWidgetItem *pitem) LOG_INFO("Do not insert null item"); return; } - LOG_INFO("Insert: " + pitem->text ()); + LOG_INFO("Insert: %s", pitem->text ().toStdString ().c_str ()); if (!m_pGraph || !m_pGraph->AddPlugin (pitem->text ().toStdString ().c_str (), NULL)) { QMessageBox::warning ( this, "Plugin addition problem", "Plugin `" + pitem->text () + "` insertion was FAILED"); - LOG_INFO("Plugin `" + pitem->text () + "` insertion FAILED"); + LOG_INFO("Plugin `%s insertion FAILED", pitem->text ().toStdString ().c_str ()); return; } } @@ -375,10 +375,10 @@ void PluginsListDialog::ProvideContextMenu(const QPoint &pos) QAction* rightClickItem = submenu.exec(item); if (rightClickItem) { if(rightClickItem->text().contains("Add to favorites") ) { - LOG_INFO("Delete item: " + current_item->text()); + LOG_INFO("Add item: %s", current_item->text().toStdString ().c_str ()); emit signalAddPluginToFav (current_item->text ()); } else if(rightClickItem->text().contains("Remove from favorites") ) { - LOG_INFO("Delete item: " + current_item->text()); + LOG_INFO("Delete item: %s", current_item->text().toStdString ().c_str ()); emit signalRemPluginToFav (current_item->text ()); } }