nss: upgrade to release 3.73
[LibreOffice.git] / include / sal / log.hxx
bloba0fa902dbce69dcce67a5d9bba02977bc659df2d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #ifndef INCLUDED_SAL_LOG_HXX
11 #define INCLUDED_SAL_LOG_HXX
13 #include "sal/config.h"
15 #include <cstdlib>
16 #include <sstream>
17 #include <string>
19 #include "sal/detail/log.h"
20 #include "sal/saldllapi.h"
21 #include "sal/types.h"
23 // Avoid the use of other sal code in this header as much as possible, so that
24 // this code can be called from other sal code without causing endless
25 // recursion.
27 /// @cond INTERNAL
29 enum sal_detail_LogAction
31 SAL_DETAIL_LOG_ACTION_IGNORE,
32 SAL_DETAIL_LOG_ACTION_LOG,
33 SAL_DETAIL_LOG_ACTION_FATAL
36 extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log(
37 sal_detail_LogLevel level, char const * area, char const * where,
38 char const * message, sal_uInt32 backtraceDepth);
40 // the return value is actually "enum sal_detail_LogAction", but due to ABI
41 // compatibility, it's left as the original "sal_Bool" / "unsigned char".
42 extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report(
43 sal_detail_LogLevel level, char const * area);
45 namespace sal { namespace detail {
47 inline void log(
48 sal_detail_LogLevel level, char const * area, char const * where,
49 std::ostringstream const & stream, sal_uInt32 backtraceDepth)
51 // An alternative would be to have sal_detail_log take a std::ostringstream
52 // pointer (via a C void pointer); the advantage would be smaller client
53 // code (the ".str().c_str()" part would move into the implementation of
54 // sal_detail_log) and potential for proper support of embedded null
55 // characters within the message, but the disadvantage would be dependence
56 // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
57 // to this inline function so that it is potentially only emitted once per
58 // dynamic library:
59 sal_detail_log(level, area, where, stream.str().c_str(), backtraceDepth);
62 // Special handling of the common case where the message consists of just a
63 // string literal, to produce smaller call-site code:
65 struct StreamStart {};
67 struct StreamString {
68 StreamString(char const * s): string(s) {}
70 char const * string;
72 typedef char Result;
75 struct StreamIgnore {
76 typedef struct { char a[2]; } Result;
79 inline StreamString operator <<(
80 SAL_UNUSED_PARAMETER StreamStart const &, char const * s)
82 return StreamString(s);
85 template< typename T > inline StreamIgnore operator <<(
86 SAL_UNUSED_PARAMETER StreamStart const &, SAL_UNUSED_PARAMETER T const &)
88 std::abort();
89 #if defined _MSC_VER && _MSC_VER < 1700
90 return StreamIgnore();
91 #endif
94 template< typename T > inline StreamIgnore operator <<(
95 SAL_UNUSED_PARAMETER StreamString const &, SAL_UNUSED_PARAMETER T const &)
97 std::abort();
98 #if defined _MSC_VER && _MSC_VER < 1700
99 return StreamIgnore();
100 #endif
103 template< typename T > inline StreamIgnore operator <<(
104 SAL_UNUSED_PARAMETER StreamIgnore const &, SAL_UNUSED_PARAMETER T const &)
106 std::abort();
107 #if defined _MSC_VER && _MSC_VER < 1700
108 return StreamIgnore();
109 #endif
112 template< typename T > typename T::Result getResult(T const &);
114 inline char const * unwrapStream(StreamString const & s) { return s.string; }
116 inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore const &) {
117 std::abort();
118 #if defined _MSC_VER && _MSC_VER < 1700
119 return 0;
120 #endif
125 // to prevent using a local variable, which can eventually shadow,
126 // resulting in compiler warnings (or even errors with -Werror)
127 #define SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream) \
128 if (sizeof ::sal::detail::getResult( \
129 ::sal::detail::StreamStart() << stream) == 1) \
131 ::sal_detail_log( \
132 (level), (area), (where), \
133 ::sal::detail::unwrapStream( \
134 ::sal::detail::StreamStart() << stream), \
135 0); \
136 } else { \
137 ::std::ostringstream sal_detail_stream; \
138 sal_detail_stream << stream; \
139 ::sal::detail::log( \
140 (level), (area), (where), sal_detail_stream, 0); \
143 #define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
144 do { \
145 if (condition) \
147 switch (sal_detail_log_report(level, area)) \
149 case SAL_DETAIL_LOG_ACTION_IGNORE: break; \
150 case SAL_DETAIL_LOG_ACTION_LOG: \
151 SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
152 break; \
153 case SAL_DETAIL_LOG_ACTION_FATAL: \
154 SAL_DETAIL_LOG_STREAM_PRIVATE_(level, area, where, stream); \
155 std::abort(); \
156 break; \
159 } while (false)
161 /// @endcond
163 /** A simple macro to create a "file and line number" string.
165 Potentially not only useful within the log framework (where it is used
166 automatically), but also when creating exception messages.
168 @attention For now, this functionality should only be used internally within
169 LibreOffice. It may change again in a future version.
171 @since LibreOffice 3.5
173 #define SAL_WHERE SAL_DETAIL_WHERE
175 /** A facility for generating temporary string messages by piping items into a
176 C++ std::ostringstream.
178 This can be useful for example in a call to SAL_INFO when depending on some
179 boolean condition data of incompatible types shall be streamed into the
180 message, as in:
182 SAL_INFO("foo", "object: " << (hasName ? obj->name : SAL_STREAM(obj)));
184 @attention For now, this functionality should only be used internally within
185 LibreOffice. It may change again in a future version.
187 @since LibreOffice 3.5
189 #if defined _LIBCPP_VERSION \
190 || (defined _GLIBCXX_RELEASE \
191 && (_GLIBCXX_RELEASE >= 12 || (_GLIBCXX_RELEASE == 11 && __GLIBCXX__ > 20210428))) \
192 || (defined _MSC_VER && _MSC_VER >= 1915)
193 #define SAL_STREAM(stream) \
194 (::std::ostringstream() << stream).str()
195 #else
196 #define SAL_STREAM(stream) \
197 (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream).str())
198 #endif
201 @page sal_log Basic logging functionality.
203 @short Macros for logging.
205 SAL_INFO(char const * area, expr),
206 SAL_INFO_IF(bool condition, char const * area, expr),
207 SAL_WARN(char const * area, expr),
208 SAL_WARN_IF(bool condition, char const * area, expr), and SAL_DEBUG(expr)
209 produce an info, warning, or debug log entry with a message produced by
210 piping items into a C++ std::ostringstream. The given expr must be so that
211 the full expression "stream << expr" is valid, where stream is a variable of
212 type std::ostringstream.
214 SAL_INFO("foo", "string " << s << " of length " << n)
216 would be an example of such a call.
218 The composed message should be in UTF-8 and it should contain no vertical
219 formatting characters and no null characters
221 For the _IF variants, log output is only generated if the given condition is
222 true (in addition to the other conditions that have to be met).
224 The SAL_DEBUG macro is for temporary debug statements that are used while
225 working on code. It is never meant to remain in the code. It will always
226 simply output the given expression in debug builds.
228 For all the other macros, the given area argument must be non-null and must
229 match the regular expression
231 @verbatim
232 <area> ::= <segment>("."<segment>)*
233 @endverbatim
235 with
237 @verbatim
238 <segment> ::= [0-9a-z]+
239 @endverbatim
241 For a list of areas used see @ref sal_log_areas "SAL debug areas". Whenever
242 you use a new log area, add it to the file include/sal/log-areas.dox .
244 Whether these macros generate any log output is controlled in a two-stage
245 process.
247 First, at compile time the macros SAL_LOG_INFO and SAL_LOG_WARN,
248 respectively, control whether the INFO and WARN macros, respectively,
249 expand to actual code (in case the macro is defined, to any value) or to
250 no-ops (in case the macro is not defined).
252 Second, at runtime the environment variable SAL_LOG further limits which
253 macro calls actually generate log output. The environment variable SAL_LOG
254 must either be unset or must match the regular expression
256 @verbatim
257 <env> ::= <switch>*
258 @endverbatim
260 with
262 @verbatim
263 <switch> ::= <sense><item>
264 <sense> ::= "+"|"-"
265 <item> ::= <flag>|<level>("."<area>)?
266 <flag> ::= "TIMESTAMP"|"RELATIVETIMER"|"FATAL"
267 <level> ::= "INFO"|"WARN"
268 @endverbatim
270 If the environment variable is unset, the setting "+WARN" is
271 assumed instead (which results in all warnings being output but no
272 infos). If the given value does not match the regular expression,
273 "+INFO+WARN" is used instead (which in turn results in everything
274 being output).
276 The "+TIMESTAMP" flag causes each output line (as selected by the level
277 switch(es)) to be prefixed by a timestamp like 2016-08-18:14:04:43.
279 The "+RELATIVETIMER" flag causes each output line (as selected by
280 the level switch(es)) to be prefixed by a relative timestamp in
281 seconds since the first output line like 1.312.
283 The "+FATAL" flag will cause later matching rules to log and call
284 std::abort. This can be disabled at some later point by using the
285 "-FATAL" flag before specifying additional rules. The flag will just
286 abort on positive rules, as it doesn't seem to make sense to abort
287 on ignored output.
289 If both +TIMESTAMP and +RELATIVETIMER are specified, they are
290 output in that order.
292 Specifying a flag with a negative sense has no effect. Specifying
293 the same flag multiple times has no extra effect.
295 A given macro call's level (INFO or WARN) and area is matched against the
296 given switches as follows: Only those switches for which the level matches
297 the given level and for which the area is a prefix (including both empty and
298 full prefixes) of the given area are considered. Log output is generated if
299 and only if among the longest such switches (if any), there is at least one
300 that has a sense of "+". (That is, if both +INFO.foo and -INFO.foo are
301 present, +INFO.foo wins.)
303 If no WARN selection is specified, but an INFO selection is, the
304 INFO selection is used for WARN messages, too.
306 For example, if SAL_LOG is "+INFO-INFO.foo+INFO.foo.bar", then calls like
307 SAL_INFO("foo.bar", ...), SAL_INFO("foo.bar.baz", ...), or
308 SAL_INFO("other", ...) generate output, while calls like
309 SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
311 The generated log output consists of the optional timestamp, the given level
312 ("info" or "warn"), the given area, the process ID, the thread ID, the
313 source file, and the source line number, each followed by a colon, followed
314 by a space, the given message, and a newline. The precise format of the log
315 output is subject to change. The log output is printed to stderr without
316 further text encoding conversion.
318 On some systems, log output can be redirected to other log sinks,
319 notably a file provided as a system path and filename via
320 environment variable SAL_LOG_FILE; or to a syslog facility if
321 LibreOffice is suitably built, by setting environment variable
322 SAL_LOG_SYSLOG.
324 @see @ref sal_log_areas
326 @attention For now, this functionality should only be used internally within
327 LibreOffice. It may change again in a future version.
329 @since LibreOffice 3.5
333 Produce log entry from stream in the given log area.
335 See @ref sal_log "basic logging functionality" for details.
337 #define SAL_INFO(area, stream) \
338 SAL_DETAIL_LOG_STREAM( \
339 SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
340 SAL_WHERE, stream)
343 Produce log entry from stream in the given log area if condition is true.
345 See @ref sal_log "basic logging functionality" for details.
347 #define SAL_INFO_IF(condition, area, stream) \
348 SAL_DETAIL_LOG_STREAM( \
349 SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
350 ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
353 Produce warning entry from stream in the given log area.
355 See @ref sal_log "basic logging functionality" for details.
357 #define SAL_WARN(area, stream) \
358 SAL_DETAIL_LOG_STREAM( \
359 SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
360 SAL_WHERE, stream)
363 Produce warning entry from stream in the given log area if condition is true.
365 See @ref sal_log "basic logging functionality" for details.
367 #define SAL_WARN_IF(condition, area, stream) \
368 SAL_DETAIL_LOG_STREAM( \
369 SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
370 ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
373 Produce temporary debugging output from stream. This macro is meant to be
374 used only while working on code and should never exist in production code.
376 See @ref sal_log "basic logging functionality" for details.
378 #define SAL_DEBUG(stream) \
379 SAL_DETAIL_LOG_STREAM( \
380 SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
383 Produce temporary debugging output from stream along with a backtrace of the
384 calling location.
386 This macro is meant to be used only while working on code and should never
387 exist in production code.
389 @param stream input stream
391 @param backtraceDepth a sal_uInt32 value indicating the maximum backtrace
392 depth; zero means no backtrace
394 See @ref sal_log "basic logging functionality" for details.
396 #define SAL_DEBUG_BACKTRACE(stream, backtraceDepth) \
397 do { \
398 if (sizeof ::sal::detail::getResult( \
399 ::sal::detail::StreamStart() << stream) == 1) \
401 ::sal_detail_log( \
402 ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, \
403 ::sal::detail::unwrapStream( \
404 ::sal::detail::StreamStart() << stream), \
405 backtraceDepth); \
406 } else { \
407 ::std::ostringstream sal_detail_stream; \
408 sal_detail_stream << stream; \
409 ::sal::detail::log( \
410 ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, sal_detail_stream, \
411 backtraceDepth); \
413 } while (false)
417 #endif
419 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */