[{"id":2393,"web_url":"https://patchwork.libcamera.org/comment/2393/","msgid":"<20190812151803.GG5006@pendragon.ideasonboard.com>","date":"2019-08-12T15:18:03","subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Jacopo,\n\nThank you for the patch.\n\nOn Mon, Aug 12, 2019 at 02:49:19PM +0200, Jacopo Mondi wrote:\n> Add the function name to the log tag.\n> \n> With this patch applied, the log format looks like:\n> INFO Camera camera_manager.cpp - start():83 libcamera v0.0.0+655-ddf32590\n\nI think I would prefer keeping the line number associated with the file:\n\nINFO Camera camera_manager.cpp:83 - start() libcamera v0.0.0+655-ddf32590\n\nor maybe\n\nINFO Camera start() (camera_manager.cpp:83) libcamera v0.0.0+655-ddf32590\n\n?\n\nI'm a bit bothered by the missing class name to be honest, as it makes\nthe function name less useful without the context. The filename helps,\nbut then does the function name alone bring much added value ? What's\neverybody's experience when reading logs, would the function name alone\nimprove readability even if it increases the length of the lines ?\n\n> Compared to:\n> INFO Camera camera_manager.cpp:83 libcamera v0.0.0+654-a6799dc5\n> \n> Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> ---\n>  src/libcamera/include/log.h | 19 +++++++++---------\n>  src/libcamera/log.cpp       | 40 ++++++++++++++++++++++---------------\n>  2 files changed, 34 insertions(+), 25 deletions(-)\n> \n> diff --git a/src/libcamera/include/log.h b/src/libcamera/include/log.h\n> index 9b203f97e304..e65d20af1ca9 100644\n> --- a/src/libcamera/include/log.h\n> +++ b/src/libcamera/include/log.h\n> @@ -50,9 +50,9 @@ const LogCategory &_LOG_CATEGORY(name)()\t\t\t\t\\\n>  class LogMessage\n>  {\n>  public:\n> -\tLogMessage(const char *fileName, unsigned int line,\n> +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n\nShould we name the new parameter funcName to match fileName ? Or rename\nfileName to file ?\n\nI would prefer keeping the file name and line number grouped, and thus\nadding the func parameter either as the first parameter of the function,\nor as the third one.\n\nSame comments for all other functions or macros.\n\n>  \t\t   LogSeverity severity);\n> -\tLogMessage(const char *fileName, unsigned int line,\n> +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n>  \t\t   const LogCategory &category, LogSeverity severity);\n>  \tLogMessage(const LogMessage &) = delete;\n>  \tLogMessage(LogMessage &&);\n> @@ -67,7 +67,7 @@ public:\n>  \tconst std::string msg() const { return msgStream_.str(); }\n>  \n>  private:\n> -\tvoid init(const char *fileName, unsigned int line);\n> +\tvoid init(const char *fileName, const char* func, unsigned int line);\n>  \n>  \tstd::ostringstream msgStream_;\n>  \tconst LogCategory &category_;\n> @@ -84,24 +84,25 @@ public:\n>  protected:\n>  \tvirtual std::string logPrefix() const = 0;\n>  \n> -\tLogMessage _log(const char *file, unsigned int line,\n> +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n>  \t\t\tLogSeverity severity) const;\n> -\tLogMessage _log(const char *file, unsigned int line,\n> +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n>  \t\t\tconst LogCategory &category,\n>  \t\t\tLogSeverity severity) const;\n>  };\n>  \n> -LogMessage _log(const char *file, unsigned int line, LogSeverity severity);\n> -LogMessage _log(const char *file, unsigned int line,\n> +LogMessage _log(const char *file, const char *func, unsigned int line,\n> +\t\tLogSeverity severity);\n> +LogMessage _log(const char *file, const char *func, unsigned int line,\n>  \t\tconst LogCategory &category, LogSeverity severity);\n>  \n>  #ifndef __DOXYGEN__\n>  #define _LOG_CATEGORY(name) logCategory##name\n>  \n>  #define _LOG1(severity) \\\n> -\t_log(__FILE__, __LINE__, Log##severity).stream()\n> +\t_log(__FILE__, __func__, __LINE__, Log##severity).stream()\n>  #define _LOG2(category, severity) \\\n> -\t_log(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> +\t_log(__FILE__, __func__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n>  \n>  /*\n>   * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of\n> diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp\n> index 91f7c3ee5157..fa9a16452f25 100644\n> --- a/src/libcamera/log.cpp\n> +++ b/src/libcamera/log.cpp\n> @@ -720,6 +720,7 @@ const LogCategory &LogCategory::defaultCategory()\n>  /**\n>   * \\brief Construct a log message for the default category\n>   * \\param[in] fileName The file name where the message is logged from\n> + * \\param[in] func The function name where the message is logged from\n>   * \\param[in] line The line number where the message is logged from\n>   * \\param[in] severity The log message severity, controlling how the message\n>   * will be displayed\n> @@ -728,16 +729,17 @@ const LogCategory &LogCategory::defaultCategory()\n>   * \\a severity argument sets the message severity to control whether it will be\n>   * output or dropped.\n>   */\n> -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> +LogMessage::LogMessage(const char *fileName, const char *func ,unsigned int line,\n>  \t\t       LogSeverity severity)\n>  \t: category_(LogCategory::defaultCategory()), severity_(severity)\n>  {\n> -\tinit(fileName, line);\n> +\tinit(fileName, func, line);\n>  }\n>  \n>  /**\n>   * \\brief Construct a log message for a given category\n>   * \\param[in] fileName The file name where the message is logged from\n> + * \\param[in] func The function name where the message is logged from\n>   * \\param[in] line The line number where the message is logged from\n>   * \\param[in] category The log message category, controlling how the message\n>   * will be displayed\n> @@ -748,11 +750,11 @@ LogMessage::LogMessage(const char *fileName, unsigned int line,\n>   * \\a severity argument sets the message severity to control whether it will be\n>   * output or dropped.\n>   */\n> -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> +LogMessage::LogMessage(const char *fileName, const char *func, unsigned int line,\n>  \t\t       const LogCategory &category, LogSeverity severity)\n>  \t: category_(category), severity_(severity)\n>  {\n> -\tinit(fileName, line);\n> +\tinit(fileName, func, line);\n>  }\n>  \n>  /**\n> @@ -774,13 +776,14 @@ LogMessage::LogMessage(LogMessage &&other)\n>  \tother.severity_ = LogInvalid;\n>  }\n>  \n> -void LogMessage::init(const char *fileName, unsigned int line)\n> +void LogMessage::init(const char *fileName, const char *func, unsigned int line)\n>  {\n>  \t/* Log the timestamp, severity and file information. */\n>  \tclock_gettime(CLOCK_MONOTONIC, &timestamp_);\n>  \n>  \tstd::ostringstream ossFileInfo;\n> -\tossFileInfo << utils::basename(fileName) << \":\" << line;\n> +\tossFileInfo << utils::basename(fileName) << \" - \"\n> +\t\t    << func << \"():\" << line;\n>  \tfileInfo_ = ossFileInfo.str();\n>  }\n>  \n> @@ -868,6 +871,7 @@ Loggable::~Loggable()\n>  /**\n>   * \\brief Create a temporary LogMessage object to log a message\n>   * \\param[in] fileName The file name where the message is logged from\n> + * \\param[in] func The function name where the message is logged from\n>   * \\param[in] line The line number where the message is logged from\n>   * \\param[in] severity The log message severity\n>   *\n> @@ -876,10 +880,10 @@ Loggable::~Loggable()\n>   *\n>   * \\return A log message\n>   */\n> -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> -\t\t\t  LogSeverity severity) const\n> +LogMessage Loggable::_log(const char *fileName, const char *func,\n> +\t\t\t  unsigned int line, LogSeverity severity) const\n>  {\n> -\tLogMessage msg(fileName, line, severity);\n> +\tLogMessage msg(fileName, func, line, severity);\n>  \n>  \tmsg.stream() << logPrefix() << \": \";\n>  \treturn msg;\n> @@ -888,6 +892,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n>  /**\n>   * \\brief Create a temporary LogMessage object to log a message\n>   * \\param[in] fileName The file name where the message is logged from\n> + * \\param[in] func The function name where the message is logged from\n>   * \\param[in] line The line number where the message is logged from\n>   * \\param[in] category The log message category\n>   * \\param[in] severity The log message severity\n> @@ -897,11 +902,11 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n>   *\n>   * \\return A log message\n>   */\n> -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> -\t\t\t  const LogCategory &category,\n> +LogMessage Loggable::_log(const char *fileName, const char *func,\n> +\t\t\t  unsigned int line, const LogCategory &category,\n>  \t\t\t  LogSeverity severity) const\n>  {\n> -\tLogMessage msg(fileName, line, category, severity);\n> +\tLogMessage msg(fileName, func, line, category, severity);\n>  \n>  \tmsg.stream() << logPrefix() << \": \";\n>  \treturn msg;\n> @@ -910,6 +915,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n>  /**\n>   * \\brief Create a temporary LogMessage object to log a message\n>   * \\param[in] fileName The file name where the message is logged from\n> + * \\param[in] func The function name where the message is logged from\n>   * \\param[in] line The line number where the message is logged from\n>   * \\param[in] severity The log message severity\n>   *\n> @@ -918,14 +924,16 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n>   *\n>   * \\return A log message\n>   */\n> -LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> +LogMessage _log(const char *fileName, const char *func,\n> +\t\tunsigned int line, LogSeverity severity)\n>  {\n> -\treturn LogMessage(fileName, line, severity);\n> +\treturn LogMessage(fileName, func, line, severity);\n>  }\n>  \n>  /**\n>   * \\brief Create a temporary LogMessage object to log a message\n>   * \\param[in] fileName The file name where the message is logged from\n> + * \\param[in] func The function name where the message is logged from\n>   * \\param[in] line The line number where the message is logged from\n>   * \\param[in] category The log message category\n>   * \\param[in] severity The log message severity\n> @@ -935,10 +943,10 @@ LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n>   *\n>   * \\return A log message\n>   */\n> -LogMessage _log(const char *fileName, unsigned int line,\n> +LogMessage _log(const char *fileName, const char *func, unsigned int line,\n>  \t\tconst LogCategory &category, LogSeverity severity)\n>  {\n> -\treturn LogMessage(fileName, line, category, severity);\n> +\treturn LogMessage(fileName, func, line, category, severity);\n>  }\n>  \n>  /**","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 93EBC6161B\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tMon, 12 Aug 2019 17:18:06 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id E63CE327;\n\tMon, 12 Aug 2019 17:18:05 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1565623086;\n\tbh=SYoIfGUriNfAy0sYSL+KKXKoQpxsdVn26vjDRqaN39U=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=GZBAgkZUyFqheVaZtwqtUsEv+C9DLk23/S3Gt/9GQ1VS3YAn+aricaOdy/NDEeh/7\n\totDRkCAZMWm61Qw5GVtAyVYSntzEq1jVak4mslOGcqyUKfapzRQQXg1DihFrM/CkBN\n\tBC5oyuCzHxsrU7YTbBEa8Wop58wrpX/4R11gH018=","Date":"Mon, 12 Aug 2019 18:18:03 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190812151803.GG5006@pendragon.ideasonboard.com>","References":"<20190812124919.736-1-jacopo@jmondi.org>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20190812124919.736-1-jacopo@jmondi.org>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Mon, 12 Aug 2019 15:18:06 -0000"}},{"id":2423,"web_url":"https://patchwork.libcamera.org/comment/2423/","msgid":"<20190817134556.GA16603@wyvern>","date":"2019-08-17T13:45:56","subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Jacopo, Laurent,\n\nOn 2019-08-12 18:18:03 +0300, Laurent Pinchart wrote:\n> Hi Jacopo,\n> \n> Thank you for the patch.\n> \n> On Mon, Aug 12, 2019 at 02:49:19PM +0200, Jacopo Mondi wrote:\n> > Add the function name to the log tag.\n> > \n> > With this patch applied, the log format looks like:\n> > INFO Camera camera_manager.cpp - start():83 libcamera v0.0.0+655-ddf32590\n> \n> I think I would prefer keeping the line number associated with the file:\n> \n> INFO Camera camera_manager.cpp:83 - start() libcamera v0.0.0+655-ddf32590\n\nI agree with Laurent here, I like to line number to be kept together \nwith the file name.\n\n> \n> or maybe\n> \n> INFO Camera start() (camera_manager.cpp:83) libcamera v0.0.0+655-ddf32590\n> \n> ?\n> \n> I'm a bit bothered by the missing class name to be honest, as it makes\n> the function name less useful without the context. The filename helps,\n> but then does the function name alone bring much added value ? What's\n> everybody's experience when reading logs, would the function name alone\n> improve readability even if it increases the length of the lines ?\n\nI must admit when I read logs from C++ I only look at the file.cpp:line \nmarking and ignore the function name as without the class name it's not \nso useful for me. I'm not bothered by it being in the output and I have \nlittle concern about the length of the log lines, provided the file+line \ninformation is early enough on the line.\n\nThat being said and to add to the bikesheeding, if the function name is \nto be printed I think it could be useful to print it in its class \ncontext.  My suggested log line would be something like:\n\nINFO Camera camera_manager.cpp:83 CameraManager::start(): libcamera v0.0.0+655-ddf32590\n\nI do not (yet) find the Log categories super useful so I would be open \nto discuss dropping them, but then again I'm not bothered by them and \nmaybe they can be useful for log filtering going forward.\n\n> \n> > Compared to:\n> > INFO Camera camera_manager.cpp:83 libcamera v0.0.0+654-a6799dc5\n> > \n> > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > ---\n> >  src/libcamera/include/log.h | 19 +++++++++---------\n> >  src/libcamera/log.cpp       | 40 ++++++++++++++++++++++---------------\n> >  2 files changed, 34 insertions(+), 25 deletions(-)\n> > \n> > diff --git a/src/libcamera/include/log.h b/src/libcamera/include/log.h\n> > index 9b203f97e304..e65d20af1ca9 100644\n> > --- a/src/libcamera/include/log.h\n> > +++ b/src/libcamera/include/log.h\n> > @@ -50,9 +50,9 @@ const LogCategory &_LOG_CATEGORY(name)()\t\t\t\t\\\n> >  class LogMessage\n> >  {\n> >  public:\n> > -\tLogMessage(const char *fileName, unsigned int line,\n> > +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n> \n> Should we name the new parameter funcName to match fileName ? Or rename\n> fileName to file ?\n> \n> I would prefer keeping the file name and line number grouped, and thus\n> adding the func parameter either as the first parameter of the function,\n> or as the third one.\n> \n> Same comments for all other functions or macros.\n> \n> >  \t\t   LogSeverity severity);\n> > -\tLogMessage(const char *fileName, unsigned int line,\n> > +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n> >  \t\t   const LogCategory &category, LogSeverity severity);\n> >  \tLogMessage(const LogMessage &) = delete;\n> >  \tLogMessage(LogMessage &&);\n> > @@ -67,7 +67,7 @@ public:\n> >  \tconst std::string msg() const { return msgStream_.str(); }\n> >  \n> >  private:\n> > -\tvoid init(const char *fileName, unsigned int line);\n> > +\tvoid init(const char *fileName, const char* func, unsigned int line);\n> >  \n> >  \tstd::ostringstream msgStream_;\n> >  \tconst LogCategory &category_;\n> > @@ -84,24 +84,25 @@ public:\n> >  protected:\n> >  \tvirtual std::string logPrefix() const = 0;\n> >  \n> > -\tLogMessage _log(const char *file, unsigned int line,\n> > +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n> >  \t\t\tLogSeverity severity) const;\n> > -\tLogMessage _log(const char *file, unsigned int line,\n> > +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n> >  \t\t\tconst LogCategory &category,\n> >  \t\t\tLogSeverity severity) const;\n> >  };\n> >  \n> > -LogMessage _log(const char *file, unsigned int line, LogSeverity severity);\n> > -LogMessage _log(const char *file, unsigned int line,\n> > +LogMessage _log(const char *file, const char *func, unsigned int line,\n> > +\t\tLogSeverity severity);\n> > +LogMessage _log(const char *file, const char *func, unsigned int line,\n> >  \t\tconst LogCategory &category, LogSeverity severity);\n> >  \n> >  #ifndef __DOXYGEN__\n> >  #define _LOG_CATEGORY(name) logCategory##name\n> >  \n> >  #define _LOG1(severity) \\\n> > -\t_log(__FILE__, __LINE__, Log##severity).stream()\n> > +\t_log(__FILE__, __func__, __LINE__, Log##severity).stream()\n> >  #define _LOG2(category, severity) \\\n> > -\t_log(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> > +\t_log(__FILE__, __func__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> >  \n> >  /*\n> >   * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of\n> > diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp\n> > index 91f7c3ee5157..fa9a16452f25 100644\n> > --- a/src/libcamera/log.cpp\n> > +++ b/src/libcamera/log.cpp\n> > @@ -720,6 +720,7 @@ const LogCategory &LogCategory::defaultCategory()\n> >  /**\n> >   * \\brief Construct a log message for the default category\n> >   * \\param[in] fileName The file name where the message is logged from\n> > + * \\param[in] func The function name where the message is logged from\n> >   * \\param[in] line The line number where the message is logged from\n> >   * \\param[in] severity The log message severity, controlling how the message\n> >   * will be displayed\n> > @@ -728,16 +729,17 @@ const LogCategory &LogCategory::defaultCategory()\n> >   * \\a severity argument sets the message severity to control whether it will be\n> >   * output or dropped.\n> >   */\n> > -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > +LogMessage::LogMessage(const char *fileName, const char *func ,unsigned int line,\n> >  \t\t       LogSeverity severity)\n> >  \t: category_(LogCategory::defaultCategory()), severity_(severity)\n> >  {\n> > -\tinit(fileName, line);\n> > +\tinit(fileName, func, line);\n> >  }\n> >  \n> >  /**\n> >   * \\brief Construct a log message for a given category\n> >   * \\param[in] fileName The file name where the message is logged from\n> > + * \\param[in] func The function name where the message is logged from\n> >   * \\param[in] line The line number where the message is logged from\n> >   * \\param[in] category The log message category, controlling how the message\n> >   * will be displayed\n> > @@ -748,11 +750,11 @@ LogMessage::LogMessage(const char *fileName, unsigned int line,\n> >   * \\a severity argument sets the message severity to control whether it will be\n> >   * output or dropped.\n> >   */\n> > -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > +LogMessage::LogMessage(const char *fileName, const char *func, unsigned int line,\n> >  \t\t       const LogCategory &category, LogSeverity severity)\n> >  \t: category_(category), severity_(severity)\n> >  {\n> > -\tinit(fileName, line);\n> > +\tinit(fileName, func, line);\n> >  }\n> >  \n> >  /**\n> > @@ -774,13 +776,14 @@ LogMessage::LogMessage(LogMessage &&other)\n> >  \tother.severity_ = LogInvalid;\n> >  }\n> >  \n> > -void LogMessage::init(const char *fileName, unsigned int line)\n> > +void LogMessage::init(const char *fileName, const char *func, unsigned int line)\n> >  {\n> >  \t/* Log the timestamp, severity and file information. */\n> >  \tclock_gettime(CLOCK_MONOTONIC, &timestamp_);\n> >  \n> >  \tstd::ostringstream ossFileInfo;\n> > -\tossFileInfo << utils::basename(fileName) << \":\" << line;\n> > +\tossFileInfo << utils::basename(fileName) << \" - \"\n> > +\t\t    << func << \"():\" << line;\n> >  \tfileInfo_ = ossFileInfo.str();\n> >  }\n> >  \n> > @@ -868,6 +871,7 @@ Loggable::~Loggable()\n> >  /**\n> >   * \\brief Create a temporary LogMessage object to log a message\n> >   * \\param[in] fileName The file name where the message is logged from\n> > + * \\param[in] func The function name where the message is logged from\n> >   * \\param[in] line The line number where the message is logged from\n> >   * \\param[in] severity The log message severity\n> >   *\n> > @@ -876,10 +880,10 @@ Loggable::~Loggable()\n> >   *\n> >   * \\return A log message\n> >   */\n> > -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > -\t\t\t  LogSeverity severity) const\n> > +LogMessage Loggable::_log(const char *fileName, const char *func,\n> > +\t\t\t  unsigned int line, LogSeverity severity) const\n> >  {\n> > -\tLogMessage msg(fileName, line, severity);\n> > +\tLogMessage msg(fileName, func, line, severity);\n> >  \n> >  \tmsg.stream() << logPrefix() << \": \";\n> >  \treturn msg;\n> > @@ -888,6 +892,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> >  /**\n> >   * \\brief Create a temporary LogMessage object to log a message\n> >   * \\param[in] fileName The file name where the message is logged from\n> > + * \\param[in] func The function name where the message is logged from\n> >   * \\param[in] line The line number where the message is logged from\n> >   * \\param[in] category The log message category\n> >   * \\param[in] severity The log message severity\n> > @@ -897,11 +902,11 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> >   *\n> >   * \\return A log message\n> >   */\n> > -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > -\t\t\t  const LogCategory &category,\n> > +LogMessage Loggable::_log(const char *fileName, const char *func,\n> > +\t\t\t  unsigned int line, const LogCategory &category,\n> >  \t\t\t  LogSeverity severity) const\n> >  {\n> > -\tLogMessage msg(fileName, line, category, severity);\n> > +\tLogMessage msg(fileName, func, line, category, severity);\n> >  \n> >  \tmsg.stream() << logPrefix() << \": \";\n> >  \treturn msg;\n> > @@ -910,6 +915,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> >  /**\n> >   * \\brief Create a temporary LogMessage object to log a message\n> >   * \\param[in] fileName The file name where the message is logged from\n> > + * \\param[in] func The function name where the message is logged from\n> >   * \\param[in] line The line number where the message is logged from\n> >   * \\param[in] severity The log message severity\n> >   *\n> > @@ -918,14 +924,16 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> >   *\n> >   * \\return A log message\n> >   */\n> > -LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> > +LogMessage _log(const char *fileName, const char *func,\n> > +\t\tunsigned int line, LogSeverity severity)\n> >  {\n> > -\treturn LogMessage(fileName, line, severity);\n> > +\treturn LogMessage(fileName, func, line, severity);\n> >  }\n> >  \n> >  /**\n> >   * \\brief Create a temporary LogMessage object to log a message\n> >   * \\param[in] fileName The file name where the message is logged from\n> > + * \\param[in] func The function name where the message is logged from\n> >   * \\param[in] line The line number where the message is logged from\n> >   * \\param[in] category The log message category\n> >   * \\param[in] severity The log message severity\n> > @@ -935,10 +943,10 @@ LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> >   *\n> >   * \\return A log message\n> >   */\n> > -LogMessage _log(const char *fileName, unsigned int line,\n> > +LogMessage _log(const char *fileName, const char *func, unsigned int line,\n> >  \t\tconst LogCategory &category, LogSeverity severity)\n> >  {\n> > -\treturn LogMessage(fileName, line, category, severity);\n> > +\treturn LogMessage(fileName, func, line, category, severity);\n> >  }\n> >  \n> >  /**\n> \n> -- \n> Regards,\n> \n> Laurent Pinchart\n> _______________________________________________\n> libcamera-devel mailing list\n> libcamera-devel@lists.libcamera.org\n> https://lists.libcamera.org/listinfo/libcamera-devel","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-ed1-x541.google.com (mail-ed1-x541.google.com\n\t[IPv6:2a00:1450:4864:20::541])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id A7EB3600F9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 15:46:23 +0200 (CEST)","by mail-ed1-x541.google.com with SMTP id r12so7465225edo.5\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 06:46:23 -0700 (PDT)","from localhost ([185.224.57.161]) by smtp.gmail.com with ESMTPSA id\n\tx42sm1663772edm.77.2019.08.17.06.46.16\n\tfor <libcamera-devel@lists.libcamera.org>\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSat, 17 Aug 2019 06:46:21 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to\n\t:user-agent; bh=9mgbqCjlrICPe48+25AUH+zOQLPJjMvNJeUjFCVuigU=;\n\tb=E3JaLkD2nDOsFbb4AYca+BfBQGJYXVt5lcvyIIgeEZBdl8WcXQ5YeXPILNQIt9d744\n\tTcCO5CzhyV10vQ+9pjT+Nc4DaVt/WCRcb5FkEA0j2v/0Fl73XGI6DVEpgES5t2TOcsUu\n\tqMaEaM2hWfzf/LLML80YXZjqkwg66XL+P/hL4b/09rn3QVlNuJFlt9uESGWvmMeDvG3t\n\taSheEGh5maMC62gmqbJglFSVqgJBPhKWpIZk4eiZc9UGZMS5CyvceroLdBhBCMihDpKn\n\tNOlOZxlmmjTSWHyIxyjOmmiuRyH86BQOXm6t8qwYyERSc2lzMHesRtBgVAda/ShDhrrj\n\tSE7g==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to:user-agent;\n\tbh=9mgbqCjlrICPe48+25AUH+zOQLPJjMvNJeUjFCVuigU=;\n\tb=cBcDoV8qZKiI+MY9FhOVybgGrbeFd7ZWFey25yKnRav8b5JKHGX1CzMGEzTnQtI2QS\n\tDnRrJY9RR3td6125us8rXOUKRQDfPLPZxxCP8RSnv7SnbdfYPfSYnlZkDGQoBZW6dRMi\n\teKNaBp3eOKW+GPsePr7ZnSvKmAVYKBKoGKGraesemP2u8JppXVd5UJ0dzSod4hR+LxW+\n\tg7F80D0JkT7kpfvrxCFnWolsYwNG0mYV0cxGrKGl+59QE6HLItlLWapHy0BhYihrnzg4\n\tOhnNNTc78KPr2jDi6mPdCJ8zCUs0VM+xhSwW2dtX7t30aXHj5OJEIWI7fM/ahjFtCOme\n\tUDsw==","X-Gm-Message-State":"APjAAAXjJikwSoRrQkEpMxu7iI0m56wqp865bD8RtO6kYdvCXp2u4N++\n\thQ4Y8LJjI0N24IxljxSrGQmLsGxAYh0=","X-Google-Smtp-Source":"APXvYqzFipYWXIhNT2oobxLCWYlPJd9l5GGqnA48oFQke3xDDHjnhfSA0prk8/IzpdkpZIl2octS0g==","X-Received":"by 2002:a17:906:bb0f:: with SMTP id\n\tjz15mr2158628ejb.264.1566049582642; \n\tSat, 17 Aug 2019 06:46:22 -0700 (PDT)","Date":"Sat, 17 Aug 2019 15:45:56 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190817134556.GA16603@wyvern>","References":"<20190812124919.736-1-jacopo@jmondi.org>\n\t<20190812151803.GG5006@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190812151803.GG5006@pendragon.ideasonboard.com>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 17 Aug 2019 13:46:23 -0000"}},{"id":2433,"web_url":"https://patchwork.libcamera.org/comment/2433/","msgid":"<20190817143755.GA15630@pendragon.ideasonboard.com>","date":"2019-08-17T14:37:55","subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"Hi Niklas,\n\nOn Sat, Aug 17, 2019 at 03:45:56PM +0200, Niklas Söderlund wrote:\n> On 2019-08-12 18:18:03 +0300, Laurent Pinchart wrote:\n> > On Mon, Aug 12, 2019 at 02:49:19PM +0200, Jacopo Mondi wrote:\n> > > Add the function name to the log tag.\n> > > \n> > > With this patch applied, the log format looks like:\n> > > INFO Camera camera_manager.cpp - start():83 libcamera v0.0.0+655-ddf32590\n> > \n> > I think I would prefer keeping the line number associated with the file:\n> > \n> > INFO Camera camera_manager.cpp:83 - start() libcamera v0.0.0+655-ddf32590\n> \n> I agree with Laurent here, I like to line number to be kept together \n> with the file name.\n> \n> > or maybe\n> > \n> > INFO Camera start() (camera_manager.cpp:83) libcamera v0.0.0+655-ddf32590\n> > \n> > ?\n> > \n> > I'm a bit bothered by the missing class name to be honest, as it makes\n> > the function name less useful without the context. The filename helps,\n> > but then does the function name alone bring much added value ? What's\n> > everybody's experience when reading logs, would the function name alone\n> > improve readability even if it increases the length of the lines ?\n> \n> I must admit when I read logs from C++ I only look at the file.cpp:line \n> marking and ignore the function name as without the class name it's not \n> so useful for me. I'm not bothered by it being in the output and I have \n> little concern about the length of the log lines, provided the file+line \n> information is early enough on the line.\n> \n> That being said and to add to the bikesheeding, if the function name is \n> to be printed I think it could be useful to print it in its class \n> context.  My suggested log line would be something like:\n> \n> INFO Camera camera_manager.cpp:83 CameraManager::start(): libcamera v0.0.0+655-ddf32590\n\nThe problem is that compilers don't offer a __class__ equivalent to\n__func__ :-S There's a gcc-specific __PRETTY_FUNCTION__ that prints the\nfull name, including the namespace and arguments, which we could then\nparse to extract the class name, but I'm not sure it's worse it.\n\n> I do not (yet) find the Log categories super useful so I would be open \n> to discuss dropping them, but then again I'm not bothered by them and \n> maybe they can be useful for log filtering going forward.\n\nI find them marginally useful in the log message itself, but for\nfiltering I think they are (or at least will be), if nothing else at\nleast to avoid printing a very large number of V4L2 QBUF/DQBUF or\nrequest completion messages.\n\n> > > Compared to:\n> > > INFO Camera camera_manager.cpp:83 libcamera v0.0.0+654-a6799dc5\n> > > \n> > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > > ---\n> > >  src/libcamera/include/log.h | 19 +++++++++---------\n> > >  src/libcamera/log.cpp       | 40 ++++++++++++++++++++++---------------\n> > >  2 files changed, 34 insertions(+), 25 deletions(-)\n> > > \n> > > diff --git a/src/libcamera/include/log.h b/src/libcamera/include/log.h\n> > > index 9b203f97e304..e65d20af1ca9 100644\n> > > --- a/src/libcamera/include/log.h\n> > > +++ b/src/libcamera/include/log.h\n> > > @@ -50,9 +50,9 @@ const LogCategory &_LOG_CATEGORY(name)()\t\t\t\t\\\n> > >  class LogMessage\n> > >  {\n> > >  public:\n> > > -\tLogMessage(const char *fileName, unsigned int line,\n> > > +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n> > \n> > Should we name the new parameter funcName to match fileName ? Or rename\n> > fileName to file ?\n> > \n> > I would prefer keeping the file name and line number grouped, and thus\n> > adding the func parameter either as the first parameter of the function,\n> > or as the third one.\n> > \n> > Same comments for all other functions or macros.\n> > \n> > >  \t\t   LogSeverity severity);\n> > > -\tLogMessage(const char *fileName, unsigned int line,\n> > > +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n> > >  \t\t   const LogCategory &category, LogSeverity severity);\n> > >  \tLogMessage(const LogMessage &) = delete;\n> > >  \tLogMessage(LogMessage &&);\n> > > @@ -67,7 +67,7 @@ public:\n> > >  \tconst std::string msg() const { return msgStream_.str(); }\n> > >  \n> > >  private:\n> > > -\tvoid init(const char *fileName, unsigned int line);\n> > > +\tvoid init(const char *fileName, const char* func, unsigned int line);\n> > >  \n> > >  \tstd::ostringstream msgStream_;\n> > >  \tconst LogCategory &category_;\n> > > @@ -84,24 +84,25 @@ public:\n> > >  protected:\n> > >  \tvirtual std::string logPrefix() const = 0;\n> > >  \n> > > -\tLogMessage _log(const char *file, unsigned int line,\n> > > +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n> > >  \t\t\tLogSeverity severity) const;\n> > > -\tLogMessage _log(const char *file, unsigned int line,\n> > > +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n> > >  \t\t\tconst LogCategory &category,\n> > >  \t\t\tLogSeverity severity) const;\n> > >  };\n> > >  \n> > > -LogMessage _log(const char *file, unsigned int line, LogSeverity severity);\n> > > -LogMessage _log(const char *file, unsigned int line,\n> > > +LogMessage _log(const char *file, const char *func, unsigned int line,\n> > > +\t\tLogSeverity severity);\n> > > +LogMessage _log(const char *file, const char *func, unsigned int line,\n> > >  \t\tconst LogCategory &category, LogSeverity severity);\n> > >  \n> > >  #ifndef __DOXYGEN__\n> > >  #define _LOG_CATEGORY(name) logCategory##name\n> > >  \n> > >  #define _LOG1(severity) \\\n> > > -\t_log(__FILE__, __LINE__, Log##severity).stream()\n> > > +\t_log(__FILE__, __func__, __LINE__, Log##severity).stream()\n> > >  #define _LOG2(category, severity) \\\n> > > -\t_log(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> > > +\t_log(__FILE__, __func__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> > >  \n> > >  /*\n> > >   * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of\n> > > diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp\n> > > index 91f7c3ee5157..fa9a16452f25 100644\n> > > --- a/src/libcamera/log.cpp\n> > > +++ b/src/libcamera/log.cpp\n> > > @@ -720,6 +720,7 @@ const LogCategory &LogCategory::defaultCategory()\n> > >  /**\n> > >   * \\brief Construct a log message for the default category\n> > >   * \\param[in] fileName The file name where the message is logged from\n> > > + * \\param[in] func The function name where the message is logged from\n> > >   * \\param[in] line The line number where the message is logged from\n> > >   * \\param[in] severity The log message severity, controlling how the message\n> > >   * will be displayed\n> > > @@ -728,16 +729,17 @@ const LogCategory &LogCategory::defaultCategory()\n> > >   * \\a severity argument sets the message severity to control whether it will be\n> > >   * output or dropped.\n> > >   */\n> > > -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > > +LogMessage::LogMessage(const char *fileName, const char *func ,unsigned int line,\n> > >  \t\t       LogSeverity severity)\n> > >  \t: category_(LogCategory::defaultCategory()), severity_(severity)\n> > >  {\n> > > -\tinit(fileName, line);\n> > > +\tinit(fileName, func, line);\n> > >  }\n> > >  \n> > >  /**\n> > >   * \\brief Construct a log message for a given category\n> > >   * \\param[in] fileName The file name where the message is logged from\n> > > + * \\param[in] func The function name where the message is logged from\n> > >   * \\param[in] line The line number where the message is logged from\n> > >   * \\param[in] category The log message category, controlling how the message\n> > >   * will be displayed\n> > > @@ -748,11 +750,11 @@ LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > >   * \\a severity argument sets the message severity to control whether it will be\n> > >   * output or dropped.\n> > >   */\n> > > -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > > +LogMessage::LogMessage(const char *fileName, const char *func, unsigned int line,\n> > >  \t\t       const LogCategory &category, LogSeverity severity)\n> > >  \t: category_(category), severity_(severity)\n> > >  {\n> > > -\tinit(fileName, line);\n> > > +\tinit(fileName, func, line);\n> > >  }\n> > >  \n> > >  /**\n> > > @@ -774,13 +776,14 @@ LogMessage::LogMessage(LogMessage &&other)\n> > >  \tother.severity_ = LogInvalid;\n> > >  }\n> > >  \n> > > -void LogMessage::init(const char *fileName, unsigned int line)\n> > > +void LogMessage::init(const char *fileName, const char *func, unsigned int line)\n> > >  {\n> > >  \t/* Log the timestamp, severity and file information. */\n> > >  \tclock_gettime(CLOCK_MONOTONIC, &timestamp_);\n> > >  \n> > >  \tstd::ostringstream ossFileInfo;\n> > > -\tossFileInfo << utils::basename(fileName) << \":\" << line;\n> > > +\tossFileInfo << utils::basename(fileName) << \" - \"\n> > > +\t\t    << func << \"():\" << line;\n> > >  \tfileInfo_ = ossFileInfo.str();\n> > >  }\n> > >  \n> > > @@ -868,6 +871,7 @@ Loggable::~Loggable()\n> > >  /**\n> > >   * \\brief Create a temporary LogMessage object to log a message\n> > >   * \\param[in] fileName The file name where the message is logged from\n> > > + * \\param[in] func The function name where the message is logged from\n> > >   * \\param[in] line The line number where the message is logged from\n> > >   * \\param[in] severity The log message severity\n> > >   *\n> > > @@ -876,10 +880,10 @@ Loggable::~Loggable()\n> > >   *\n> > >   * \\return A log message\n> > >   */\n> > > -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > -\t\t\t  LogSeverity severity) const\n> > > +LogMessage Loggable::_log(const char *fileName, const char *func,\n> > > +\t\t\t  unsigned int line, LogSeverity severity) const\n> > >  {\n> > > -\tLogMessage msg(fileName, line, severity);\n> > > +\tLogMessage msg(fileName, func, line, severity);\n> > >  \n> > >  \tmsg.stream() << logPrefix() << \": \";\n> > >  \treturn msg;\n> > > @@ -888,6 +892,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > >  /**\n> > >   * \\brief Create a temporary LogMessage object to log a message\n> > >   * \\param[in] fileName The file name where the message is logged from\n> > > + * \\param[in] func The function name where the message is logged from\n> > >   * \\param[in] line The line number where the message is logged from\n> > >   * \\param[in] category The log message category\n> > >   * \\param[in] severity The log message severity\n> > > @@ -897,11 +902,11 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > >   *\n> > >   * \\return A log message\n> > >   */\n> > > -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > -\t\t\t  const LogCategory &category,\n> > > +LogMessage Loggable::_log(const char *fileName, const char *func,\n> > > +\t\t\t  unsigned int line, const LogCategory &category,\n> > >  \t\t\t  LogSeverity severity) const\n> > >  {\n> > > -\tLogMessage msg(fileName, line, category, severity);\n> > > +\tLogMessage msg(fileName, func, line, category, severity);\n> > >  \n> > >  \tmsg.stream() << logPrefix() << \": \";\n> > >  \treturn msg;\n> > > @@ -910,6 +915,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > >  /**\n> > >   * \\brief Create a temporary LogMessage object to log a message\n> > >   * \\param[in] fileName The file name where the message is logged from\n> > > + * \\param[in] func The function name where the message is logged from\n> > >   * \\param[in] line The line number where the message is logged from\n> > >   * \\param[in] severity The log message severity\n> > >   *\n> > > @@ -918,14 +924,16 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > >   *\n> > >   * \\return A log message\n> > >   */\n> > > -LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> > > +LogMessage _log(const char *fileName, const char *func,\n> > > +\t\tunsigned int line, LogSeverity severity)\n> > >  {\n> > > -\treturn LogMessage(fileName, line, severity);\n> > > +\treturn LogMessage(fileName, func, line, severity);\n> > >  }\n> > >  \n> > >  /**\n> > >   * \\brief Create a temporary LogMessage object to log a message\n> > >   * \\param[in] fileName The file name where the message is logged from\n> > > + * \\param[in] func The function name where the message is logged from\n> > >   * \\param[in] line The line number where the message is logged from\n> > >   * \\param[in] category The log message category\n> > >   * \\param[in] severity The log message severity\n> > > @@ -935,10 +943,10 @@ LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> > >   *\n> > >   * \\return A log message\n> > >   */\n> > > -LogMessage _log(const char *fileName, unsigned int line,\n> > > +LogMessage _log(const char *fileName, const char *func, unsigned int line,\n> > >  \t\tconst LogCategory &category, LogSeverity severity)\n> > >  {\n> > > -\treturn LogMessage(fileName, line, category, severity);\n> > > +\treturn LogMessage(fileName, func, line, category, severity);\n> > >  }\n> > >  \n> > >  /**","headers":{"Return-Path":"<laurent.pinchart@ideasonboard.com>","Received":["from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 99F97600F9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 16:38:01 +0200 (CEST)","from pendragon.ideasonboard.com\n\t(dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi\n\t[IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 14552556;\n\tSat, 17 Aug 2019 16:38:01 +0200 (CEST)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1566052681;\n\tbh=+qZSCOFkdLYDPSwyIjsYvIoJ5MpJgolFiqJb2cj4/VE=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=IvSzDne6hv23BMn5eGL8NKrflXoB83AiC+PwEJ6d4tT8VOknDrjYbq6ChRiYK7ZGy\n\tpDDAz01BhlSJ76tmU7kbbbnVV/gRYiFzH7Qox0quj0YKesuOFd26n/XSB76/8O5tA6\n\tUqsR2i2S3K0LNVL59ONl+YSKnQ2N+92RIHqmbnxA=","Date":"Sat, 17 Aug 2019 17:37:55 +0300","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Niklas =?utf-8?q?S=C3=B6derlund?= <niklas.soderlund@ragnatech.se>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190817143755.GA15630@pendragon.ideasonboard.com>","References":"<20190812124919.736-1-jacopo@jmondi.org>\n\t<20190812151803.GG5006@pendragon.ideasonboard.com>\n\t<20190817134556.GA16603@wyvern>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190817134556.GA16603@wyvern>","User-Agent":"Mutt/1.10.1 (2018-07-13)","Subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 17 Aug 2019 14:38:01 -0000"}},{"id":2447,"web_url":"https://patchwork.libcamera.org/comment/2447/","msgid":"<20190817152321.GA21683@wyvern>","date":"2019-08-17T15:23:21","subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","submitter":{"id":5,"url":"https://patchwork.libcamera.org/api/people/5/","name":"Niklas Söderlund","email":"niklas.soderlund@ragnatech.se"},"content":"Hi Laurent,\n\nOn 2019-08-17 17:37:55 +0300, Laurent Pinchart wrote:\n> Hi Niklas,\n> \n> On Sat, Aug 17, 2019 at 03:45:56PM +0200, Niklas Söderlund wrote:\n> > On 2019-08-12 18:18:03 +0300, Laurent Pinchart wrote:\n> > > On Mon, Aug 12, 2019 at 02:49:19PM +0200, Jacopo Mondi wrote:\n> > > > Add the function name to the log tag.\n> > > > \n> > > > With this patch applied, the log format looks like:\n> > > > INFO Camera camera_manager.cpp - start():83 libcamera v0.0.0+655-ddf32590\n> > > \n> > > I think I would prefer keeping the line number associated with the file:\n> > > \n> > > INFO Camera camera_manager.cpp:83 - start() libcamera v0.0.0+655-ddf32590\n> > \n> > I agree with Laurent here, I like to line number to be kept together \n> > with the file name.\n> > \n> > > or maybe\n> > > \n> > > INFO Camera start() (camera_manager.cpp:83) libcamera v0.0.0+655-ddf32590\n> > > \n> > > ?\n> > > \n> > > I'm a bit bothered by the missing class name to be honest, as it makes\n> > > the function name less useful without the context. The filename helps,\n> > > but then does the function name alone bring much added value ? What's\n> > > everybody's experience when reading logs, would the function name alone\n> > > improve readability even if it increases the length of the lines ?\n> > \n> > I must admit when I read logs from C++ I only look at the file.cpp:line \n> > marking and ignore the function name as without the class name it's not \n> > so useful for me. I'm not bothered by it being in the output and I have \n> > little concern about the length of the log lines, provided the file+line \n> > information is early enough on the line.\n> > \n> > That being said and to add to the bikesheeding, if the function name is \n> > to be printed I think it could be useful to print it in its class \n> > context.  My suggested log line would be something like:\n> > \n> > INFO Camera camera_manager.cpp:83 CameraManager::start(): libcamera v0.0.0+655-ddf32590\n> \n> The problem is that compilers don't offer a __class__ equivalent to\n> __func__ :-S There's a gcc-specific __PRETTY_FUNCTION__ that prints the\n> full name, including the namespace and arguments, which we could then\n> parse to extract the class name, but I'm not sure it's worse it.\n\nOhh you are right, I was so sure I used __class__ somewhere back in the \nday I did not bother to look it up. But now that I did look it up I see \nthe problem.\n\nFor the issue at hand I don't have an opinion on if we should keep \nprinting the function name or not. For me personally it has little value, \nbut others might find it useful so maybe we should keep it.\n\n> \n> > I do not (yet) find the Log categories super useful so I would be open \n> > to discuss dropping them, but then again I'm not bothered by them and \n> > maybe they can be useful for log filtering going forward.\n> \n> I find them marginally useful in the log message itself, but for\n> filtering I think they are (or at least will be), if nothing else at\n> least to avoid printing a very large number of V4L2 QBUF/DQBUF or\n> request completion messages.\n> \n> > > > Compared to:\n> > > > INFO Camera camera_manager.cpp:83 libcamera v0.0.0+654-a6799dc5\n> > > > \n> > > > Signed-off-by: Jacopo Mondi <jacopo@jmondi.org>\n> > > > ---\n> > > >  src/libcamera/include/log.h | 19 +++++++++---------\n> > > >  src/libcamera/log.cpp       | 40 ++++++++++++++++++++++---------------\n> > > >  2 files changed, 34 insertions(+), 25 deletions(-)\n> > > > \n> > > > diff --git a/src/libcamera/include/log.h b/src/libcamera/include/log.h\n> > > > index 9b203f97e304..e65d20af1ca9 100644\n> > > > --- a/src/libcamera/include/log.h\n> > > > +++ b/src/libcamera/include/log.h\n> > > > @@ -50,9 +50,9 @@ const LogCategory &_LOG_CATEGORY(name)()\t\t\t\t\\\n> > > >  class LogMessage\n> > > >  {\n> > > >  public:\n> > > > -\tLogMessage(const char *fileName, unsigned int line,\n> > > > +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n> > > \n> > > Should we name the new parameter funcName to match fileName ? Or rename\n> > > fileName to file ?\n> > > \n> > > I would prefer keeping the file name and line number grouped, and thus\n> > > adding the func parameter either as the first parameter of the function,\n> > > or as the third one.\n> > > \n> > > Same comments for all other functions or macros.\n> > > \n> > > >  \t\t   LogSeverity severity);\n> > > > -\tLogMessage(const char *fileName, unsigned int line,\n> > > > +\tLogMessage(const char *fileName, const char *func, unsigned int line,\n> > > >  \t\t   const LogCategory &category, LogSeverity severity);\n> > > >  \tLogMessage(const LogMessage &) = delete;\n> > > >  \tLogMessage(LogMessage &&);\n> > > > @@ -67,7 +67,7 @@ public:\n> > > >  \tconst std::string msg() const { return msgStream_.str(); }\n> > > >  \n> > > >  private:\n> > > > -\tvoid init(const char *fileName, unsigned int line);\n> > > > +\tvoid init(const char *fileName, const char* func, unsigned int line);\n> > > >  \n> > > >  \tstd::ostringstream msgStream_;\n> > > >  \tconst LogCategory &category_;\n> > > > @@ -84,24 +84,25 @@ public:\n> > > >  protected:\n> > > >  \tvirtual std::string logPrefix() const = 0;\n> > > >  \n> > > > -\tLogMessage _log(const char *file, unsigned int line,\n> > > > +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n> > > >  \t\t\tLogSeverity severity) const;\n> > > > -\tLogMessage _log(const char *file, unsigned int line,\n> > > > +\tLogMessage _log(const char *file, const char *func, unsigned int line,\n> > > >  \t\t\tconst LogCategory &category,\n> > > >  \t\t\tLogSeverity severity) const;\n> > > >  };\n> > > >  \n> > > > -LogMessage _log(const char *file, unsigned int line, LogSeverity severity);\n> > > > -LogMessage _log(const char *file, unsigned int line,\n> > > > +LogMessage _log(const char *file, const char *func, unsigned int line,\n> > > > +\t\tLogSeverity severity);\n> > > > +LogMessage _log(const char *file, const char *func, unsigned int line,\n> > > >  \t\tconst LogCategory &category, LogSeverity severity);\n> > > >  \n> > > >  #ifndef __DOXYGEN__\n> > > >  #define _LOG_CATEGORY(name) logCategory##name\n> > > >  \n> > > >  #define _LOG1(severity) \\\n> > > > -\t_log(__FILE__, __LINE__, Log##severity).stream()\n> > > > +\t_log(__FILE__, __func__, __LINE__, Log##severity).stream()\n> > > >  #define _LOG2(category, severity) \\\n> > > > -\t_log(__FILE__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> > > > +\t_log(__FILE__, __func__, __LINE__, _LOG_CATEGORY(category)(), Log##severity).stream()\n> > > >  \n> > > >  /*\n> > > >   * Expand the LOG() macro to _LOG1() or _LOG2() based on the number of\n> > > > diff --git a/src/libcamera/log.cpp b/src/libcamera/log.cpp\n> > > > index 91f7c3ee5157..fa9a16452f25 100644\n> > > > --- a/src/libcamera/log.cpp\n> > > > +++ b/src/libcamera/log.cpp\n> > > > @@ -720,6 +720,7 @@ const LogCategory &LogCategory::defaultCategory()\n> > > >  /**\n> > > >   * \\brief Construct a log message for the default category\n> > > >   * \\param[in] fileName The file name where the message is logged from\n> > > > + * \\param[in] func The function name where the message is logged from\n> > > >   * \\param[in] line The line number where the message is logged from\n> > > >   * \\param[in] severity The log message severity, controlling how the message\n> > > >   * will be displayed\n> > > > @@ -728,16 +729,17 @@ const LogCategory &LogCategory::defaultCategory()\n> > > >   * \\a severity argument sets the message severity to control whether it will be\n> > > >   * output or dropped.\n> > > >   */\n> > > > -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > > > +LogMessage::LogMessage(const char *fileName, const char *func ,unsigned int line,\n> > > >  \t\t       LogSeverity severity)\n> > > >  \t: category_(LogCategory::defaultCategory()), severity_(severity)\n> > > >  {\n> > > > -\tinit(fileName, line);\n> > > > +\tinit(fileName, func, line);\n> > > >  }\n> > > >  \n> > > >  /**\n> > > >   * \\brief Construct a log message for a given category\n> > > >   * \\param[in] fileName The file name where the message is logged from\n> > > > + * \\param[in] func The function name where the message is logged from\n> > > >   * \\param[in] line The line number where the message is logged from\n> > > >   * \\param[in] category The log message category, controlling how the message\n> > > >   * will be displayed\n> > > > @@ -748,11 +750,11 @@ LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > > >   * \\a severity argument sets the message severity to control whether it will be\n> > > >   * output or dropped.\n> > > >   */\n> > > > -LogMessage::LogMessage(const char *fileName, unsigned int line,\n> > > > +LogMessage::LogMessage(const char *fileName, const char *func, unsigned int line,\n> > > >  \t\t       const LogCategory &category, LogSeverity severity)\n> > > >  \t: category_(category), severity_(severity)\n> > > >  {\n> > > > -\tinit(fileName, line);\n> > > > +\tinit(fileName, func, line);\n> > > >  }\n> > > >  \n> > > >  /**\n> > > > @@ -774,13 +776,14 @@ LogMessage::LogMessage(LogMessage &&other)\n> > > >  \tother.severity_ = LogInvalid;\n> > > >  }\n> > > >  \n> > > > -void LogMessage::init(const char *fileName, unsigned int line)\n> > > > +void LogMessage::init(const char *fileName, const char *func, unsigned int line)\n> > > >  {\n> > > >  \t/* Log the timestamp, severity and file information. */\n> > > >  \tclock_gettime(CLOCK_MONOTONIC, &timestamp_);\n> > > >  \n> > > >  \tstd::ostringstream ossFileInfo;\n> > > > -\tossFileInfo << utils::basename(fileName) << \":\" << line;\n> > > > +\tossFileInfo << utils::basename(fileName) << \" - \"\n> > > > +\t\t    << func << \"():\" << line;\n> > > >  \tfileInfo_ = ossFileInfo.str();\n> > > >  }\n> > > >  \n> > > > @@ -868,6 +871,7 @@ Loggable::~Loggable()\n> > > >  /**\n> > > >   * \\brief Create a temporary LogMessage object to log a message\n> > > >   * \\param[in] fileName The file name where the message is logged from\n> > > > + * \\param[in] func The function name where the message is logged from\n> > > >   * \\param[in] line The line number where the message is logged from\n> > > >   * \\param[in] severity The log message severity\n> > > >   *\n> > > > @@ -876,10 +880,10 @@ Loggable::~Loggable()\n> > > >   *\n> > > >   * \\return A log message\n> > > >   */\n> > > > -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > > -\t\t\t  LogSeverity severity) const\n> > > > +LogMessage Loggable::_log(const char *fileName, const char *func,\n> > > > +\t\t\t  unsigned int line, LogSeverity severity) const\n> > > >  {\n> > > > -\tLogMessage msg(fileName, line, severity);\n> > > > +\tLogMessage msg(fileName, func, line, severity);\n> > > >  \n> > > >  \tmsg.stream() << logPrefix() << \": \";\n> > > >  \treturn msg;\n> > > > @@ -888,6 +892,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > >  /**\n> > > >   * \\brief Create a temporary LogMessage object to log a message\n> > > >   * \\param[in] fileName The file name where the message is logged from\n> > > > + * \\param[in] func The function name where the message is logged from\n> > > >   * \\param[in] line The line number where the message is logged from\n> > > >   * \\param[in] category The log message category\n> > > >   * \\param[in] severity The log message severity\n> > > > @@ -897,11 +902,11 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > >   *\n> > > >   * \\return A log message\n> > > >   */\n> > > > -LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > > -\t\t\t  const LogCategory &category,\n> > > > +LogMessage Loggable::_log(const char *fileName, const char *func,\n> > > > +\t\t\t  unsigned int line, const LogCategory &category,\n> > > >  \t\t\t  LogSeverity severity) const\n> > > >  {\n> > > > -\tLogMessage msg(fileName, line, category, severity);\n> > > > +\tLogMessage msg(fileName, func, line, category, severity);\n> > > >  \n> > > >  \tmsg.stream() << logPrefix() << \": \";\n> > > >  \treturn msg;\n> > > > @@ -910,6 +915,7 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > >  /**\n> > > >   * \\brief Create a temporary LogMessage object to log a message\n> > > >   * \\param[in] fileName The file name where the message is logged from\n> > > > + * \\param[in] func The function name where the message is logged from\n> > > >   * \\param[in] line The line number where the message is logged from\n> > > >   * \\param[in] severity The log message severity\n> > > >   *\n> > > > @@ -918,14 +924,16 @@ LogMessage Loggable::_log(const char *fileName, unsigned int line,\n> > > >   *\n> > > >   * \\return A log message\n> > > >   */\n> > > > -LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> > > > +LogMessage _log(const char *fileName, const char *func,\n> > > > +\t\tunsigned int line, LogSeverity severity)\n> > > >  {\n> > > > -\treturn LogMessage(fileName, line, severity);\n> > > > +\treturn LogMessage(fileName, func, line, severity);\n> > > >  }\n> > > >  \n> > > >  /**\n> > > >   * \\brief Create a temporary LogMessage object to log a message\n> > > >   * \\param[in] fileName The file name where the message is logged from\n> > > > + * \\param[in] func The function name where the message is logged from\n> > > >   * \\param[in] line The line number where the message is logged from\n> > > >   * \\param[in] category The log message category\n> > > >   * \\param[in] severity The log message severity\n> > > > @@ -935,10 +943,10 @@ LogMessage _log(const char *fileName, unsigned int line, LogSeverity severity)\n> > > >   *\n> > > >   * \\return A log message\n> > > >   */\n> > > > -LogMessage _log(const char *fileName, unsigned int line,\n> > > > +LogMessage _log(const char *fileName, const char *func, unsigned int line,\n> > > >  \t\tconst LogCategory &category, LogSeverity severity)\n> > > >  {\n> > > > -\treturn LogMessage(fileName, line, category, severity);\n> > > > +\treturn LogMessage(fileName, func, line, category, severity);\n> > > >  }\n> > > >  \n> > > >  /**\n> \n> -- \n> Regards,\n> \n> Laurent Pinchart","headers":{"Return-Path":"<niklas.soderlund@ragnatech.se>","Received":["from mail-ed1-x542.google.com (mail-ed1-x542.google.com\n\t[IPv6:2a00:1450:4864:20::542])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 8DA2F600F9\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 17:23:24 +0200 (CEST)","by mail-ed1-x542.google.com with SMTP id w20so7582054edd.2\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSat, 17 Aug 2019 08:23:24 -0700 (PDT)","from localhost ([185.224.57.161]) by smtp.gmail.com with ESMTPSA id\n\tx21sm1689168edb.0.2019.08.17.08.23.23\n\t(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n\tSat, 17 Aug 2019 08:23:23 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=ragnatech-se.20150623.gappssmtp.com; s=20150623;\n\th=date:from:to:cc:subject:message-id:references:mime-version\n\t:content-disposition:content-transfer-encoding:in-reply-to\n\t:user-agent; bh=5D8p/5jmHIiDJs0YrkWVQqoUADgd+hDXVLzSV26E3Hk=;\n\tb=zCpheGEOEd5ff3ntaHg42kIyA89si6gAD9/VEfnbq3d6sPiONedicWS0emN91LMj4b\n\twjsvgjP+mJ3+yl+kTDUhsNUfn7tb1rbmSsUzr7rpKM9inzinyYkeI95mplNeJHLlC6vy\n\tffCxoLKsA0kkHzVm3Nx7vZXWHJDoQ0Mnb1cXTlsIqwerrZkpMpdY5KU2B2snBuDPktRK\n\tVGfkYPUYXZ2MwvPSOxeBB9RZ4bb2KoO1cbKaEquelE5qJDL2DiaBpK8JfUI+U+7Zk8Nt\n\t0jtPmTeGbh0AWonlttLTf8Z0I2SyZ7l4EXRbuIoSzFXlyHz8KfYSYCKF60zUO5m83mWu\n\t6dnQ==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:date:from:to:cc:subject:message-id:references\n\t:mime-version:content-disposition:content-transfer-encoding\n\t:in-reply-to:user-agent;\n\tbh=5D8p/5jmHIiDJs0YrkWVQqoUADgd+hDXVLzSV26E3Hk=;\n\tb=Cg2+iaQfDXwqno+XckkLd7biMEJ+WaxtbP9p+6ywCRLUVcKKqAss3IPNQy2MGCmi1s\n\tqU9HNrahYTXOfsW8vX7JQoy0hyOl1p4wTJbg3vhtcfna2r4FSgGyxRRtEDg4UKRAquOL\n\tumvGUZdwAnUpwQGQ0fL5FGMt5gnnfdB6G/pPcA3jhZxxEbDk2BAE41KV3lGgempuA5qS\n\tqc/ljcFwjSdwsh/bQt7vf5w/KpfCXdjxN2mjIjpol3aoUxadM4cwz6OkrVA7kHqpJbsb\n\tqHJAFfxjjPrQexjYsSjGEc3SMIudz19kcs1Lj1DdG4bFIRPhLP0XLHXarsVtpZOLYLRk\n\tvkTQ==","X-Gm-Message-State":"APjAAAUOc+yAzkurMkAfJpjA7iXMTDhAbf712gYL26xN/GWJQ/Kbf5gC\n\t1p47jXTXcyPSOpitbBFE+oAkbzWXixU=","X-Google-Smtp-Source":"APXvYqwvwjsBv+PGnWOZR4q0WZ4TArisqOyxkqvOdNVWF6xApH7X75A3OE/NhYxc5Mbz9KsfW1eLfg==","X-Received":"by 2002:a17:906:4ed8:: with SMTP id\n\ti24mr13626431ejv.312.1566055404109; \n\tSat, 17 Aug 2019 08:23:24 -0700 (PDT)","Date":"Sat, 17 Aug 2019 17:23:21 +0200","From":"Niklas =?iso-8859-1?q?S=F6derlund?= <niklas.soderlund@ragnatech.se>","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Cc":"libcamera-devel@lists.libcamera.org","Message-ID":"<20190817152321.GA21683@wyvern>","References":"<20190812124919.736-1-jacopo@jmondi.org>\n\t<20190812151803.GG5006@pendragon.ideasonboard.com>\n\t<20190817134556.GA16603@wyvern>\n\t<20190817143755.GA15630@pendragon.ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=iso-8859-1","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20190817143755.GA15630@pendragon.ideasonboard.com>","User-Agent":"Mutt/1.12.1 (2019-06-15)","Subject":"Re: [libcamera-devel] [PATCH] libcamera: log: Print the function\n\tname in log","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.23","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","X-List-Received-Date":"Sat, 17 Aug 2019 15:23:24 -0000"}}]