trace.cpp
Go to the documentation of this file.
1 #include "trace.h"
2 
3 #include <cmath>
4 #include <deque>
5 #include <iomanip>
6 #include <iostream>
7 #include <memory>
8 
9 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
10 // /////////////////////////////////////////////// debug /////////////////////////////////////////////// //
11 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
12 #define ACTIVATE_TRACE_LIB_TERMINATE_ON_INTERNAL_ERROR
13 #ifdef ACTIVATE_TRACE_LIB_TERMINATE_ON_INTERNAL_ERROR
14 #define TerminateIf(...) \
15  { \
16  if (__VA_ARGS__) \
17  { \
18  std::cerr << "TERMINATING!:\n (" << #__VA_ARGS__ << ") == true\n " \
19  << "'" << BOOST_CURRENT_FUNCTION << "' @ " << __LINE__ << " in '" \
20  << __FILE__ << "'\n " \
21  << "Stack Trace:\n"; \
22  Trace::PrintStackTrace(std::cerr, " "); \
23  std::cerr << std::flush; \
24  std::terminate(); \
25  } \
26  } \
27  do \
28  { \
29  } while (false)
30 #else
31 #define TerminateIf(...) \
32  do \
33  { \
34  } while (false)
35 #endif
36 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
37 // /////////////////////////////////////////////// types /////////////////////////////////////////////// //
38 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
39 namespace armarx::detail
40 {
42  {
43  static void PrintExceptionBacktrace(std::ostream& out, const std::string& pre);
44  static void ClearExceptionBacktrace();
45 
46  static thread_local ExceptionBacktraceTree* Active;
47  static thread_local std::deque<ExceptionBacktraceTree> All;
48 
49  friend class Trace;
50 
52  parent{parent},
53  parentEntryOffset{parent ? parent->entries.size() : 0},
55  {
56  }
57 
59  const std::size_t parentEntryOffset;
60 
61  std::size_t currentStackSize;
62  std::deque<ExceptionBacktraceTree> children;
63  std::deque<LocationProvider> entries;
64 
65  void
66  addEntry(const Trace* t) noexcept
67  {
68  entries.emplace_back(t->location);
70  }
71 
72  void print(std::ostream& out, const std::string& prefix = "", std::size_t levelOffset = 0);
73  };
74 } // namespace armarx::detail
75 
76 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
77 // //////////////////////////////////////////////// data /////////////////////////////////////////////// //
78 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
79 namespace armarx::detail
80 {
81  thread_local const Trace* Trace::Top = nullptr;
82  thread_local std::uintmax_t Trace::Size = 0;
83  thread_local ExceptionBacktraceTree* ExceptionBacktraceTree::Active = nullptr;
84  thread_local std::deque<ExceptionBacktraceTree> ExceptionBacktraceTree::All;
85 } // namespace armarx::detail
86 
87 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
88 // ///////////////////////////////////////////// management //////////////////////////////////////////// //
89 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
90 namespace armarx::detail
91 {
92  void
94  {
97  }
98 
99  void
101  {
103  }
104 
106  {
107  TerminateIf(Top != this);
108  if (exceptional())
109  {
111  {
112  if (Size > ExceptionBacktraceTree::Active->currentStackSize)
113  {
114  //add subtree
119  }
120  while (Size == (ExceptionBacktraceTree::Active->parent
121  ? ExceptionBacktraceTree::Active->parent->currentStackSize
122  : 0))
123  {
124  //go to parent tree
126  }
127  }
128  else
129  {
130  //add new root tree
131  ExceptionBacktraceTree::All.emplace_back(nullptr);
133  }
134  //add entry to curent tree
138  ? ExceptionBacktraceTree::Active->parent->currentStackSize
139  : 0))
140  {
141  //go to parent tree
143  }
144  }
146  {
148  auto& deque = p ? p->children : ExceptionBacktraceTree::All;
150  deque.pop_back();
152  }
153  Top = parent;
154  --Size;
155  }
156 } // namespace armarx::detail
157 
158 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
159 // /////////////////////////////////////////////// output ////////////////////////////////////////////// //
160 // ///////////////////////////////////////////////////////////////////////////////////////////////////// //
161 namespace armarx::detail
162 {
163  std::ostream&
164  operator<<(std::ostream& out, const LocationProvider::Location& l)
165  {
166  return out << l.file << ":" << l.line << " : " << l.func;
167  }
168 
169  std::ostream&
170  operator<<(std::ostream& out, const LocationProvider& t)
171  {
172  return out << t.location();
173  }
174 
175  std::ostream&
176  operator<<(std::ostream& out, const Trace& t)
177  {
178  return out << t.location;
179  }
180 
181  void
182  Trace::PrintStackTrace(std::ostream& out, const std::string& pre)
183  {
184  const Trace* trace = Top;
185 
186  const auto numW = Size ? std::log10(Size) + 1 : 1;
187 
188  for (std::uintmax_t cnt = 0; trace; ++cnt, trace = trace->parent)
189  {
190  out << pre << std::setw(numW) << cnt << std::setw(0) << ": " << *trace << "\n";
191  }
192  }
193 
194  void
195  ExceptionBacktraceTree::PrintExceptionBacktrace(std::ostream& out, const std::string& pre)
196  {
197  const auto numW = ExceptionBacktraceTree::All.size()
198  ? std::log10(ExceptionBacktraceTree::All.size()) + 1
199  : 1;
200  for (std::size_t i = 0; i < ExceptionBacktraceTree::All.size(); ++i)
201  {
202  if (i)
203  {
204  out << "--------------------------" << std::string(numW, '-') << "\n";
205  }
206  if (ExceptionBacktraceTree::All.size() > 1)
207  {
208  out << "Exception Backtrace Tree " << std::setw(numW) << i << std::setw(0) << ":\n";
209  }
210  ExceptionBacktraceTree::All.at(i).print(out, pre);
211  Trace::PrintStackTrace(out, pre + "* ");
212  }
213  }
214 
215  void
216  Trace::PrintExceptionBacktrace(std::ostream& out, const std::string& pre)
217  {
219  }
220 
221  void
222  ExceptionBacktraceTree::print(std::ostream& out,
223  const std::string& prefix,
224  std::size_t levelOffset)
225  {
226  TerminateIf(entries.empty());
227  const auto numW = std::log10(entries.size()) + 1;
228 
229  std::size_t nextChildParentEntryOffset = std::numeric_limits<std::size_t>::max();
230 
231  std::size_t nextChildIndex = 0;
232  auto updateNextChildEntryOffset = [&]
233  {
234  nextChildParentEntryOffset = std::numeric_limits<std::size_t>::max();
235  if (nextChildIndex < children.size())
236  {
237  nextChildParentEntryOffset = children.at(nextChildIndex).parentEntryOffset;
238  }
239  };
240  updateNextChildEntryOffset();
241 
242  for (std::size_t entryIdx = 0; entryIdx < entries.size(); ++entryIdx)
243  {
244  const std::size_t level =
245  /*parentEntryOffset +*/ levelOffset + entries.size() - entryIdx;
246  while (entryIdx >= nextChildParentEntryOffset && nextChildIndex < children.size())
247  {
248  children.at(nextChildIndex).print(out, prefix + "| ", level);
249  out << prefix << "|/\n";
250  ++nextChildIndex;
251  updateNextChildEntryOffset();
252  }
253  out << prefix << "* -" << std::setw(numW) << level << std::setw(0) << ": "
254  << entries.at(entryIdx) << "\n";
255  }
256  //print children after this branch
257  for (; nextChildIndex < children.size(); ++nextChildIndex)
258  {
259  children.at(nextChildIndex).print(out, prefix + "| ");
260  out << prefix << "|/\n";
261  }
262  }
263 } // namespace armarx::detail
armarx::detail::Trace::~Trace
~Trace()
Definition: trace.cpp:105
armarx::detail::ExceptionBacktraceTree::parent
ExceptionBacktraceTree *const parent
Definition: trace.cpp:58
armarx::detail::LocationProvider::location
const FncLoc location
Definition: trace.h:23
armarx::detail::LocationProvider::Location::file
const std::string file
Definition: trace.h:17
TerminateIf
#define TerminateIf(...)
Definition: trace.cpp:14
armarx::detail::ExceptionBacktraceTree::currentStackSize
std::size_t currentStackSize
Definition: trace.cpp:61
armarx::detail::LocationProvider
Definition: trace.h:13
armarx::detail::Trace::PrintStackTrace
static void PrintStackTrace(std::ostream &out, const std::string &pre="")
Definition: trace.cpp:182
trace.h
armarx::detail::ExceptionBacktraceTree::children
std::deque< ExceptionBacktraceTree > children
Definition: trace.cpp:62
armarx::detail::Trace
Definition: trace.h:26
armarx::detail::Trace::exceptional
bool exceptional() const
Definition: trace.h:70
armarx::detail::ExceptionBacktraceTree::ExceptionBacktraceTree
ExceptionBacktraceTree(ExceptionBacktraceTree *parent)
Definition: trace.cpp:51
armarx::detail::ExceptionBacktraceTree::entries
std::deque< LocationProvider > entries
Definition: trace.cpp:63
armarx::detail::ExceptionBacktraceTree::ClearExceptionBacktrace
static void ClearExceptionBacktrace()
Definition: trace.cpp:93
armarx::detail::ExceptionBacktraceTree::Active
static thread_local ExceptionBacktraceTree * Active
Definition: trace.cpp:46
max
T max(T t1, T t2)
Definition: gdiam.h:51
armarx::detail
Definition: ApplicationNetworkStats.cpp:36
armarx::detail::ExceptionBacktraceTree::PrintExceptionBacktrace
static void PrintExceptionBacktrace(std::ostream &out, const std::string &pre)
Definition: trace.cpp:195
GfxTL::Trace
T Trace(const MatrixXX< N, N, T > &a)
Definition: MatrixXX.h:478
armarx::detail::LocationProvider::Location::line
const int line
Definition: trace.h:19
armarx::detail::Trace::GetStackTraceSize
static std::uintmax_t GetStackTraceSize()
Definition: trace.h:50
armarx::detail::ExceptionBacktraceTree
Definition: trace.cpp:41
armarx::detail::Trace::location
const LocationProvider location
Definition: trace.h:34
armarx::detail::Trace::parent
const Trace * parent
Definition: trace.h:32
armarx::detail::ExceptionBacktraceTree::parentEntryOffset
const std::size_t parentEntryOffset
Definition: trace.cpp:59
armarx::detail::LocationProvider::Location::func
const std::string func
Definition: trace.h:18
armarx::detail::Trace::ClearExceptionBacktrace
static void ClearExceptionBacktrace()
Definition: trace.cpp:100
armarx::detail::ExceptionBacktraceTree::All
static thread_local std::deque< ExceptionBacktraceTree > All
Definition: trace.cpp:47
armarx::detail::ExceptionBacktraceTree::print
void print(std::ostream &out, const std::string &prefix="", std::size_t levelOffset=0)
Definition: trace.cpp:222
armarx::detail::Trace::PrintExceptionBacktrace
static void PrintExceptionBacktrace(std::ostream &out, const std::string &pre="")
Definition: trace.cpp:216
IceInternal::trace
void trace(const char *, const ::Ice::OutputStream &, const ::Ice::LoggerPtr &, const TraceLevelsPtr &)
armarx::detail::ExceptionBacktraceTree::addEntry
void addEntry(const Trace *t) noexcept
Definition: trace.cpp:66
armarx::detail::operator<<
std::ostream & operator<<(std::ostream &out, const LocationProvider::Location &l)
Definition: trace.cpp:164
armarx::detail::LocationProvider::Location
Definition: trace.h:15