/src/trafficserver/include/tscore/Diags.h
Line | Count | Source |
1 | | /** @file |
2 | | |
3 | | A brief file description |
4 | | |
5 | | @section license License |
6 | | |
7 | | Licensed to the Apache Software Foundation (ASF) under one |
8 | | or more contributor license agreements. See the NOTICE file |
9 | | distributed with this work for additional information |
10 | | regarding copyright ownership. The ASF licenses this file |
11 | | to you under the Apache License, Version 2.0 (the |
12 | | "License"); you may not use this file except in compliance |
13 | | with the License. You may obtain a copy of the License at |
14 | | |
15 | | http://www.apache.org/licenses/LICENSE-2.0 |
16 | | |
17 | | Unless required by applicable law or agreed to in writing, software |
18 | | distributed under the License is distributed on an "AS IS" BASIS, |
19 | | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
20 | | See the License for the specific language governing permissions and |
21 | | limitations under the License. |
22 | | */ |
23 | | |
24 | | /**************************************************************************** |
25 | | |
26 | | Diags.h |
27 | | |
28 | | This file contains code to manipulate run-time diagnostics, and print |
29 | | warnings and errors at runtime. Action tags and debugging tags are |
30 | | supported, allowing run-time conditionals affecting diagnostics. |
31 | | |
32 | | ****************************************************************************/ |
33 | | |
34 | | #pragma once |
35 | | |
36 | | #include "tsutil/DbgCtl.h" |
37 | | #include "tsutil/SourceLocation.h" |
38 | | #include "tscore/DiagsTypes.h" |
39 | | #include "tscore/LogMessage.h" |
40 | | |
41 | | ////////////////////////////////////////////////////////////////////////// |
42 | | // // |
43 | | // Macros // |
44 | | // // |
45 | | // The following are diagnostic macros that wrap up the compiler // |
46 | | // __FILE__, __FUNCTION__, and __LINE__ macros into closures // |
47 | | // and then invoke the closure on the remaining arguments. // |
48 | | // // |
49 | | // This closure hack is done, because the cpp preprocessor doesn't // |
50 | | // support manipulation and union of varargs parameters. // |
51 | | // // |
52 | | ////////////////////////////////////////////////////////////////////////// |
53 | | |
54 | | #if !defined(__GNUC__) |
55 | | #ifndef __FUNCTION__ |
56 | | #define __FUNCTION__ nullptr |
57 | | #endif |
58 | | #endif |
59 | | |
60 | | class DiagsPtr |
61 | | { |
62 | | public: |
63 | | friend Diags *diags(); |
64 | | static void set(Diags *new_ptr); |
65 | | |
66 | | private: |
67 | | static Diags *_diags_ptr; |
68 | | }; |
69 | | |
70 | | inline Diags * |
71 | | diags() |
72 | 17.9k | { |
73 | 17.9k | return DiagsPtr::_diags_ptr; |
74 | 17.9k | } |
75 | | |
76 | | // Note that the log functions being implemented as a macro has the advantage |
77 | | // that the pre-compiler expands this in place such that the call to |
78 | | // MakeSourceLocation happens at the call site for the function. |
79 | | #define DiagsError(LEVEL, ...) \ |
80 | 209 | do { \ |
81 | 209 | static const SourceLocation DiagsError_loc = MakeSourceLocation(); \ |
82 | 209 | static LogMessage DiagsError_log_message; \ |
83 | 209 | DiagsError_log_message.message(LEVEL, DiagsError_loc, __VA_ARGS__); \ |
84 | 209 | } while (false) |
85 | | |
86 | | #define Status(...) DiagsError(DL_Status, __VA_ARGS__) // Log information |
87 | 0 | #define Note(...) DiagsError(DL_Note, __VA_ARGS__) // Log significant information |
88 | 0 | #define Warning(...) DiagsError(DL_Warning, __VA_ARGS__) // Log concerning information |
89 | 209 | #define Error(...) DiagsError(DL_Error, __VA_ARGS__) // Log operational failure, fail CI |
90 | 0 | #define Fatal(...) DiagsError(DL_Fatal, __VA_ARGS__) // Log recoverable crash, fail CI, exit & allow restart |
91 | | #define Alert(...) DiagsError(DL_Alert, __VA_ARGS__) // Log recoverable crash, fail CI, exit & restart, Ops attention |
92 | | #define Emergency(...) DiagsError(DL_Emergency, __VA_ARGS__) // Log unrecoverable crash, fail CI, exit, Ops attention |
93 | | |
94 | | /** Apply throttling to a log site. |
95 | | * |
96 | | * Logs using SiteThrottled* version will be throttled at a certain interval |
97 | | * that applies to the call site, regardless of whether the messages within |
98 | | * that interval are unique or not. This is helpful for logs which can be noisy |
99 | | * and frequently have differing content, such as the length of a buffer or a |
100 | | * counter. Rather than changing the log to contain less information, this can |
101 | | * be applied to the site so that when it is emitted, the information is |
102 | | * present, but the set of possibly slightly different logs will still be |
103 | | * suppressed against a configurable interval as a whole. |
104 | | */ |
105 | | #define SiteThrottledDiagsError(LEVEL, ...) \ |
106 | | do { \ |
107 | | static const SourceLocation STDE_loc = MakeSourceLocation(); \ |
108 | | static LogMessage STDE_log_message{IS_THROTTLED}; \ |
109 | | STDE_log_message.message(LEVEL, STDE_loc, __VA_ARGS__); \ |
110 | | } while (false) |
111 | | |
112 | | #define SiteThrottledStatus(...) SiteThrottledDiagsError(DL_Status, __VA_ARGS__) // Log information |
113 | | #define SiteThrottledNote(...) SiteThrottledDiagsError(DL_Note, __VA_ARGS__) // Log significant information |
114 | | #define SiteThrottledWarning(...) SiteThrottledDiagsError(DL_Warning, __VA_ARGS__) // Log concerning information |
115 | | #define SiteThrottledError(...) SiteThrottledDiagsError(DL_Error, __VA_ARGS__) // Log operational failure, fail CI |
116 | | #define SiteThrottledFatal(...) \ |
117 | | SiteThrottledDiagsError(DL_Fatal, __VA_ARGS__) // Log recoverable crash, fail CI, exit & allow restart |
118 | | #define SiteThrottledAlert(...) \ |
119 | | SiteThrottledDiagsError(DL_Alert, __VA_ARGS__) // Log recoverable crash, fail CI, exit & restart, Ops attention |
120 | | #define SiteThrottledEmergency(...) \ |
121 | | SiteThrottledDiagsError(DL_Emergency, __VA_ARGS__) // Log unrecoverable crash, fail CI, exit, Ops attention |
122 | | |
123 | | #define DiagsErrorV(LEVEL, FMT, AP) \ |
124 | | do { \ |
125 | | static const SourceLocation DiagsErrorV_loc = MakeSourceLocation(); \ |
126 | | static LogMessage DiagsErrorV_log_message; \ |
127 | | DiagsErrorV_log_message.message_va(LEVEL, DiagsErrorV_loc, FMT, AP); \ |
128 | | } while (false) |
129 | | |
130 | | #define StatusV(fmt, ap) DiagsErrorV(DL_Status, fmt, ap) |
131 | | #define NoteV(fmt, ap) DiagsErrorV(DL_Note, fmt, ap) |
132 | | #define WarningV(fmt, ap) DiagsErrorV(DL_Warning, fmt, ap) |
133 | | #define ErrorV(fmt, ap) DiagsErrorV(DL_Error, fmt, ap) |
134 | | #define FatalV(fmt, ap) DiagsErrorV(DL_Fatal, fmt, ap) |
135 | | #define AlertV(fmt, ap) DiagsErrorV(DL_Alert, fmt, ap) |
136 | | #define EmergencyV(fmt, ap) DiagsErrorV(DL_Emergency, fmt, ap) |
137 | | |
138 | | /** See the comment above SiteThrottledDiagsError for an explanation of how the |
139 | | * SiteThrottled functions behave. */ |
140 | | #define SiteThrottledDiagsErrorV(LEVEL, FMT, AP) \ |
141 | | do { \ |
142 | | static const SourceLocation STDEV_loc = MakeSourceLocation(); \ |
143 | | static LogMessage STDEV_log_message{IS_THROTTLED}; \ |
144 | | STDEV_log_message.message_va(LEVEL, STDEV_loc, FMT, AP); \ |
145 | | } while (false) |
146 | | |
147 | | #define SiteThrottledStatusV(fmt, ap) SiteThrottledDiagsErrorV(DL_Status, fmt, ap) |
148 | | #define SiteThrottledNoteV(fmt, ap) SiteThrottledDiagsErrorV(DL_Note, fmt, ap) |
149 | | #define SiteThrottledWarningV(fmt, ap) SiteThrottledDiagsErrorV(DL_Warning, fmt, ap) |
150 | | #define SiteThrottledErrorV(fmt, ap) SiteThrottledDiagsErrorV(DL_Error, fmt, ap) |
151 | | #define SiteThrottledFatalV(fmt, ap) SiteThrottledDiagsErrorV(DL_Fatal, fmt, ap) |
152 | | #define SiteThrottledAlertV(fmt, ap) SiteThrottledDiagsErrorV(DL_Alert, fmt, ap) |
153 | | #define SiteThrottledEmergencyV(fmt, ap) SiteThrottledDiagsErrorV(DL_Emergency, fmt, ap) |
154 | | |
155 | | #if TS_USE_DIAGS |
156 | | |
157 | | /// A Diag version of the above. |
158 | | #define Diag(TAG, ...) \ |
159 | | do { \ |
160 | | if (unlikely(diags()->on())) { \ |
161 | | static const SourceLocation Diag_loc = MakeSourceLocation(); \ |
162 | | static LogMessage Diag_log_message; \ |
163 | | Diag_log_message.diag(TAG, Diag_loc, __VA_ARGS__); \ |
164 | | } \ |
165 | | } while (false) |
166 | | |
167 | | // A BufferWriter version of Dbg(). |
168 | | #define Dbg_bw(ctl__, fmt, ...) \ |
169 | | do { \ |
170 | | if (ctl__.on()) { \ |
171 | | DbgPrint(ctl__, "%s", swoc::bwprint(ts::bw_dbg, fmt, __VA_ARGS__).c_str()); \ |
172 | | } \ |
173 | | } while (false) |
174 | | |
175 | | #define is_action_tag_set(_t) unlikely(diags()->on(_t, DiagsTagType_Action)) |
176 | | |
177 | | #else // TS_USE_DIAGS |
178 | | |
179 | | #define Diag(...) |
180 | | |
181 | | #define Dbg_bw(ctl__, fmt, ...) |
182 | | |
183 | | #define is_action_tag_set(_t) 0 |
184 | | |
185 | | #endif // TS_USE_DIAGS |