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