c356030e6ac87884d2ed77eb237172e7b71dfb0c
[libi2ncommon] / src / tracefunc.cpp
1 /** @file
2  * @brief implementation of tracing functionality.
3  *
4  * @copyright © Copyright 2008 by Intra2net AG
5  * @license commercial
6  *
7  * info@intra2net.com
8  *
9  * @note This module is not thread safe!
10  * @todo make this module thread safe (only useful when we can use threads...)
11  */
12
13 #include "tracefunc.hpp"
14
15 #include <list>
16 #include <vector>
17 #include <sstream>
18
19
20 namespace I2n
21 {
22 namespace Tracer
23 {
24
25 using Logger::GlobalLogger;
26
27
28 namespace
29 {
30
31 typedef std::list< ScopeTracker* > ScopeTrackerList;
32
33 ScopeTrackerList scope_tracker_list;
34
35
36 std::vector< std::string > indents;
37
38
39 /**
40  * @brief ensures indent level string to exist up to the desired level.
41  * @param level the desired indent level.
42  */
43 void ensure_indent_level(int level)
44 {
45    while (indents.size() <= level)
46    {
47       indents.push_back( indents.back() + "  " );
48    }
49 } // eo ensure_indent_level(int)
50
51
52 /**
53  * @brief module initializer.
54  */
55 class __Initializer
56 {
57    public:
58       __Initializer()
59       {
60          // pre initialize indent strings:
61          indents.clear();
62          indents.reserve(10);
63          indents.push_back("");
64          for(int i=10; i-->0;)
65          {
66             indents.push_back( indents.back() + "  " );
67          }
68       }
69 } __initializer;
70
71
72 } // eo namespace <anonymous>
73
74
75 /*
76 ** implementation of ScopeTracker
77 */
78
79 /**
80  * @brief constructor. initializes object with a source location and emits a ENTER message.
81  * @param loc the source location.
82  *
83  * the message is indented according to the current depth of nested ScopeTracker instances.
84  */
85 ScopeTracker::ScopeTracker(
86     const SourceLocation& loc)
87 : Location(loc)
88 , Depth(0)
89 , FuncDepth(0)
90 {
91    if (!scope_tracker_list.empty())
92    {
93       ScopeTracker* last_tracker= scope_tracker_list.back();
94       if (Location)
95       {
96          if (last_tracker->Location
97              && last_tracker->Location.File == Location.File
98              && last_tracker->Location.FunctionName == Location.FunctionName)
99          {
100             FuncDepth= last_tracker->FuncDepth+1;
101          }
102       }
103       Depth= last_tracker->Depth + 1;
104    }
105    ensure_indent_level(Depth);
106    scope_tracker_list.push_back(this);
107    {
108       std::ostringstream ostr;
109       if (Location.FunctionName.empty())
110       {
111          ostr << "<unknown> (global scope?)";
112       }
113       else
114       {
115          ostr << Location.FunctionName;
116          if (FuncDepth>0)
117          {
118             ostr << "#" << FuncDepth+1;
119          }
120       }
121       Tag= ostr.str();
122    }
123    // spit a message
124    if (Logger::has_log_level(Logger::LogLevel::Debug))
125    {
126       GlobalLogger.debug() << indents[Depth] << "ENTER " << Tag;
127    }
128 } // eo ScopeTrcaker::ScopeTracker(const SourceLocation&)
129
130
131 /**
132  * @brief destructor. emits a LEAVE message.
133  *
134  *
135  */
136 ScopeTracker::~ScopeTracker()
137 {
138    // spit a message
139    if (Logger::has_log_level(Logger::LogLevel::Debug))
140    {
141       GlobalLogger.debug() << indents[Depth] << "LEAVE " << Tag;
142    }
143    if (scope_tracker_list.empty())
144    {
145       return;
146    }
147    if (scope_tracker_list.back() == this)
148    {
149       scope_tracker_list.pop_back();
150    }
151    else
152    {
153       // oh hell, this should never be the case!
154       //TODO
155       GlobalLogger.error() << "inconsistency detected in scope tracker";
156    }
157 } // eo ScopeTracker::~ScopeTracker()
158
159
160
161
162 } // eo namespace Tracer
163 } // eo namespace I2n