libi2ncommon: (reinhard) integrated "logfunc" and "tracing" from connd.
[libi2ncommon] / src / tracefunc.cpp
CommitLineData
b6fb82a2
RP
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
20namespace I2n
21{
22namespace Tracer
23{
24
25using Logger::GlobalLogger;
26
27
28namespace
29{
30
31typedef std::list< ScopeTracker* > ScopeTrackerList;
32
33ScopeTrackerList scope_tracker_list;
34
35
36std::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 */
43void 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 */
55class __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 */
85ScopeTracker::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 */
136ScopeTracker::~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