Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
MsgHandler.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3// Copyright (C) 2001-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/****************************************************************************/
20// Retrieves messages about the process and gives them further to output
21/****************************************************************************/
22#include <config.h>
23
24#include <string>
25#include <cassert>
26#include <vector>
27#include <algorithm>
28#include <iostream>
29#ifdef WIN32
30#define NOMINMAX
31#include <windows.h>
32#undef NOMINMAX
33#else
34#include <unistd.h>
35#endif
39#include "MsgHandler.h"
40
41
42// ===========================================================================
43// static member variables
44// ===========================================================================
54std::string MsgHandler::myErrorPrefix = "Error: ";
55std::string MsgHandler::myWarningPrefix = "Warning: ";
56
57
58// ===========================================================================
59// method definitions
60// ===========================================================================
61
73
74
86
87
95
96
97void
101
102void
106
107
108std::string
109MsgHandler::insertLineBreaks(std::string msg, int lineWidth) {
110 // TODO: check what FXFont::getTextWidth can do
111 //int textWidth = getApp()->getNormalFont()->getTextWidth
112 if ((int)msg.size() <= lineWidth) {
113 return msg;
114 }
115 size_t pos = 0;
116 size_t nextLineBreak = msg.find('\n');
117 size_t spaceAfterLine = msg.find(' ', lineWidth);
118 while (spaceAfterLine != std::string::npos) {
119 if (nextLineBreak == std::string::npos || nextLineBreak > spaceAfterLine) {
120 msg = msg.replace(spaceAfterLine, 1, "\n");
121 pos = spaceAfterLine + 1;
122 } else {
123 pos = nextLineBreak + 1;
124 }
125 spaceAfterLine = msg.find(' ', pos + lineWidth);
126 nextLineBreak = msg.find('\n', pos);
127 }
128 return msg;
129}
130
131
132void
133MsgHandler::inform(std::string msg, bool addType) {
134 if (addType && !myInitialMessages.empty() && myInitialMessages.size() < 5) {
135 myInitialMessages.push_back(msg);
136 }
137 // beautify progress output
139 myAmProcessingProcess = false;
141 }
142 msg = build(msg, addType);
143 // inform all receivers
144 for (auto i : myRetrievers) {
145 i->inform(msg);
146 }
147 // set the information that something occurred
148 myWasInformed = true;
149}
150
151
152void
153MsgHandler::beginProcessMsg(std::string msg, bool addType) {
154 msg = build(msg, addType);
155 // inform all other receivers
156 for (auto i : myRetrievers) {
157 i->inform(msg, true);
159 }
160 // set the information that something occurred
161 myWasInformed = true;
162}
163
164
165void
166MsgHandler::endProcessMsg2(bool success, long duration) {
167 if (success) {
168 if (duration > -1) {
169 endProcessMsg(TLF(" done (%ms).", toString(duration)));
170 } else {
171 endProcessMsg(TL(" done."));
172 }
173 } else {
174 endProcessMsg(TL(" failed."));
175 }
176}
177
178
179void
181 // inform all other receivers
182 for (auto i : myRetrievers) {
183 i->inform(msg);
184 }
185 // set the information that something occurred
186 myWasInformed = true;
187 myAmProcessingProcess = false;
188}
189
190
191void
192MsgHandler::clear(bool resetInformed) {
193 if (myAggregationThreshold >= 0) {
194 for (const auto& i : myAggregationCount) {
195 if (i.second > myAggregationThreshold) {
196 inform(toString(i.second) + " total messages of type: " + i.first);
197 }
198 }
199 }
200 myAggregationCount.clear();
201 if (!resetInformed && myInitialMessages.size() > 1) {
202 const bool wasInformed = myWasInformed;
203 for (const std::string& msg : myInitialMessages) {
204 inform(msg, false);
205 }
206 myInitialMessages.clear();
208 }
209 if (resetInformed) {
210 myWasInformed = false;
211 }
212}
213
214
215void
217 if (!isRetriever(retriever)) {
218 myRetrievers.push_back(retriever);
219 }
220}
221
222
223void
225 std::vector<OutputDevice*>::iterator i = find(myRetrievers.begin(), myRetrievers.end(), retriever);
226 if (i != myRetrievers.end()) {
227 myRetrievers.erase(i);
228 }
229}
230
231
232bool
234 return std::find(myRetrievers.begin(), myRetrievers.end(), retriever) != myRetrievers.end();
235}
236
237
238void
240 if (myErrorInstance != nullptr) {
242 }
243 if (myWarningInstance != nullptr) {
245 }
246 if (myMessageInstance != nullptr) {
248 }
249}
250
251
252void
253MsgHandler::setupI18n(const std::string& locale) {
254#ifdef HAVE_INTL
255 if (locale != "") {
256#ifdef WIN32
257 _putenv_s("LANGUAGE", locale.data());
258#else
259 setenv("LANGUAGE", locale.data(), true);
260#endif
261 }
262 if (!setlocale(LC_MESSAGES, "")) {
263 WRITE_WARNINGF(TL("Could not set locale to '%'."), locale);
264 }
265 const char* sumoPath = getenv("SUMO_HOME");
266 if (sumoPath == nullptr) {
267 if (!bindtextdomain("sumo", nullptr)) {
268 WRITE_WARNING(TL("Environment variable SUMO_HOME is not set, could not find localized messages."));
269 return;
270 }
271 } else {
272 const std::string path = sumoPath + std::string("/data/locale/");
273 if (!bindtextdomain("sumo", path.data())) {
274 WRITE_WARNING(TL("Could not find localized messages."));
275 return;
276 }
277 }
278 bind_textdomain_codeset("sumo", "UTF-8");
279 textdomain("sumo");
280#ifdef WIN32
281 SetConsoleOutputCP(CP_UTF8);
282#endif
283#else
284 UNUSED_PARAMETER(locale);
285#endif
286 myWarningPrefix = TL("Warning: ");
287 myErrorPrefix = TL("Error: ");
288 gLocaleInitialized = true;
289}
290
291
292void
294 // initialize console properly
295 OutputDevice::getDevice("stdout");
296 OutputDevice::getDevice("stderr");
298 getWarningInstance()->setAggregationThreshold(oc.getInt("aggregate-warnings"));
299 getErrorInstance()->setAggregationThreshold(oc.getInt("aggregate-warnings"));
300 if (oc.getBool("no-warnings")) {
302 }
303 // build the logger if possible
304 if (oc.isSet("log", false)) {
305 OutputDevice* logFile = &OutputDevice::getDevice(oc.getString("log"));
306 getErrorInstance()->addRetriever(logFile);
307 if (!oc.getBool("no-warnings")) {
309 }
311 if (oc.getBool("log.timestamps")) {
312 myWriteTimestamps = true;
313 }
314 if (oc.getBool("log.processid")) {
315 myWriteProcessId = true;
316 }
317 }
318 if (oc.isSet("message-log", false)) {
319 OutputDevice* logFile = &OutputDevice::getDevice(oc.getString("message-log"));
321 }
322 if (oc.isSet("error-log", false)) {
323 OutputDevice* logFile = &OutputDevice::getDevice(oc.getString("error-log"));
324 getErrorInstance()->addRetriever(logFile);
326 }
327 if (oc.getBool("verbose")) {
328 getErrorInstance()->myInitialMessages.push_back("Repeating initial error messages:");
329 } else {
331 }
332}
333
334
335void
337 delete myMessageInstance;
338 myMessageInstance = nullptr;
339 delete myWarningInstance;
340 myWarningInstance = nullptr;
341 delete myErrorInstance;
342 myErrorInstance = nullptr;
343}
344
345
346std::string
348 std::stringstream prefix;
349 prefix << "[PID: ";
350#ifdef WIN32
351 prefix << GetCurrentProcessId();
352#else
353 prefix << getpid();
354#endif
355 prefix << "] ";
356 return prefix.str();
357}
358
359
361 myType(type), myWasInformed(false), myAggregationThreshold(-1) {
362 if (type == MsgType::MT_MESSAGE) {
364 } else {
366 }
367}
368
369
372
373
374bool
376 return myWasInformed;
377}
378
379
380/****************************************************************************/
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_WARNING(msg)
Definition MsgHandler.h:286
#define TL(string)
Definition MsgHandler.h:304
#define TLF(string,...)
Definition MsgHandler.h:306
bool gLocaleInitialized
Definition StdDefs.cpp:34
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
virtual void addRetriever(OutputDevice *retriever)
Adds a further retriever to the instance responsible for a certain msg type.
std::vector< std::string > myInitialMessages
storage for initial messages
Definition MsgHandler.h:251
bool wasInformed() const
Returns the information whether any messages were added.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
virtual void inform(std::string msg, bool addType=true)
adds a new error to the list
static void enableDebugGLMessages(bool enable)
enable/disable gl-debug messages
static std::string insertLineBreaks(std::string msg, int lineWidth)
reformats a long string to contain newline after a certain line length in px (depending on the curren...
virtual void endProcessMsg(std::string msg)
Ends a process information.
std::string buildProcessIdPrefix() const
std::string build(const std::string &msg, bool addType)
Builds the string which includes the mml-message type.
Definition MsgHandler.h:177
static Factory myFactory
The function to call for new MsgHandlers, nullptr means use default constructor.
Definition MsgHandler.h:220
bool myWasInformed
information whether an output occurred at all
Definition MsgHandler.h:239
static bool myWriteTimestamps
Whether to prefix every message with a time stamp.
Definition MsgHandler.h:263
static void setupI18n(const std::string &locale="")
set up gettext stuff
static void initOutputOptions()
init output options
static MsgHandler * myErrorInstance
The instance to handle errors.
Definition MsgHandler.h:223
static MsgHandler * myMessageInstance
The instance to handle normal messages.
Definition MsgHandler.h:229
bool isRetriever(OutputDevice *retriever) const
Returns whether the given output device retrieves messages from the handler.
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
std::map< const std::string, int > myAggregationCount
count for messages of the same type
Definition MsgHandler.h:245
static void enableDebugMessages(bool enable)
enable/disable debug messages
static bool myAmProcessingProcess
Information whether a process information is printed to cout.
Definition MsgHandler.h:232
std::vector< OutputDevice * > myRetrievers
The list of retrievers that shall be informed about new messages or errors.
Definition MsgHandler.h:248
MsgHandler *(* Factory)(MsgType)
Definition MsgHandler.h:60
virtual ~MsgHandler()
destructor
virtual void clear(bool resetInformed=true)
Clears information whether an error occurred previously and print aggregated message summary.
void setAggregationThreshold(const int thresh)
Definition MsgHandler.h:164
static MsgHandler * myWarningInstance
The instance to handle warnings.
Definition MsgHandler.h:226
virtual void endProcessMsg2(bool success, long duration=-1)
Ends a process information with predefined messages.
virtual void beginProcessMsg(std::string msg, bool addType=true)
Begins a process information.
static bool myWriteDebugMessages
Flag to enable or disable debug output.
Definition MsgHandler.h:257
static bool myWriteDebugGLMessages
Flag to enable or disable GL specific debug output.
Definition MsgHandler.h:260
static std::string myWarningPrefix
The possibly translated warning prefix (mainly for speedup)
Definition MsgHandler.h:272
static bool myWriteProcessId
Whether to prefix every message with the process id.
Definition MsgHandler.h:266
static void cleanupOnEnd()
Removes pending handler.
static std::string myErrorPrefix
The possibly translated error prefix (mainly for speedup)
Definition MsgHandler.h:269
static void removeRetrieverFromAllInstances(OutputDevice *out)
ensure that that given output device is no longer used as retriever by any instance
virtual void removeRetriever(OutputDevice *retriever)
Removes the retriever from the handler.
int myAggregationThreshold
do not output more messages of the same type if the count exceeds this threshold
Definition MsgHandler.h:242
@ MT_MESSAGE
The message is only something to show.
@ MT_ERROR
The message is an error.
@ MT_WARNING
The message is a warning.
MsgHandler(MsgType type)
standard constructor
static MsgHandler * getMessageInstance()
Returns the instance to add normal messages to.
A storage for options typed value containers)
Definition OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
#define UNUSED_PARAMETER(x)