31#include <sys/syscall.h>
33#include <boost/logic/tribool.hpp>
35#include <IceUtil/Time.h>
37#include <SimoxUtility/algorithm/string/string_tools.h>
40#include <ArmarXCore/interface/core/Log.h>
86 return std::make_shared<LogSender>();
97 impl->cancelNextMessage =
false;
99 impl->printBackTrace = boost::logic::indeterminate;
108 impl->cancelNextMessage =
false;
110 impl->printBackTrace =
true;
119 if (!currentMessage.str().empty())
164 return *this << std::chrono::duration_cast<std::chrono::microseconds>(
timestamp);
167 currentMessage <<
timestamp.count() <<
" ns";
176 return *this << std::chrono::duration_cast<std::chrono::milliseconds>(
timestamp);
181 return *this << std::chrono::duration_cast<std::chrono::nanoseconds>(
timestamp);
184 currentMessage <<
timestamp.count() <<
" µs";
193 return *this << std::chrono::duration_cast<std::chrono::seconds>(
timestamp);
198 return *this << std::chrono::duration_cast<std::chrono::microseconds>(
timestamp);
201 currentMessage <<
timestamp.count() <<
" ms";
210 return *this << std::chrono::duration_cast<std::chrono::minutes>(
timestamp);
215 return *this << std::chrono::duration_cast<std::chrono::milliseconds>(
timestamp);
218 currentMessage <<
timestamp.count() <<
" s";
227 return *this << std::chrono::duration_cast<std::chrono::seconds>(
timestamp);
230 currentMessage <<
timestamp.count() <<
" min";
237 double time_count =
timestamp.toMicroSecondsDouble();
238 std::string unit =
"µs";
240 if (time_count >= 1000)
245 if (time_count >= 1000)
250 if (time_count >= 60)
255 if (time_count >= 60)
260 if (time_count >= 24)
269 return *
this << std::to_string(time_count) +
" " + unit;
310 std::stringstream stream;
319 stream <<
"\033[3" << colorCode <<
"m";
326 LogSender::resetLocation()
328 impl->currentFile =
"";
329 impl->currentLine = -1;
330 impl->currentFunction =
"";
336 simox::alg::trim(message);
337 if (impl->cancelNextMessage)
339 impl->cancelNextMessage =
false;
348 if (severity < impl->minimumLoggingLevel)
359 IceUtil::Time time = IceUtil::Time::now();
363 if (!impl->currentTag.tagName.empty())
365 catStr =
"[" + impl->currentTag.tagName +
"]: ";
372 std::string outputStr;
380 outputStr +=
"\033[1m";
384 outputStr +=
"[" + time.toDateTime().substr(time.toDateTime().find(
' ') + 1) +
"]" +
"[" +
392 outputStr += message;
402 msg.time = time.toMicroSeconds();
403 msg.tag = impl->currentTag.tagName;
404 msg.type = (MessageType)severity;
406 msg.file = impl->currentFile;
407 msg.line = impl->currentLine;
408 msg.function = impl->currentFunction;
409 msg.threadId = impl->threadId ? *impl->threadId :
getThreadId();
411 if ((severity >=
MessageTypeT::WARN && boost::logic::indeterminate(impl->printBackTrace)) ||
412 impl->printBackTrace)
426 std::unique_lock lock(
447 std::cout << outputStr << std::endl;
455 return syscall(SYS_gettid);
472 log(impl->currentSeverity, currentMessage.str());
473 currentMessage.str(
"");
479 unsigned int maxLength = 40;
482 if (originalFunctionName.length() <= maxLength)
484 return originalFunctionName;
487 std::string beforeFunctionName =
488 originalFunctionName.substr(0, originalFunctionName.rfind(
"::"));
489 std::string::size_type namespaceDotsPos =
490 beforeFunctionName.find(
"::", beforeFunctionName.find(
' '));
492 if (namespaceDotsPos != std::string::npos)
494 std::string afterClassName =
495 originalFunctionName.substr(originalFunctionName.rfind(
"::"));
496 result = beforeFunctionName.substr(namespaceDotsPos + 2) + afterClassName;
500 result = originalFunctionName;
503 if (result.length() <= maxLength)
509 result = result.substr(0, result.find(
"("));
518 void* callstack[128];
519 const int nMaxFrames =
sizeof(callstack) /
sizeof(callstack[0]);
522 int nFrames = ::backtrace(callstack, nMaxFrames);
523 char** symbols = backtrace_symbols(callstack, nFrames);
525 std::ostringstream trace_buf;
527 for (
int i = linesToSkip; i < nFrames; i++)
531 if (dladdr(callstack[i], &info) && info.dli_sname)
533 char* demangled =
nullptr;
536 if (info.dli_sname[0] ==
'_')
538 demangled = abi::__cxa_demangle(info.dli_sname,
nullptr,
nullptr, &
status);
543 "%-3d %*p %s + %zd\n",
545 int(2 +
sizeof(
void*) * 2),
548 : info.dli_sname ==
nullptr ? symbols[i]
550 (
char*)callstack[i] - (
char*)info.dli_saddr);
559 int(2 +
sizeof(
void*) * 2),
569 if (nFrames == nMaxFrames)
571 trace_buf <<
"[truncated]\n";
574 return trace_buf.str();
580 return impl->currentSeverity;
586 impl->currentFile = file;
587 return shared_from_this();
593 impl->currentLine = line;
594 return shared_from_this();
600 impl->currentFunction = function;
601 return shared_from_this();
607 impl->minimumLoggingLevel = level;
608 return shared_from_this();
614 impl->printBackTrace = printBackTrace;
615 return shared_from_this();
621 impl->threadId = tid;
622 return shared_from_this();
628 impl->currentTag = tag;
629 return shared_from_this();
672 if (simox::alg::to_lower(typeStr) ==
"debug")
677 if (simox::alg::to_lower(typeStr) ==
"verbose")
682 if (simox::alg::to_lower(typeStr) ==
"important")
687 if (simox::alg::to_lower(typeStr) ==
"warning")
692 if (simox::alg::to_lower(typeStr) ==
"error")
697 if (simox::alg::to_lower(typeStr) ==
"fatal")
729 std::cout <<
"logging is now DEACTIVATED" << std::endl;
734 std::cout <<
"logging is now ACTIVATED" << std::endl;
752 LogSender::initConsole()
754 static bool initialized =
false;
759 char* termType = getenv(
"TERM");
761 if (termType !=
nullptr)
763 std::string termTypeStr(termType);
765 if (termTypeStr !=
"xterm" && termTypeStr !=
"emacs" &&
766 termTypeStr !=
"xterm-256color")
788 LogSender& LogSender::operator<< <MessageTypeT>(
const MessageTypeT& severity)
790 impl->currentSeverity = severity;
798 impl->currentTag =
tag;
804 LogSender& LogSender::operator<< <LogSender::manipulator>(
const manipulator& manipulator)
806 (this->*manipulator)();
820 LogSender& LogSender::operator<< <bool>(
const bool& duality)
824 currentMessage <<
"true";
828 currentMessage <<
"false";
842 std::unique_lock lock(*spamFilterData->mutex);
843 float deactivationDurationSec = spamFilterData->durationSec;
845 std::string
id = impl->currentFile +
":" +
to_string(impl->currentLine);
846 auto it = spamFilter->find(spamFilterData->identifier);
848 if (it != spamFilter->end())
850 auto itSub = it->second.find(
id);
851 IceUtil::Time durationEnd = IceUtil::Time::now() + IceUtil::Time::milliSecondsDouble(
852 deactivationDurationSec * 1000);
854 if (itSub == it->second.end())
856 itSub = it->second.insert(std::make_pair(
id, durationEnd)).first;
857 impl->cancelNextMessage =
false;
859 else if (IceUtil::Time::now() < itSub->second)
861 impl->cancelNextMessage =
true;
865 impl->cancelNextMessage =
false;
866 itSub->second = durationEnd;
#define ARMARXCORE_IMPORT_EXPORT
Wrapper for the Log IceStorm topic with convenience methods for logging.
static std::string CropFunctionName(const std::string &originalFunctionName)
LogSenderPtr setFile(const std::string &file)
Set the source code filename associated with this message.
static std::string GetColorCodeString(MessageTypeT verbosityLevel)
static void SetGlobalMinimumLoggingLevel(MessageTypeT level)
With setGlobalMinimumLoggingLevel the minimum verbosity-level of log-messages can be set for the whol...
static std::string CreateBackTrace(int linesToSkip=1)
LogSenderPtr setTag(const LogTag &tag)
LogSenderPtr setFunction(const std::string &function)
Set the function name associated with this message.
LogSenderPtr setLocalMinimumLoggingLevel(MessageTypeT level)
static void SetLoggingGroup(const std::string &loggingGroup)
static LogSenderPtr createLogSender()
MessageTypeT getSeverity()
Retrieves the current message severity.
void(LogSender::* manipulator)()
LogSenderPtr setBacktrace(bool printBackTrace)
static long getProcessId()
LogSender & operator<<(const T &message)
Appends a variable to the current message stringstream.
void log(MessageTypeT severity, std::string message)
Sends a message to the logging component.
LogSenderPtr setLine(int line)
Set the source code line associated with this message.
static long getThreadId()
static void SetColoredConsoleActivated(bool activated=true)
LogSenderPtr setThreadId(Ice::Int tid)
CoutType &(* StandardEndLine)(CoutType &)
static void SetComponentName(const std::string &componentName)
static void SetSendLoggingActivated(bool activated=true)
void flush()
Sends the current message to the log and resets the content.
static std::string levelToString(MessageTypeT type)
static MessageTypeT GetGlobalMinimumLoggingLevel()
static MessageTypeT StringToLevel(const std::string &typeStr)
stringToLevel converts a string into a LoggingLevel, if possible.
static void setProxy(const std::string &componentName, LogPrx logProxy)
static void SetLoggingActivated(bool activated=true, bool showMessage=true)
setLoggingActivated() is used to activate or disable the logging facilities in the whole application
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::Log > LogPrx
bool LogSender_ColoringActivated
std::ostream LogSender_outbuf(std::cout.rdbuf())
LogSender::ConsoleColor GetColorCode(MessageType type)
std::shared_ptr< SpamFilterData > SpamFilterDataPtr
LogPrx LogSender_logProxy
bool LogSender_LoggingActivated
std::vector< LogMessage > LogSender_buffer
bool LogSender_SendLogging
std::ostream LogSender_errbuf(std::cerr.rdbuf())
std::shared_ptr< LogSender > LogSenderPtr
Typedef of std::shared_ptr for convenience.
std::shared_ptr< SpamFilterMap > SpamFilterMapPtr
const std::string & to_string(const std::string &s)
MessageTypeT LogSender_GlobalMinimumLoggingLevel
std::string LogSender_componentName
std::string LogSender_loggingGroup
boost::logic::tribool printBackTrace
std::string currentFunction
std::optional< Ice::Int > threadId
MessageTypeT minimumLoggingLevel
Flag to specify a minimum logging level for this LogSender usually is set by Logging-Class.
MessageTypeT currentSeverity
SpamFilterMapPtr spamFilter