]> git.ipfire.org Git - thirdparty/squid.git/blob - src/Debug.h
SourceFormat Enforcement
[thirdparty/squid.git] / src / Debug.h
1 /*
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 /* DEBUG: section 00 Debug Routines */
10
11 #ifndef SQUID_DEBUG_H
12 #define SQUID_DEBUG_H
13
14 // XXX should be mem/forward.h once it removes dependencies on typedefs.h
15 #include "mem/AllocatorProxy.h"
16
17 #include <iostream>
18 #undef assert
19 #include <sstream>
20 #include <iomanip>
21 #if defined(assert)
22 #undef assert
23 #endif
24
25 #if PURIFY
26 #define assert(EX) ((void)0)
27 #elif defined(NODEBUG)
28 #define assert(EX) ((void)0)
29 #elif STDC_HEADERS
30 #define assert(EX) ((EX)?((void)0):xassert( # EX , __FILE__, __LINE__))
31 #else
32 #define assert(EX) ((EX)?((void)0):xassert("EX", __FILE__, __LINE__))
33 #endif
34
35 /* context-based debugging, the actual type is subject to change */
36 typedef int Ctx;
37 Ctx ctx_enter(const char *descr);
38 void ctx_exit(Ctx ctx);
39
40 /* defined debug section limits */
41 #define MAX_DEBUG_SECTIONS 100
42
43 /* defined names for Debug Levels */
44 #define DBG_CRITICAL 0 /**< critical messages always shown when they occur */
45 #define DBG_IMPORTANT 1 /**< important messages always shown when their section is being checked */
46 /* levels 2-8 are still being discussed amongst the developers */
47 #define DBG_DATA 9 /**< output is a large data dump only necessary for advanced debugging */
48
49 #define DBG_PARSE_NOTE(x) (opt_parse_cfg_only?0:(x)) /**< output is always to be displayed on '-k parse' but at level-x normally. */
50
51 class Debug
52 {
53
54 public:
55 /// meta-information for debugs() or a similar debugging call
56 class Context
57 {
58 public:
59 Context(const int aSectionLevel, const int aLevel);
60
61 int level; ///< minimum debugging level required by the debugs() call
62 int sectionLevel; ///< maximum debugging level allowed during the call
63
64 private:
65 friend class Debug;
66 void rewind(const int aSection, const int aLevel);
67 void formatStream();
68 Context *upper; ///< previous or parent record in nested debugging calls
69 std::ostringstream buf; ///< debugs() output sink
70 };
71
72 /// whether debugging the given section and the given level produces output
73 static bool Enabled(const int section, const int level)
74 {
75 return level <= Debug::Levels[section];
76 }
77
78 static char *debugOptions;
79 static char *cache_log;
80 static int rotateNumber;
81 static int Levels[MAX_DEBUG_SECTIONS];
82 static int override_X;
83 static int log_stderr;
84 static bool log_syslog;
85
86 static void parseOptions(char const *);
87
88 /// minimum level required by the current debugs() call
89 static int Level() { return Current ? Current->level : 1; }
90 /// maximum level currently allowed
91 static int SectionLevel() { return Current ? Current->sectionLevel : 1; }
92
93 /// opens debugging context and returns output buffer
94 static std::ostringstream &Start(const int section, const int level);
95 /// logs output buffer created in Start() and closes debugging context
96 static void Finish();
97
98 private:
99 static Context *Current; ///< deepest active context; nil outside debugs()
100 };
101
102 extern FILE *debug_log;
103
104 size_t BuildPrefixInit();
105 const char * SkipBuildPrefix(const char* path);
106
107 /* Debug stream
108 *
109 * Unit tests can enable full debugging to stderr for one
110 * debug section; to enable this, #define ENABLE_DEBUG_SECTION to the
111 * section number before any header
112 */
113 #define debugs(SECTION, LEVEL, CONTENT) \
114 do { \
115 const int _dbg_level = (LEVEL); \
116 if (Debug::Enabled((SECTION), _dbg_level)) { \
117 std::ostream &_dbo = Debug::Start((SECTION), _dbg_level); \
118 if (_dbg_level > DBG_IMPORTANT) { \
119 _dbo << (SECTION) << ',' << _dbg_level << "| " \
120 << SkipBuildPrefix(__FILE__)<<"("<<__LINE__<<") "<<__FUNCTION__<<": "; \
121 } \
122 _dbo << CONTENT; \
123 Debug::Finish(); \
124 } \
125 } while (/*CONSTCOND*/ 0)
126
127 /** stream manipulator which does nothing.
128 * \deprecated Do not add to new code, and remove when editing old code
129 *
130 * Its purpose is to inactivate calls made following previous debugs()
131 * guidelines such as
132 * debugs(1,2, HERE << "some message");
133 *
134 * His former objective is now absorbed in the debugs call itself
135 */
136 inline std::ostream&
137 HERE(std::ostream& s)
138 {
139 return s;
140 }
141
142 /*
143 * MYNAME is for use at debug levels 0 and 1 where HERE is too messy.
144 *
145 * debugs(1,1, MYNAME << "WARNING: some message");
146 */
147 #ifdef __PRETTY_FUNCTION__
148 #define MYNAME __PRETTY_FUNCTION__ << " "
149 #else
150 #define MYNAME __FUNCTION__ << " "
151 #endif
152
153 /* some uint8_t do not like streaming control-chars (values 0-31, 127+) */
154 inline std::ostream& operator <<(std::ostream &os, const uint8_t d)
155 {
156 return (os << (int)d);
157 }
158
159 /* Legacy debug function definitions */
160 void _db_init(const char *logfile, const char *options);
161 void _db_print(const char *,...) PRINTF_FORMAT_ARG1;
162 void _db_set_syslog(const char *facility);
163 void _db_rotate_log(void);
164
165 /// Prints raw and/or non-terminated data safely, efficiently, and beautifully.
166 /// Allows raw data debugging in debugs() statements with low debugging levels
167 /// by printing only if higher section debugging levels are configured:
168 /// debugs(11, DBG_IMPORTANT, "always printed" << Raw(may be printed...));
169 class Raw
170 {
171 public:
172 Raw(const char *label, const char *data, const size_t size):
173 level(-1), label_(label), data_(data), size_(size), useHex_(false) {}
174
175 /// limit data printing to at least the given debugging level
176 Raw &minLevel(const int aLevel) { level = aLevel; return *this; }
177
178 /// print data using two hex digits per byte (decoder: xxd -r -p)
179 Raw &hex() { useHex_ = true; return *this; }
180
181 /// If debugging is prohibited by the current debugs() or section level,
182 /// prints nothing. Otherwise, dumps data using one of these formats:
183 /// " label[size]=data" if label was set and data size is positive
184 /// " label[0]" if label was set and data size is zero
185 /// " data" if label was not set and data size is positive
186 /// "" (i.e., prints nothing) if label was not set and data size is zero
187 std::ostream &print(std::ostream &os) const;
188
189 /// Minimum section debugging level necessary for printing. By default,
190 /// small strings are always printed while large strings are only printed
191 /// if DBG_DATA debugging level is enabled.
192 int level;
193
194 private:
195 void printHex(std::ostream &os) const;
196
197 const char *label_; ///< optional data name or ID; triggers size printing
198 const char *data_; ///< raw data to be printed
199 size_t size_; ///< data length
200 bool useHex_; ///< whether hex() has been called
201 };
202
203 inline
204 std::ostream &operator <<(std::ostream &os, const Raw &raw)
205 {
206 return raw.print(os);
207 }
208
209 /// debugs objects pointed by possibly nil pointers: label=object
210 template <class Pointer>
211 class RawPointerT {
212 public:
213 RawPointerT(const char *aLabel, const Pointer &aPtr):
214 label(aLabel), ptr(aPtr) {}
215 const char *label; /// the name or description of the being-debugged object
216 const Pointer &ptr; /// a possibly nil pointer to the being-debugged object
217 };
218
219 /// convenience wrapper for creating RawPointerT<> objects
220 template <class Pointer>
221 inline RawPointerT<Pointer>
222 RawPointer(const char *label, const Pointer &ptr)
223 {
224 return RawPointerT<Pointer>(label, ptr);
225 }
226
227 /// prints RawPointerT<>, dereferencing the raw pointer if possible
228 template <class Pointer>
229 inline std::ostream &
230 operator <<(std::ostream &os, const RawPointerT<Pointer> &pd)
231 {
232 os << pd.label << '=';
233 if (pd.ptr)
234 return os << *pd.ptr;
235 else
236 return os << "[nil]";
237 }
238
239 #endif /* SQUID_DEBUG_H */
240