Coverage Report

Created: 2025-08-11 06:28

/src/quantlib/ql/utilities/tracing.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2005 StatPro Italia srl
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <http://quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
/*! \file tracing.hpp
21
    \brief tracing facilities
22
*/
23
24
#ifndef quantlib_tracing_hpp
25
#define quantlib_tracing_hpp
26
27
#include <ql/types.hpp>
28
#include <ql/errors.hpp>
29
#include <ql/patterns/singleton.hpp>
30
#include <boost/current_function.hpp>
31
#include <iosfwd>
32
33
namespace QuantLib::detail {
34
35
        class Tracing : public Singleton<Tracing> {
36
            friend class QuantLib::Singleton<Tracing>;
37
          private:
38
            Tracing();  // NOLINT(modernize-use-equals-delete)
39
          public:
40
0
            void enable() {
41
0
                #if defined(QL_ENABLE_TRACING)
42
0
                enabled_ = true;
43
0
                #else
44
0
                QL_FAIL("tracing support not available");
45
0
                #endif
46
0
            }
47
0
            void disable() { enabled_ = false; }
48
0
            void setStream(std::ostream& stream) { out_ = &stream; }
49
0
            bool enabled() const { return enabled_; }
50
0
            std::ostream& stream() { return *out_; }
51
0
            Integer depth() const { return depth_; }
52
0
            void down() { depth_++; }
53
0
            void up() { depth_--; }
54
          private:
55
            std::ostream* out_;
56
            bool enabled_ = false;
57
            Integer depth_ = 0;
58
        };
59
60
    }
61
62
/*! \addtogroup macros
63
    @{
64
*/
65
66
/*! \defgroup debugMacros Debugging macros
67
68
    For debugging purposes, macros can be used to output information
69
    about the code being executed.  Instrumenting code as in:
70
    \code
71
    namespace Foo {
72
73
        int bar(int i) {
74
            QL_TRACE_ENTER_FUNCTION;
75
            QL_TRACE_VARIABLE(i);
76
77
            if (i == 42) {
78
                QL_TRACE_LOCATION;
79
                QL_TRACE("Right answer, but no question");
80
            } else {
81
                QL_TRACE_LOCATION;
82
                QL_TRACE("Wrong answer");
83
                i *= 2;
84
            }
85
86
            QL_TRACE_VARIABLE(i);
87
            QL_TRACE_EXIT_FUNCTION;
88
            return i;
89
        }
90
91
    }
92
    \endcode
93
    will output a trace like the following when the code is run:
94
    \code
95
    trace[3]: Entering int Foo::bar(int)
96
    trace[3]: i = 21
97
    trace[3]: At line 16 in tracing_example.cpp
98
    trace[3]: Wrong answer
99
    trace[3]: i = 42
100
    trace[3]: Exiting int Foo::bar(int)
101
    \endcode
102
    (the actual output will depend on the compiler and the file
103
    names).  A word of warning must be added: adding so much tracing
104
    to your code might degrade its readability.
105
106
    @{
107
*/
108
109
/*! \def QL_TRACE_ENABLE
110
    \brief enable tracing
111
112
    The statement
113
    \code
114
    QL_TRACE_ENABLE;
115
    \endcode
116
    can be used to enable tracing. Such statement might be
117
    ignored; refer to QL_TRACE for details.
118
*/
119
120
/*! \def QL_TRACE_DISABLE
121
    \brief disable tracing
122
123
    The statement
124
    \code
125
    QL_TRACE_DISABLE;
126
    \endcode
127
    can be used to disable tracing. Such statement might be
128
    ignored; refer to QL_TRACE for details.
129
*/
130
131
/*! \def QL_TRACE_ON
132
    \brief set tracing stream
133
134
    The statement
135
    \code
136
    QL_TRACE_ON(stream);
137
    \endcode
138
    can be used to set the stream where tracing messages are
139
    output. Such statement might be ignored; refer to QL_TRACE for
140
    details.
141
*/
142
143
/*! \def QL_TRACE
144
    \brief output tracing information
145
146
    The statement
147
    \code
148
    QL_TRACE(message);
149
    \endcode
150
    can be used to output a trace of the code being executed. If
151
    tracing was disabled during configuration, such statements are
152
    removed by the preprocessor for maximum performance; if it was
153
    enabled, whether and where the message is output depends on the
154
    current settings.
155
*/
156
157
/*! \def QL_TRACE_ENTER_FUNCTION
158
    \brief output tracing information
159
160
    The statement
161
    \code
162
    QL_TRACE_ENTER_FUNCTION;
163
    \endcode
164
    can be used at the beginning of a function to trace the fact that
165
    the program execution is entering such function. It should be
166
    paired with a corresponding QL_TRACE_EXIT_FUNCTION macro. Such
167
    statement might be ignored; refer to QL_TRACE for details. Also,
168
    function information might not be available depending on the
169
    compiler.
170
*/
171
172
/*! \def QL_TRACE_EXIT_FUNCTION
173
    \brief output tracing information
174
175
    The statement
176
    \code
177
    QL_TRACE_EXIT_FUNCTION;
178
    \endcode
179
    can be used before returning from a function to trace the fact
180
    that the program execution is exiting such function. It should be
181
    paired with a corresponding QL_TRACE_ENTER_FUNCTION macro. Such
182
    statement might be ignored; refer to QL_TRACE for details. Also,
183
    function information might not be available depending on the
184
    compiler.
185
*/
186
187
/*! \def QL_TRACE_LOCATION
188
    \brief output tracing information
189
190
    The statement
191
    \code
192
    QL_TRACE_LOCATION;
193
    \endcode
194
    can be used to trace the current file and line. Such statement
195
    might be ignored; refer to QL_TRACE for details.
196
*/
197
198
/*! \def QL_TRACE_VARIABLE
199
    \brief output tracing information
200
201
    The statement
202
    \code
203
    QL_TRACE_VARIABLE(variable);
204
    \endcode
205
    can be used to trace the current value of a variable. Such
206
    statement might be ignored; refer to QL_TRACE for details. Also,
207
    the variable type must allow sending it to an output stream.
208
*/
209
210
/*! @} */
211
212
/*! @} */
213
214
#if defined(QL_ENABLE_TRACING)
215
216
#define QL_DEFAULT_TRACER   QuantLib::detail::Tracing::instance()
217
218
#define QL_TRACE_ENABLE \
219
QL_DEFAULT_TRACER.enable()
220
221
#define QL_TRACE_DISABLE \
222
QL_DEFAULT_TRACER.disable()
223
224
#define QL_TRACE_ON(out) \
225
QL_DEFAULT_TRACER.setStream(out)
226
227
#define QL_TRACE(message) \
228
if (QL_DEFAULT_TRACER.enabled()) \
229
    try { \
230
        QL_DEFAULT_TRACER.stream() << "trace[" << QL_DEFAULT_TRACER.depth() \
231
                                   << "]: " << message << std::endl; \
232
    } catch (...) {} \
233
else
234
235
#define QL_TRACE_ENTER_FUNCTION \
236
if (QL_DEFAULT_TRACER.enabled()) \
237
    try { \
238
        QL_DEFAULT_TRACER.down(); \
239
        QL_DEFAULT_TRACER.stream() << "trace[" << QL_DEFAULT_TRACER.depth() \
240
                                   << "]: " \
241
                                   << "Entering " << BOOST_CURRENT_FUNCTION \
242
                                   << std::endl; \
243
    } catch (...) {} \
244
else
245
246
#define QL_TRACE_EXIT_FUNCTION \
247
if (QL_DEFAULT_TRACER.enabled()) \
248
    try { \
249
        QL_DEFAULT_TRACER.stream() << "trace[" << QL_DEFAULT_TRACER.depth() \
250
                                   << "]: " \
251
                                   << "Exiting " << BOOST_CURRENT_FUNCTION \
252
                                   << std::endl; \
253
        QL_DEFAULT_TRACER.up(); \
254
    } catch (...) { QL_DEFAULT_TRACER.up(); } \
255
else
256
257
#define QL_TRACE_LOCATION \
258
QL_TRACE("At line " << __LINE__ << " in " << __FILE__)
259
260
#define QL_TRACE_VARIABLE(variable) \
261
QL_TRACE(#variable << " = " << variable)
262
263
#else
264
265
#define QL_DEFAULT_TRACER
266
#define QL_TRACE_ENABLE
267
#define QL_TRACE_DISABLE
268
#define QL_TRACE_ON(out)
269
#define QL_TRACE(message)
270
#define QL_TRACE_ENTER_FUNCTION
271
#define QL_TRACE_EXIT_FUNCTION
272
#define QL_TRACE_LOCATION
273
#define QL_TRACE_VARIABLE(variable)
274
275
#endif
276
277
#endif