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 enum sal_detail_LogLevel level
, char const * area
, char const * where
,
31 char const * message
);
33 namespace sal
{ namespace detail
{
35 inline void SAL_CALL
log(
36 sal_detail_LogLevel level
, char const * area
, char const * where
,
37 std::ostringstream
const & stream
)
39 // An alternative would be to have sal_detail_log take a std::ostringstream
40 // pointer (via a C void pointer); the advantage would be smaller client
41 // code (the ".str().c_str()" part would move into the implementation of
42 // sal_detail_log) and potential for proper support of embedded null
43 // characters within the message, but the disadvantage would be dependence
44 // on the C++ ABI; as a compromise, the ".str().c_str()" part has been moved
45 // to this inline function so that it is potentially only emitted once per
47 sal_detail_log(level
, area
, where
, stream
.str().c_str());
50 // Special handling of the common case where the message consists of just a
51 // string literal, to produce smaller call-site code:
53 struct StreamStart
{};
56 StreamString(char const * s
): string(s
) {}
64 typedef struct { char a
[2]; } Result
;
67 inline StreamString
operator <<(
68 SAL_UNUSED_PARAMETER StreamStart
const &, char const * s
)
70 return StreamString(s
);
73 template< typename T
> inline StreamIgnore
operator <<(
74 SAL_UNUSED_PARAMETER StreamStart
const &, SAL_UNUSED_PARAMETER T
const &)
77 #if defined _MSC_VER && _MSC_VER < 1700
78 return StreamIgnore();
82 template< typename T
> inline StreamIgnore
operator <<(
83 SAL_UNUSED_PARAMETER StreamString
const &, SAL_UNUSED_PARAMETER T
const &)
86 #if defined _MSC_VER && _MSC_VER < 1700
87 return StreamIgnore();
91 template< typename T
> inline StreamIgnore
operator <<(
92 SAL_UNUSED_PARAMETER StreamIgnore
const &, SAL_UNUSED_PARAMETER T
const &)
95 #if defined _MSC_VER && _MSC_VER < 1700
96 return StreamIgnore();
100 template< typename T
> typename
T::Result
getResult(T
const &);
102 inline char const * unwrapStream(StreamString
const & s
) { return s
.string
; }
104 inline char const * unwrapStream(SAL_UNUSED_PARAMETER StreamIgnore
const &) {
106 #if defined _MSC_VER && _MSC_VER < 1700
113 #define SAL_DETAIL_LOG_STREAM(condition, level, area, where, stream) \
116 if (sizeof ::sal::detail::getResult( \
117 ::sal::detail::StreamStart() << stream) == 1) \
120 (level), (area), (where), \
121 ::sal::detail::unwrapStream( \
122 ::sal::detail::StreamStart() << stream)); \
124 ::std::ostringstream sal_detail_stream; \
125 sal_detail_stream << stream; \
126 ::sal::detail::log( \
127 (level), (area), (where), sal_detail_stream); \
134 /** A simple macro to create a "file and line number" string.
136 Potentially not only useful within the log framework (where it is used
137 automatically), but also when creating exception messages.
139 @attention For now, this functionality should only be used internally within
140 LibreOffice. It may change again in a future version.
142 @since LibreOffice 3.5
144 #define SAL_WHERE SAL_DETAIL_WHERE
146 /** A facility for generating temporary string messages by piping items into a
147 C++ std::ostringstream.
149 This can be useful for example in a call to SAL_INFO when depending on some
150 boolean condition data of incompatible types shall be streamed into the
153 SAL_INFO("foo", "object: " << (hasName ? obj->name : SAL_STREAM(obj)));
155 @attention For now, this functionality should only be used internally within
156 LibreOffice. It may change again in a future version.
158 @since LibreOffice 3.5
160 #define SAL_STREAM(stream) \
161 (dynamic_cast< ::std::ostringstream & >(::std::ostringstream() << stream). \
165 @page sal_log Basic logging functionality.
167 @short Macros for logging.
169 SAL_INFO(char const * area, expr),
170 SAL_INFO_IF(bool condition, char const * area, expr),
171 SAL_WARN(char const * area, expr),
172 SAL_WARN_IF(bool condition, char const * area, expr), and SAL_DEBUG(expr)
173 produce an info, warning, or debug log entry with a message produced by
174 piping items into a C++ std::ostringstream. The given expr must be so that
175 the full expression "stream << expr" is valid, where stream is a variable of
176 type std::ostringstream.
178 SAL_INFO("foo", "string " << s << " of length " << n)
180 would be an example of such a call.
182 The composed message should be in UTF-8 and it should contain no vertical
183 formatting characters and no null characters
185 For the _IF variants, log output is only generated if the given condition is
186 true (in addition to the other conditions that have to be met).
188 The SAL_DEBUG macro is for temporary debug statements that are used while
189 working on code. It is never meant to remain in the code. It will always
190 simply output the given expression in debug builds.
192 For all the other macros, the given area argument must be non-null and must
193 match the regular expression
196 <area> ::= <segment>("."<segment>)*
202 <segment> ::= [0-9a-z]+
205 For a list of areas used see @ref sal_log_areas "SAL debug areas". Whenever
206 you use a new log area, add it to the file include/sal/log-areas.dox .
208 Whether these macros generate any log output is controlled in a two-stage
211 First, at compile time the macros SAL_LOG_INFO and SAL_LOG_WARN,
212 respectively, control whether the INFO and WARN macros, respectively,
213 expand to actual code (in case the macro is defined, to any value) or to
214 no-ops (in case the macro is not defined).
216 Second, at runtime the environment variable SAL_LOG further limits which
217 macro calls actually generate log output. The environment variable SAL_LOG
218 must either be unset or must match the regular expression
227 <switch> ::= <sense><level>("."<area>)?
229 <level> ::= "INFO"|"WARN"
232 If the environment variable is unset, "+WARN" is used instead (which results
233 in all warnings being output but no infos). If the given value does not
234 match the regular expression, "+INFO+WARN" is used instead (which in turn
235 results in everything being output).
237 A given macro call's level (INFO or WARN) and area is matched against the
238 given switches as follows: Only those switches for which the level matches
239 the given level and for which the area is a prefix (including both empty and
240 full prefixes) of the given area are considered. Log output is generated if
241 and only if among the longest such switches (if any), there is at least one
242 that has a sense of "+". (That is, if both +INFO.foo and -INFO.foo are
243 present, +INFO.foo wins.)
245 For example, if SAL_LOG is "+INFO-INFO.foo+INFO.foo.bar", then calls like
246 SAL_INFO("foo.bar", ...), SAL_INFO("foo.bar.baz", ...), or
247 SAL_INFO("other", ...) generate output, while calls like
248 SAL_INFO("foo", ...) or SAL_INFO("foo.barzzz", ...) do not.
250 The generated log output consists of the given level ("info" or "warn"), the
251 given area, the process ID, the thread ID, the source file, and the source
252 line number, each followed by a colon, followed by a space, the given
253 message, and a newline. The precise format of the log output is subject to
254 change. The log output is printed to stderr without further text encoding
257 @see @ref sal_log_areas
259 @attention For now, this functionality should only be used internally within
260 LibreOffice. It may change again in a future version.
262 @since LibreOffice 3.5
266 Produce log entry from stream in the given log area.
268 See @ref sal_log "basic logging functionality" for details.
270 #define SAL_INFO(area, stream) \
271 SAL_DETAIL_LOG_STREAM( \
272 SAL_DETAIL_ENABLE_LOG_INFO, ::SAL_DETAIL_LOG_LEVEL_INFO, area, \
276 Produce log entry from stream in the given log area if condition is true.
278 See @ref sal_log "basic logging functionality" for details.
280 #define SAL_INFO_IF(condition, area, stream) \
281 SAL_DETAIL_LOG_STREAM( \
282 SAL_DETAIL_ENABLE_LOG_INFO && (condition), \
283 ::SAL_DETAIL_LOG_LEVEL_INFO, area, SAL_WHERE, stream)
286 Produce warning entry from stream in the given log area.
288 See @ref sal_log "basic logging functionality" for details.
290 #define SAL_WARN(area, stream) \
291 SAL_DETAIL_LOG_STREAM( \
292 SAL_DETAIL_ENABLE_LOG_WARN, ::SAL_DETAIL_LOG_LEVEL_WARN, area, \
296 Produce warning entry from stream in the given log area if condition is true.
298 See @ref sal_log "basic logging functionality" for details.
300 #define SAL_WARN_IF(condition, area, stream) \
301 SAL_DETAIL_LOG_STREAM( \
302 SAL_DETAIL_ENABLE_LOG_WARN && (condition), \
303 ::SAL_DETAIL_LOG_LEVEL_WARN, area, SAL_WHERE, stream)
306 Produce temporary debugging output from stream. This macro is meant to be
307 used only while working on code and should never exist in production code.
309 See @ref sal_log "basic logging functionality" for details.
311 #define SAL_DEBUG(stream) \
312 SAL_DETAIL_LOG_STREAM( \
313 SAL_LOG_TRUE, ::SAL_DETAIL_LOG_LEVEL_DEBUG, 0, 0, stream)
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */