1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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/.
10 #ifndef INCLUDED_SAL_LOG_HXX
11 #define INCLUDED_SAL_LOG_HXX
13 #include "sal/config.h"
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
29 extern "C" SAL_DLLPUBLIC
void SAL_CALL
sal_detail_log(
30 sal_detail_LogLevel level
, char const * area
, char const * where
,
31 char const * message
, sal_uInt32 backtraceDepth
);
33 extern "C" SAL_DLLPUBLIC sal_Bool SAL_CALL
sal_detail_log_report(
34 sal_detail_LogLevel level
, char const * area
);
36 namespace sal
{ namespace detail
{
39 sal_detail_LogLevel level
, char const * area
, char const * where
,
40 std::ostringstream
const & stream
, sal_uInt32 backtraceDepth
)
42 // An alternative would be to have sal_detail_log take a std::ostringstream
43 // pointer (via a C void pointer); the advantage would be smaller client
44 // code (the ".str().c_str()" part would move into the implementation of
45 // sal_detail_log) and potential for proper support of embedded null
46 // characters within the message, but the disadvantage would be dependence
47 // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
48 // to this inline function so that it is potentially only emitted once per
50 sal_detail_log(level
, area
, where
, stream
.str().c_str(), backtraceDepth
);
53 // Special handling of the common case where the message consists of just a
54 // string literal, to produce smaller call-site code:
56 struct StreamStart
{};
59 StreamString(char const * s
): string(s
) {}
67 typedef struct { char a
[2]; } Result
;
70 inline StreamString
operator <<(
71 SAL_UNUSED_PARAMETER StreamStart
const &, char const * s
)
73 return StreamString(s
);
76 template< typename T
> inline StreamIgnore
operator <<(
77 SAL_UNUSED_PARAMETER StreamStart
const &, SAL_UNUSED_PARAMETER T
const &)
80 #if defined _MSC_VER && _MSC_VER < 1700
81 return StreamIgnore();
85 template< typename T
> inline StreamIgnore
operator <<(
86 SAL_UNUSED_PARAMETER StreamString
const &, SAL_UNUSED_PARAMETER T
const &)
89 #if defined _MSC_VER && _MSC_VER < 1700
90 return StreamIgnore();
94 template< typename T
> inline StreamIgnore
operator <<(
95 SAL_UNUSED_PARAMETER StreamIgnore
const &, SAL_UNUSED_PARAMETER T
const &)
98 #if defined _MSC_VER && _MSC_VER < 1700
99 return StreamIgnore();
103 template< typename T
> typename
T::Result
getResult(T
const &);
105 inline char const * unwrapStream(StreamString
const & s
) { return s
.string
; }
107 inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore
const &) {
109 #if defined _MSC_VER && _MSC_VER < 1700
116 #define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
118 if ((condition) && sal_detail_log_report(level, area)) { \
119 if (sizeof ::sal::detail::getResult( \
120 ::sal::detail::StreamStart() << stream) == 1) \
123 (level), (area), (where), \
124 ::sal::detail::unwrapStream( \
125 ::sal::detail::StreamStart() << stream), \
128 ::std::ostringstream sal_detail_stream; \
129 sal_detail_stream << stream; \
130 ::sal::detail::log( \
131 (level), (area), (where), sal_detail_stream, 0); \
138 /** A simple macro to create a "file and line number" string.
140 Potentially not only useful within the log framework (where it is used
141 automatically), but also when creating exception messages.
143 @attention For now, this functionality should only be used internally within
144 LibreOffice. It may change again in a future version.
146 @since LibreOffice 3.5
148 #define SAL_WHERE SAL_DETAIL_WHERE
150 /** A facility for generating temporary string messages by piping items into a
151 C++ std::ostringstream.
153 This can be useful for example in a call to SAL_INFO when depending on some
154 boolean condition data of incompatible types shall be streamed into the
157 SAL_INFO("foo", "object: " << (hasName ? obj->name : SAL_STREAM(obj)));
159 @attention For now, this functionality should only be used internally within
160 LibreOffice. It may change again in a future version.
162 @since LibreOffice 3.5
164 #if defined _LIBCPP_VERSION || (defined _MSC_VER && _MSC_VER >= 1915)
165 #define SAL_STREAM(stream) \
166 (::std::ostringstream() << stream).str()
168 #define SAL_STREAM(stream) \
169 (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream).str())
173 @page sal_log Basic logging functionality.
175 @short Macros for logging.
177 SAL_INFO(char const * area, expr),
178 SAL_INFO_IF(bool condition, char const * area, expr),
179 SAL_WARN(char const * area, expr),
180 SAL_WARN_IF(bool condition, char const * area, expr), and SAL_DEBUG(expr)
181 produce an info, warning, or debug log entry with a message produced by
182 piping items into a C++ std::ostringstream. The given expr must be so that
183 the full expression "stream << expr" is valid, where stream is a variable of
184 type std::ostringstream.
186 SAL_INFO("foo", "string " << s << " of length " << n)
188 would be an example of such a call.
190 The composed message should be in UTF-8 and it should contain no vertical
191 formatting characters and no null characters
193 For the _IF variants, log output is only generated if the given condition is
194 true (in addition to the other conditions that have to be met).
196 The SAL_DEBUG macro is for temporary debug statements that are used while
197 working on code. It is never meant to remain in the code. It will always
198 simply output the given expression in debug builds.
200 For all the other macros, the given area argument must be non-null and must
201 match the regular expression
204 <area> ::= <segment>("."<segment>)*
210 <segment> ::= [0-9a-z]+
213 For a list of areas used see @ref sal_log_areas "SAL debug areas". Whenever
214 you use a new log area, add it to the file include/sal/log-areas.dox .
216 Whether these macros generate any log output is controlled in a two-stage
219 First, at compile time the macros SAL_LOG_INFO and SAL_LOG_WARN,
220 respectively, control whether the INFO and WARN macros, respectively,
221 expand to actual code (in case the macro is defined, to any value) or to
222 no-ops (in case the macro is not defined).
224 Second, at runtime the environment variable SAL_LOG further limits which
225 macro calls actually generate log output. The environment variable SAL_LOG
226 must either be unset or must match the regular expression
235 <switch> ::= <sense><item>
237 <item> ::= <flag>|<level>("."<area>)?
238 <flag> ::= "TIMESTAMP"|"RELATIVETIMER"
239 <level> ::= "INFO"|"WARN"
242 If the environment variable is unset, the setting "+WARN" is
243 assumed instead (which results in all warnings being output but no
244 infos). If the given value does not match the regular expression,
245 "+INFO+WARN" is used instead (which in turn results in everything
248 The "+TIMESTAMP" flag causes each output line (as selected by the level
249 switch(es)) to be prefixed by a timestamp like 2016-08-18:14:04:43.
251 The "+RELATIVETIMER" flag causes each output line (as selected by
252 the level switch(es)) to be prefixed by a relative timestamp in
253 seconds since the first output line like 1.312.
255 If both +TIMESTAMP and +RELATIVETIMER are specified, they are
256 output in that order.
258 Specifying a flag with a negative sense has no effect. Specifying
259 the same flag multiple times has no extra effect.
261 A given macro call's level (INFO or WARN) and area is matched against the
262 given switches as follows: Only those switches for which the level matches
263 the given level and for which the area is a prefix (including both empty and
264 full prefixes) of the given area are considered. Log output is generated if
265 and only if among the longest such switches (if any), there is at least one
266 that has a sense of "+". (That is, if both +INFO.foo and -INFO.foo are
267 present, +INFO.foo wins.)
269 If no WARN selection is specified, but an INFO selection is, the
270 INFO selection is used for WARN messages, too.
272 For example, if SAL_LOG is "+INFO-INFO.foo+INFO.foo.bar", then calls like
273 SAL_INFO("foo.bar", ...), SAL_INFO("foo.bar.baz", ...), or
274 SAL_INFO("other", ...) generate output, while calls like
275 SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
277 The generated log output consists of the optional timestamp, the given level
278 ("info" or "warn"), the given area, the process ID, the thread ID, the
279 source file, and the source line number, each followed by a colon, followed
280 by a space, the given message, and a newline. The precise format of the log
281 output is subject to change. The log output is printed to stderr without
282 further text encoding conversion.
284 On some systems, log output can be redirected to other log sinks,
285 notably a file provided as a system path and filename via
286 environment variable SAL_LOG_FILE; or to a syslog facility if
287 LibreOffice is suitably built, by setting environment variable
290 @see @ref sal_log_areas
292 @attention For now, this functionality should only be used internally within
293 LibreOffice. It may change again in a future version.
295 @since LibreOffice 3.5
299 Produce log entry from stream in the given log area.
301 See @ref sal_log "basic logging functionality" for details.
303 #define SAL_INFO(area, stream) \
304 SAL_DETAIL_LOG_STREAM( \
305 SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
309 Produce log entry from stream in the given log area if condition is true.
311 See @ref sal_log "basic logging functionality" for details.
313 #define SAL_INFO_IF(condition, area, stream) \
314 SAL_DETAIL_LOG_STREAM( \
315 SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
316 ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
319 Produce warning entry from stream in the given log area.
321 See @ref sal_log "basic logging functionality" for details.
323 #define SAL_WARN(area, stream) \
324 SAL_DETAIL_LOG_STREAM( \
325 SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
329 Produce warning entry from stream in the given log area if condition is true.
331 See @ref sal_log "basic logging functionality" for details.
333 #define SAL_WARN_IF(condition, area, stream) \
334 SAL_DETAIL_LOG_STREAM( \
335 SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
336 ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
339 Produce temporary debugging output from stream. This macro is meant to be
340 used only while working on code and should never exist in production code.
342 See @ref sal_log "basic logging functionality" for details.
344 #define SAL_DEBUG(stream) \
345 SAL_DETAIL_LOG_STREAM( \
346 SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, stream)
349 Produce temporary debugging output from stream along with a backtrace of the
352 This macro is meant to be used only while working on code and should never
353 exist in production code.
355 @param stream input stream
357 @param backtraceDepth a sal_uInt32 value indicating the maximum backtrace
358 depth; zero means no backtrace
360 See @ref sal_log "basic logging functionality" for details.
362 #define SAL_DEBUG_BACKTRACE(stream, backtraceDepth) \
364 if (sizeof ::sal::detail::getResult( \
365 ::sal::detail::StreamStart() << stream) == 1) \
368 ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, \
369 ::sal::detail::unwrapStream( \
370 ::sal::detail::StreamStart() << stream), \
373 ::std::ostringstream sal_detail_stream; \
374 sal_detail_stream << stream; \
375 ::sal::detail::log( \
376 ::SAL_DETAIL_LOG_LEVEL_DEBUG, NULL, NULL, sal_detail_stream, \
385 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */