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())
162 if (timestamp.count() > 1000)
164 return *this << std::chrono::duration_cast<std::chrono::microseconds>(timestamp);
167 currentMessage << timestamp.count() <<
" ns";
174 if (timestamp.count() > 1000)
176 return *this << std::chrono::duration_cast<std::chrono::milliseconds>(timestamp);
179 if (timestamp.count() <= 1. / 1000)
181 return *this << std::chrono::duration_cast<std::chrono::nanoseconds>(timestamp);
184 currentMessage << timestamp.count() <<
" µs";
191 if (timestamp.count() > 1000)
193 return *this << std::chrono::duration_cast<std::chrono::seconds>(timestamp);
196 if (timestamp.count() <= 1. / 1000)
198 return *this << std::chrono::duration_cast<std::chrono::microseconds>(timestamp);
201 currentMessage << timestamp.count() <<
" ms";
208 if (timestamp.count() > 60)
210 return *this << std::chrono::duration_cast<std::chrono::minutes>(timestamp);
213 if (timestamp.count() <= 1. / 1000)
215 return *this << std::chrono::duration_cast<std::chrono::milliseconds>(timestamp);
218 currentMessage << timestamp.count() <<
" s";
225 if (timestamp.count() < 1. / 60)
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)
262 return *
this << timestamp.toDateTime();
310 std::stringstream stream;
319 stream <<
"\033[3" << colorCode <<
"m";
326 LogSender::resetLocation()
328 impl->currentFile =
"";
329 impl->currentLine = -1;
330 impl->currentFunction =
"";
337 if (impl->cancelNextMessage)
339 impl->cancelNextMessage =
false;
348 if (severity < impl->minimumLoggingLevel)
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) +
"]" +
"[" +
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;
796 LogSender& LogSender::operator<< <LogTag>(
const LogTag& tag)
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";
835 LogSender& LogSender::operator<< <SpamFilterDataPtr>(
const SpamFilterDataPtr& spamFilterData)
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;