28 #include <ArmarXCore/interface/core/Log.h>
33 #include <sys/syscall.h>
38 #include <boost/logic/tribool.hpp>
40 #include <SimoxUtility/algorithm/string/string_tools.h>
42 #include <IceUtil/Time.h>
90 return std::make_shared<LogSender>();
104 impl->cancelNextMessage =
false;
106 impl->printBackTrace = boost::logic::indeterminate;
118 impl->cancelNextMessage =
false;
120 impl->printBackTrace =
true;
129 if (!currentMessage.str().empty())
169 if (timestamp.count() > 1000)
171 return *this << std::chrono::duration_cast<std::chrono::microseconds>(timestamp);
174 currentMessage << timestamp.count() <<
" ns";
180 if (timestamp.count() > 1000)
182 return *this << std::chrono::duration_cast<std::chrono::milliseconds>(timestamp);
185 if (timestamp.count() <= 1. / 1000)
187 return *this << std::chrono::duration_cast<std::chrono::nanoseconds>(timestamp);
190 currentMessage << timestamp.count() <<
" µs";
196 if (timestamp.count() > 1000)
198 return *this << std::chrono::duration_cast<std::chrono::seconds>(timestamp);
201 if (timestamp.count() <= 1. / 1000)
203 return *this << std::chrono::duration_cast<std::chrono::microseconds>(timestamp);
206 currentMessage << timestamp.count() <<
" ms";
212 if (timestamp.count() > 60)
214 return *this << std::chrono::duration_cast<std::chrono::minutes>(timestamp);
217 if (timestamp.count() <= 1. / 1000)
219 return *this << std::chrono::duration_cast<std::chrono::milliseconds>(timestamp);
222 currentMessage << timestamp.count() <<
" s";
228 if (timestamp.count() < 1. / 60)
230 return *this << std::chrono::duration_cast<std::chrono::seconds>(timestamp);
233 currentMessage << timestamp.count() <<
" min";
239 double time_count = timestamp.toMicroSecondsDouble();
240 std::string unit =
"µs";
242 if (time_count >= 1000)
247 if (time_count >= 1000)
252 if (time_count >= 60)
257 if (time_count >= 60)
262 if (time_count >= 24)
264 return *
this << timestamp.toDateTime();
309 std::stringstream stream;
313 stream <<
"\033[0" <<
"m";
317 stream <<
"\033[3" << colorCode <<
"m";
323 void LogSender::resetLocation()
325 impl->currentFile =
"";
326 impl->currentLine = -1;
327 impl->currentFunction =
"";
333 if (impl->cancelNextMessage)
335 impl->cancelNextMessage =
false;
344 if (severity < impl->minimumLoggingLevel)
360 if (!impl->currentTag.tagName.empty())
362 catStr =
"[" + impl->currentTag.tagName +
"]: ";
369 std::string outputStr;
377 outputStr +=
"\033[1m";
381 outputStr +=
"[" + time.toDateTime().substr(time.toDateTime().find(
' ') + 1) +
"]" +
"[" +
LogSender_componentName +
"]" + catStr;
398 msg.time = time.toMicroSeconds();
399 msg.tag = impl->currentTag.tagName;
400 msg.type = (MessageType)severity;
402 msg.file = impl->currentFile;
403 msg.line = impl->currentLine;
404 msg.function = impl->currentFunction;
405 msg.threadId = impl->threadId ? *impl->threadId :
getThreadId();
407 if ((severity >=
MessageTypeT::WARN && boost::logic::indeterminate(impl->printBackTrace))
408 || impl->printBackTrace)
442 std::cout << outputStr << std::endl;
449 return syscall(SYS_gettid);
465 log(impl->currentSeverity, currentMessage.str());
466 currentMessage.str(
"");
471 unsigned int maxLength = 40;
474 if (originalFunctionName.length() <= maxLength)
476 return originalFunctionName;
479 std::string beforeFunctionName = originalFunctionName.substr(0, originalFunctionName.rfind(
"::"));
480 std::string::size_type namespaceDotsPos = beforeFunctionName.find(
"::", beforeFunctionName.find(
' '));
482 if (namespaceDotsPos != std::string::npos)
484 std::string afterClassName = originalFunctionName.substr(originalFunctionName.rfind(
"::"));
485 result = beforeFunctionName.substr(namespaceDotsPos + 2) + afterClassName;
489 result = originalFunctionName;
492 if (result.length() <= maxLength)
498 result = result.substr(0, result.find(
"("));
510 void* callstack[128];
511 const int nMaxFrames =
sizeof(callstack) /
sizeof(callstack[0]);
514 int nFrames = ::backtrace(callstack, nMaxFrames);
515 char** symbols = backtrace_symbols(callstack, nFrames);
517 std::ostringstream trace_buf;
519 for (
int i = linesToSkip; i < nFrames; i++)
523 if (dladdr(callstack[i], &info) && info.dli_sname)
525 char* demangled =
nullptr;
528 if (info.dli_sname[0] ==
'_')
530 demangled = abi::__cxa_demangle(info.dli_sname,
nullptr,
nullptr, &
status);
533 snprintf(buf,
sizeof(buf),
"%-3d %*p %s + %zd\n",
534 i - linesToSkip + 1,
int(2 +
sizeof(
void*) * 2), callstack[i],
536 info.dli_sname ==
nullptr ? symbols[i] : info.dli_sname,
537 (
char*)callstack[i] - (
char*)info.dli_saddr);
542 snprintf(buf,
sizeof(buf),
"%-3d %*p %s\n",
543 i - linesToSkip + 1,
int(2 +
sizeof(
void*) * 2), callstack[i], symbols[i]);
551 if (nFrames == nMaxFrames)
553 trace_buf <<
"[truncated]\n";
556 return trace_buf.str();
561 return impl->currentSeverity;
566 impl->currentFile = file;
567 return shared_from_this();
572 impl->currentLine = line;
573 return shared_from_this();
578 impl->currentFunction =
function;
579 return shared_from_this();
584 impl->minimumLoggingLevel = level;
585 return shared_from_this();
590 impl->printBackTrace = printBackTrace;
591 return shared_from_this();
595 impl->threadId = tid;
596 return shared_from_this();
601 impl->currentTag = tag;
602 return shared_from_this();
643 if (simox::alg::to_lower(typeStr) ==
"debug")
648 if (simox::alg::to_lower(typeStr) ==
"verbose")
653 if (simox::alg::to_lower(typeStr) ==
"important")
658 if (simox::alg::to_lower(typeStr) ==
"warning")
663 if (simox::alg::to_lower(typeStr) ==
"error")
668 if (simox::alg::to_lower(typeStr) ==
"fatal")
698 std::cout <<
"logging is now DEACTIVATED" << std::endl;
703 std::cout <<
"logging is now ACTIVATED" << std::endl;
718 void LogSender::initConsole()
720 static bool initialized =
false;
725 char* termType = getenv(
"TERM");
727 if (termType !=
nullptr)
729 std::string termTypeStr(termType);
731 if (termTypeStr !=
"xterm"
732 && termTypeStr !=
"emacs"
733 && termTypeStr !=
"xterm-256color")
758 LogSender& LogSender::operator<< <MessageTypeT>(
const MessageTypeT& severity)
760 impl->currentSeverity = severity;
766 LogSender& LogSender::operator<< <LogTag>(
const LogTag& tag)
768 impl->currentTag =
tag;
774 LogSender& LogSender::operator<< <LogSender::manipulator>(
const manipulator& manipulator)
776 (this->*manipulator)();
789 LogSender& LogSender::operator<< <bool>(
const bool& duality)
793 currentMessage <<
"true";
797 currentMessage <<
"false";
804 LogSender& LogSender::operator<< <SpamFilterDataPtr>(
const SpamFilterDataPtr& spamFilterData)
811 std::unique_lock lock(*spamFilterData->mutex);
812 float deactivationDurationSec = spamFilterData->durationSec;
814 std::string
id = impl->currentFile +
":" +
to_string(impl->currentLine);
815 auto it = spamFilter->find(spamFilterData->identifier);
817 if (it != spamFilter->end())
819 auto itSub = it->second.find(
id);
820 IceUtil::Time durationEnd = IceUtil::Time::now() + IceUtil::Time::milliSecondsDouble(deactivationDurationSec * 1000);
822 if (itSub == it->second.end())
824 itSub = it->second.insert(
828 impl->cancelNextMessage =
false;
830 else if (IceUtil::Time::now() < itSub->second)
832 impl->cancelNextMessage =
true;
836 impl->cancelNextMessage =
false;
837 itSub->second = durationEnd;