]> git.ipfire.org Git - thirdparty/squid.git/blame - src/Debug.h
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / Debug.h
CommitLineData
c772f001 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
c772f001 3 *
bbc27441
AJ
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.
c772f001 7 */
bbc27441
AJ
8
9/* DEBUG: section 00 Debug Routines */
10
e1f7507e
AJ
11#ifndef SQUID_DEBUG_H
12#define SQUID_DEBUG_H
c772f001 13
ebaabe74 14#include "base/Here.h"
ae72213d
FC
15// XXX should be mem/forward.h once it removes dependencies on typedefs.h
16#include "mem/AllocatorProxy.h"
17
f95fe6ed 18#include <iostream>
a8d99c60 19#undef assert
f95fe6ed 20#include <sstream>
bf8fe701 21#include <iomanip>
27e059d4 22#if defined(assert)
a8d99c60 23#undef assert
24#endif
27e059d4 25
a8d99c60 26#if PURIFY
27#define assert(EX) ((void)0)
28#elif defined(NODEBUG)
29#define assert(EX) ((void)0)
30#elif STDC_HEADERS
31#define assert(EX) ((EX)?((void)0):xassert( # EX , __FILE__, __LINE__))
32#else
33#define assert(EX) ((EX)?((void)0):xassert("EX", __FILE__, __LINE__))
34#endif
f95fe6ed 35
62493678
AJ
36/* context-based debugging, the actual type is subject to change */
37typedef int Ctx;
8a648e8d
FC
38Ctx ctx_enter(const char *descr);
39void ctx_exit(Ctx ctx);
62493678 40
e1f7507e
AJ
41/* defined debug section limits */
42#define MAX_DEBUG_SECTIONS 100
43
feefade1 44/* defined names for Debug Levels */
f53969cc
SM
45#define DBG_CRITICAL 0 /**< critical messages always shown when they occur */
46#define DBG_IMPORTANT 1 /**< important messages always shown when their section is being checked */
feefade1 47/* levels 2-8 are still being discussed amongst the developers */
f53969cc 48#define DBG_DATA 9 /**< output is a large data dump only necessary for advanced debugging */
feefade1 49
bbbea8ad
AJ
50#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. */
51
62e76326 52class Debug
c772f001 53{
62e76326 54
c772f001 55public:
014adac1
AR
56 /// meta-information for debugs() or a similar debugging call
57 class Context
58 {
59 public:
60 Context(const int aSectionLevel, const int aLevel);
61
62 int level; ///< minimum debugging level required by the debugs() call
63 int sectionLevel; ///< maximum debugging level allowed during the call
64
65 private:
66 friend class Debug;
67 void rewind(const int aSection, const int aLevel);
68 void formatStream();
69 Context *upper; ///< previous or parent record in nested debugging calls
70 std::ostringstream buf; ///< debugs() output sink
e863656d 71 bool forceAlert; ///< the current debugs() will be a syslog ALERT
014adac1
AR
72 };
73
74 /// whether debugging the given section and the given level produces output
75 static bool Enabled(const int section, const int level)
76 {
77 return level <= Debug::Levels[section];
78 }
79
62493678
AJ
80 static char *debugOptions;
81 static char *cache_log;
82 static int rotateNumber;
62e76326 83 static int Levels[MAX_DEBUG_SECTIONS];
62493678
AJ
84 static int override_X;
85 static int log_stderr;
86 static bool log_syslog;
87
d9e04dc7 88 static void parseOptions(char const *);
f95fe6ed 89
014adac1
AR
90 /// minimum level required by the current debugs() call
91 static int Level() { return Current ? Current->level : 1; }
92 /// maximum level currently allowed
93 static int SectionLevel() { return Current ? Current->sectionLevel : 1; }
26ac0430 94
014adac1
AR
95 /// opens debugging context and returns output buffer
96 static std::ostringstream &Start(const int section, const int level);
97 /// logs output buffer created in Start() and closes debugging context
98 static void Finish();
bfa09779 99
e863656d
CT
100 /// configures the active debugging context to write syslog ALERT
101 static void ForceAlert();
ccfbe8f4
AR
102
103 /// prefixes each grouped debugs() line after the first one in the group
104 static std::ostream& Extra(std::ostream &os) { return os << "\n "; }
105
014adac1
AR
106private:
107 static Context *Current; ///< deepest active context; nil outside debugs()
c772f001 108};
109
0c7e529e
AR
110/// cache.log FILE or, as the last resort, stderr stream;
111/// may be nil during static initialization and destruction!
112FILE *DebugStream();
113/// change-avoidance macro; new code should call DebugStream() instead
114#define debug_log DebugStream()
115
116/// start logging to stderr (instead of cache.log, if any)
117void StopUsingDebugLog();
118
119/// a hack for low-level file descriptor manipulations in ipcCreate()
120void ResyncDebugLog(FILE *newDestination);
f76d2f97 121
03714d23
FC
122/* Debug stream
123 *
124 * Unit tests can enable full debugging to stderr for one
125 * debug section; to enable this, #define ENABLE_DEBUG_SECTION to the
126 * section number before any header
127 */
f95fe6ed 128#define debugs(SECTION, LEVEL, CONTENT) \
129 do { \
014adac1
AR
130 const int _dbg_level = (LEVEL); \
131 if (Debug::Enabled((SECTION), _dbg_level)) { \
132 std::ostream &_dbo = Debug::Start((SECTION), _dbg_level); \
133 if (_dbg_level > DBG_IMPORTANT) { \
134 _dbo << (SECTION) << ',' << _dbg_level << "| " \
ebaabe74 135 << Here() << ": "; \
3304cfef 136 } \
bfd38d03 137 _dbo << CONTENT; \
014adac1 138 Debug::Finish(); \
f95fe6ed 139 } \
140 } while (/*CONSTCOND*/ 0)
141
e863656d
CT
142/// Does not change the stream being manipulated. Exists for its side effect:
143/// In a debugs() context, forces the message to become a syslog ALERT.
144/// Outside of debugs() context, has no effect and should not be used.
145std::ostream& ForceAlert(std::ostream& s);
146
fc9d2eb0
FC
147/** stream manipulator which does nothing.
148 * \deprecated Do not add to new code, and remove when editing old code
def17b6a 149 *
fc9d2eb0
FC
150 * Its purpose is to inactivate calls made following previous debugs()
151 * guidelines such as
23d6095a 152 * debugs(1,2, HERE << "some message");
fc9d2eb0
FC
153 *
154 * His former objective is now absorbed in the debugs call itself
def17b6a 155 */
fc9d2eb0
FC
156inline std::ostream&
157HERE(std::ostream& s)
158{
159 return s;
160}
def17b6a 161
23d6095a
AJ
162/*
163 * MYNAME is for use at debug levels 0 and 1 where HERE is too messy.
164 *
165 * debugs(1,1, MYNAME << "WARNING: some message");
166 */
167#ifdef __PRETTY_FUNCTION__
168#define MYNAME __PRETTY_FUNCTION__ << " "
169#else
170#define MYNAME __FUNCTION__ << " "
171#endif
172
cc192b50 173/* some uint8_t do not like streaming control-chars (values 0-31, 127+) */
26ac0430
AJ
174inline std::ostream& operator <<(std::ostream &os, const uint8_t d)
175{
066c9540 176 return (os << (int)d);
177}
178
ec85ebda 179/* Legacy debug function definitions */
8a648e8d 180void _db_init(const char *logfile, const char *options);
8a648e8d
FC
181void _db_set_syslog(const char *facility);
182void _db_rotate_log(void);
96e03dd8 183
be039a68
AR
184/// Prints raw and/or non-terminated data safely, efficiently, and beautifully.
185/// Allows raw data debugging in debugs() statements with low debugging levels
186/// by printing only if higher section debugging levels are configured:
187/// debugs(11, DBG_IMPORTANT, "always printed" << Raw(may be printed...));
2113e038
A
188class Raw
189{
be039a68
AR
190public:
191 Raw(const char *label, const char *data, const size_t size):
f5e17947 192 level(-1), label_(label), data_(data), size_(size), useHex_(false), useGap_(true) {}
be039a68
AR
193
194 /// limit data printing to at least the given debugging level
195 Raw &minLevel(const int aLevel) { level = aLevel; return *this; }
196
6821c276
CT
197 /// print data using two hex digits per byte (decoder: xxd -r -p)
198 Raw &hex() { useHex_ = true; return *this; }
199
f5e17947
CT
200 Raw &gap(bool useGap = true) { useGap_ = useGap; return *this; }
201
be039a68
AR
202 /// If debugging is prohibited by the current debugs() or section level,
203 /// prints nothing. Otherwise, dumps data using one of these formats:
204 /// " label[size]=data" if label was set and data size is positive
205 /// " label[0]" if label was set and data size is zero
206 /// " data" if label was not set and data size is positive
207 /// "" (i.e., prints nothing) if label was not set and data size is zero
208 std::ostream &print(std::ostream &os) const;
209
210 /// Minimum section debugging level necessary for printing. By default,
211 /// small strings are always printed while large strings are only printed
212 /// if DBG_DATA debugging level is enabled.
213 int level;
214
215private:
6821c276
CT
216 void printHex(std::ostream &os) const;
217
be039a68
AR
218 const char *label_; ///< optional data name or ID; triggers size printing
219 const char *data_; ///< raw data to be printed
220 size_t size_; ///< data length
6821c276 221 bool useHex_; ///< whether hex() has been called
f5e17947 222 bool useGap_; ///< whether to print leading space if label is missing
be039a68
AR
223};
224
225inline
226std::ostream &operator <<(std::ostream &os, const Raw &raw)
227{
228 return raw.print(os);
229}
230
cb171ead
CT
231/// debugs objects pointed by possibly nil pointers: label=object
232template <class Pointer>
233class RawPointerT {
234public:
235 RawPointerT(const char *aLabel, const Pointer &aPtr):
236 label(aLabel), ptr(aPtr) {}
237 const char *label; /// the name or description of the being-debugged object
238 const Pointer &ptr; /// a possibly nil pointer to the being-debugged object
239};
240
241/// convenience wrapper for creating RawPointerT<> objects
242template <class Pointer>
243inline RawPointerT<Pointer>
244RawPointer(const char *label, const Pointer &ptr)
245{
246 return RawPointerT<Pointer>(label, ptr);
247}
248
249/// prints RawPointerT<>, dereferencing the raw pointer if possible
250template <class Pointer>
251inline std::ostream &
252operator <<(std::ostream &os, const RawPointerT<Pointer> &pd)
253{
254 os << pd.label << '=';
255 if (pd.ptr)
256 return os << *pd.ptr;
257 else
258 return os << "[nil]";
259}
260
653d9927
A
261/// std::ostream manipulator to print integers as hex numbers prefixed by 0x
262template <class Integer>
263class AsHex
264{
265public:
266 explicit AsHex(const Integer n): raw(n) {}
267 Integer raw; ///< the integer to print
268};
269
270template <class Integer>
271inline std::ostream &
272operator <<(std::ostream &os, const AsHex<Integer> number)
273{
274 const auto oldFlags = os.flags();
275 os << std::hex << std::showbase << number.raw;
276 os.setf(oldFlags);
277 return os;
278}
279
280/// a helper to ease AsHex object creation
281template <class Integer>
282inline AsHex<Integer> asHex(const Integer n) { return AsHex<Integer>(n); }
283
e1f7507e 284#endif /* SQUID_DEBUG_H */
f53969cc 285