LCOV - code coverage report
Current view: top level - src/utils/common - MsgHandler.h (source / functions) Coverage Total Hit
Test: lcov.info Lines: 95.0 % 20 19
Test Date: 2025-12-06 15:35:27 Functions: 85.1 % 74 63

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2003-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    MsgHandler.h
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Michael Behrisch
      17              : /// @author  Jakob Erdmann
      18              : /// @author  Mirko Barthauer
      19              : /// @date    Tue, 17 Jun 2003
      20              : ///
      21              : // Retrieves messages about the process and gives them further to output
      22              : /****************************************************************************/
      23              : #pragma once
      24              : #include <config.h>
      25              : #include <string>
      26              : #include <vector>
      27              : #include <map>
      28              : #include <utils/common/StringUtils.h>
      29              : #include <utils/common/Translation.h>
      30              : #include <utils/iodevices/OutputDevice.h>
      31              : 
      32              : 
      33              : // ===========================================================================
      34              : // class definitions
      35              : // ===========================================================================
      36              : /**
      37              :  * MsgHandler
      38              :  */
      39              : class MsgHandler {
      40              : public:
      41              :     /**
      42              :      * @enum MsgType
      43              :      * An enumeration to differ between different types of messages
      44              :      * (errors, warning and information)
      45              :      */
      46              :     enum class MsgType {
      47              :         /// The message is only something to show
      48              :         MT_MESSAGE,
      49              :         /// The message is a warning
      50              :         MT_WARNING,
      51              :         /// The message is an error
      52              :         MT_ERROR,
      53              :         /// The message is debug output
      54              :         MT_DEBUG,
      55              :         /// The message is GL debug output
      56              :         MT_GLDEBUG
      57              :     };
      58              : 
      59              : private:
      60              :     typedef MsgHandler* (*Factory)(MsgType);
      61              : 
      62              : public:
      63              :     /// @brief Sets the factory function to use for new MsgHandlers
      64              :     static void setFactory(Factory func) {
      65              :         // clean old instances
      66        12414 :         cleanupOnEnd();
      67        12414 :         myFactory = func;
      68         4373 :     }
      69              : 
      70              :     /// @brief Returns the instance to add normal messages to
      71              :     static MsgHandler* getMessageInstance();
      72              : 
      73              :     /// @brief Returns the instance to add warnings to
      74              :     static MsgHandler* getWarningInstance();
      75              : 
      76              :     /// @brief Returns the instance to add errors to
      77              :     static MsgHandler* getErrorInstance();
      78              : 
      79              :     /// @brief enable/disable debug messages
      80              :     static void enableDebugMessages(bool enable);
      81              : 
      82              :     /// @brief enable/disable gl-debug messages
      83              :     static void enableDebugGLMessages(bool enable);
      84              : 
      85              :     /// @brief check whether to enable/disable debug messages
      86              :     static inline bool writeDebugMessages() {
      87              :         return myWriteDebugMessages;
      88              :     }
      89              : 
      90              :     /// @brief check whether to enable/disable gl-debug messages
      91              :     static inline bool writeDebugGLMessages() {
      92        31580 :         return myWriteDebugGLMessages;
      93              :     }
      94              : 
      95              :     /// @brief reformats a long string to contain newline after a certain line length in px (depending on the current font)
      96              :     static std::string insertLineBreaks(std::string msg, int lineWidth);
      97              : 
      98              :     /// @brief ensure that that given output device is no longer used as retriever by any instance
      99              :     static void removeRetrieverFromAllInstances(OutputDevice* out);
     100              : 
     101              :     ///@brief set up gettext stuff
     102              :     static void setupI18n(const std::string& locale = "");
     103              : 
     104              :     ///@brief init output options
     105              :     static void initOutputOptions();
     106              : 
     107              :     /// @brief Removes pending handler
     108              :     static void cleanupOnEnd();
     109              : 
     110              :     /// @brief adds a new error to the list
     111              :     virtual void inform(std::string msg, bool addType = true);
     112              : 
     113              :     /// @brief adds a new formatted message
     114              :     // variadic function
     115              :     template<typename T, typename... Targs>
     116       542889 :     void informf(const std::string& format, T value, Targs... Fargs) {
     117       542889 :         if (!aggregationThresholdReached(format)) {
     118      1372409 :             inform(StringUtils::format(format, value, Fargs...), true);
     119              :         }
     120       542889 :     }
     121              : 
     122              :     /** @brief Begins a process information
     123              :      *
     124              :      * When a longer action is started, this method should be used to inform the user about it.
     125              :      * There will be no newline printed, but the message handler will be informed that
     126              :      *  a process message has been begun. If an error occurs, a newline will be printed.
     127              :      * After the action has been performed, use endProcessMsg to inform the user about it.
     128              :      */
     129              :     virtual void beginProcessMsg(std::string msg, bool addType = true);
     130              : 
     131              :     /// @brief Ends a process information with predefined messages
     132              :     virtual void endProcessMsg2(bool success, long duration = -1);
     133              : 
     134              :     /// @brief Ends a process information
     135              :     virtual void endProcessMsg(std::string msg);
     136              : 
     137              :     /// @brief Clears information whether an error occurred previously and print aggregated message summary
     138              :     virtual void clear(bool resetInformed = true);
     139              : 
     140              :     /// @brief Adds a further retriever to the instance responsible for a certain msg type
     141              :     virtual void addRetriever(OutputDevice* retriever);
     142              : 
     143              :     /// @brief Removes the retriever from the handler
     144              :     virtual void removeRetriever(OutputDevice* retriever);
     145              : 
     146              :     /// @brief Returns whether the given output device retrieves messages from the handler
     147              :     bool isRetriever(OutputDevice* retriever) const;
     148              : 
     149              :     /// @brief Returns the information whether any messages were added
     150              :     bool wasInformed() const;
     151              : 
     152              :     /** @brief Generic output operator
     153              :      * @return The MsgHandler for further processing
     154              :      */
     155              :     template <class T>
     156              :     MsgHandler& operator<<(const T& t) {
     157              :         // inform all other receivers
     158              :         for (OutputDevice* o : myRetrievers) {
     159              :             (*o) << t;
     160              :         }
     161              :         return *this;
     162              :     }
     163              : 
     164              :     void setAggregationThreshold(const int thresh) {
     165        91600 :         myAggregationThreshold = thresh;
     166              :     }
     167              : 
     168              :     int getAggregationThreshold() const {
     169            0 :         return myAggregationThreshold;
     170              :     }
     171              : 
     172              : protected:
     173              : 
     174              :     std::string buildProcessIdPrefix() const;
     175              : 
     176              :     /// @brief Builds the string which includes the mml-message type
     177      5738385 :     inline std::string build(const std::string& msg, bool addType) {
     178              :         std::string prefix;
     179      5738385 :         if (myWriteTimestamps) {
     180           12 :             prefix += "[" + StringUtils::isoTimeString() + "] ";
     181              :         }
     182      5738385 :         if (myWriteProcessId) {
     183           12 :             prefix += buildProcessIdPrefix();
     184              :         }
     185      5738385 :         if (addType) {
     186      5733672 :             switch (myType) {
     187              :                 case MsgType::MT_MESSAGE:
     188              :                     break;
     189              :                 case MsgType::MT_WARNING:
     190              :                     prefix += myWarningPrefix;
     191              :                     break;
     192              :                 case MsgType::MT_ERROR:
     193              :                     prefix += myErrorPrefix;
     194              :                     break;
     195              :                 case MsgType::MT_DEBUG:
     196              :                     prefix += "Debug: ";
     197              :                     break;
     198              :                 case MsgType::MT_GLDEBUG:
     199              :                     prefix += "GLDebug: ";
     200              :                     break;
     201              :                 default:
     202              :                     break;
     203              :             }
     204              :         }
     205      5738385 :         return prefix + msg;
     206              :     }
     207              : 
     208       542889 :     virtual bool aggregationThresholdReached(const std::string& format) {
     209       542889 :         return myAggregationThreshold >= 0 && myAggregationCount[format]++ >= myAggregationThreshold;
     210              :     }
     211              : 
     212              :     /// @brief standard constructor
     213              :     MsgHandler(MsgType type);
     214              : 
     215              :     /// @brief destructor
     216              :     virtual ~MsgHandler();
     217              : 
     218              : private:
     219              :     /// @brief The function to call for new MsgHandlers, nullptr means use default constructor
     220              :     static Factory myFactory;
     221              : 
     222              :     /// @brief The instance to handle errors
     223              :     static MsgHandler* myErrorInstance;
     224              : 
     225              :     /// @brief The instance to handle warnings
     226              :     static MsgHandler* myWarningInstance;
     227              : 
     228              :     /// @brief The instance to handle normal messages
     229              :     static MsgHandler* myMessageInstance;
     230              : 
     231              :     /// @brief Information whether a process information is printed to cout
     232              :     static bool myAmProcessingProcess;
     233              : 
     234              : private:
     235              :     /// @brief The type of the instance
     236              :     MsgType myType;
     237              : 
     238              :     /// @brief information whether an output occurred at all
     239              :     bool myWasInformed;
     240              : 
     241              :     /// @brief do not output more messages of the same type if the count exceeds this threshold
     242              :     int myAggregationThreshold;
     243              : 
     244              :     /// @brief count for messages of the same type
     245              :     std::map<const std::string, int> myAggregationCount;
     246              : 
     247              :     /// @brief The list of retrievers that shall be informed about new messages or errors
     248              :     std::vector<OutputDevice*> myRetrievers;
     249              : 
     250              :     /// @brief storage for initial messages
     251              :     std::vector<std::string> myInitialMessages;
     252              : 
     253              :     /** @brief Flag to enable or disable debug output
     254              :      *
     255              :      * This value is used to show more internal information through warning messages about certain operations
     256              :      */
     257              :     static bool myWriteDebugMessages;
     258              : 
     259              :     /// @brief Flag to enable or disable GL specific debug output
     260              :     static bool myWriteDebugGLMessages;
     261              : 
     262              :     /// @brief Whether to prefix every message with a time stamp
     263              :     static bool myWriteTimestamps;
     264              : 
     265              :     /// @brief Whether to prefix every message with the process id
     266              :     static bool myWriteProcessId;
     267              : 
     268              :     /// @brief The possibly translated error prefix (mainly for speedup)
     269              :     static std::string myErrorPrefix;
     270              : 
     271              :     /// @brief The possibly translated warning prefix (mainly for speedup)
     272              :     static std::string myWarningPrefix;
     273              : 
     274              : private:
     275              :     /// @brief invalid copy constructor
     276              :     MsgHandler(const MsgHandler& s) = delete;
     277              : 
     278              :     /// @brief invalid assignment operator
     279              :     MsgHandler& operator=(const MsgHandler& s) = delete;
     280              : };
     281              : 
     282              : 
     283              : // ===========================================================================
     284              : // global definitions
     285              : // ===========================================================================
     286              : #define WRITE_WARNING(msg) MsgHandler::getWarningInstance()->inform(msg);
     287              : #define WRITE_WARNINGF(...) MsgHandler::getWarningInstance()->informf(__VA_ARGS__);
     288              : #define WRITE_MESSAGE(msg) MsgHandler::getMessageInstance()->inform(msg);
     289              : #define WRITE_MESSAGEF(...) MsgHandler::getMessageInstance()->informf(__VA_ARGS__);
     290              : #define PROGRESS_BEGIN_MESSAGE(msg) MsgHandler::getMessageInstance()->beginProcessMsg((msg) + std::string(" ..."));
     291              : #define PROGRESS_DONE_MESSAGE() MsgHandler::getMessageInstance()->endProcessMsg2(true);
     292              : #define PROGRESS_BEGIN_TIME_MESSAGE(msg) SysUtils::getCurrentMillis(); MsgHandler::getMessageInstance()->beginProcessMsg((msg) + std::string(" ..."));
     293              : #define PROGRESS_TIME_MESSAGE(before) MsgHandler::getMessageInstance()->endProcessMsg2(true, SysUtils::getCurrentMillis() - before);
     294              : #define PROGRESS_FAILED_MESSAGE() MsgHandler::getMessageInstance()->endProcessMsg2(false);
     295              : #define WRITE_ERROR(msg) MsgHandler::getErrorInstance()->inform(msg);
     296              : #define WRITE_ERRORF(...) MsgHandler::getErrorInstance()->informf(__VA_ARGS__);
     297              : #ifdef HAVE_INTL
     298              : // basic translation
     299              : #define TL(string) gettext(string)
     300              : // complex translation ("This % an %", "is", "example")
     301              : #define TLF(string, ...) StringUtils::format(gettext(string), __VA_ARGS__)
     302              : #else
     303              : // basic translation
     304              : #define TL(string) (string)
     305              : // complex translation ("This % an %", "is", "example")
     306              : #define TLF(string, ...) StringUtils::format(string, __VA_ARGS__)
     307              : #endif
        

Generated by: LCOV version 2.0-1