BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bsls_log.h
Go to the documentation of this file.
1/// @file bsls_log.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bsls_log.h -*-C++-*-
8#ifndef INCLUDED_BSLS_LOG
9#define INCLUDED_BSLS_LOG
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bsls_log bsls_log
15/// @brief Provide a namespace for low-level logging functions.
16/// @addtogroup bsl
17/// @{
18/// @addtogroup bsls
19/// @{
20/// @addtogroup bsls_log
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bsls_log-purpose"> Purpose</a>
25/// * <a href="#bsls_log-classes"> Classes </a>
26/// * <a href="#bsls_log-macros"> Macros </a>
27/// * <a href="#bsls_log-description"> Description </a>
28/// * <a href="#bsls_log-macro-reference"> Macro Reference </a>
29/// * <a href="#bsls_log-motivation"> Motivation </a>
30/// * <a href="#bsls_log-functionality"> Functionality </a>
31/// * <a href="#bsls_log-log-message-handler"> Log Message Handler </a>
32/// * <a href="#bsls_log-writing-log-messages"> Writing Log Messages </a>
33/// * <a href="#bsls_log-log-severity-and-the-severity-threshold"> Log Severity and the Severity Threshold </a>
34/// * <a href="#bsls_log-usage"> Usage </a>
35/// * <a href="#bsls_log-example-1-logging-formatted-messages"> Example 1: Logging Formatted Messages </a>
36///
37/// # Purpose {#bsls_log-purpose}
38/// Provide a namespace for low-level logging functions.
39///
40/// # Classes {#bsls_log-classes}
41///
42/// - bsls::Log: namespace for low-level logging functions
43///
44/// # Macros {#bsls_log-macros}
45///
46/// - BSLS_LOG: write log message using `printf`-style format specification
47/// - BSLS_LOG_SIMPLE: write log message as an unformatted string
48/// - BSLS_LOG_FATAL: write fatal message using `printf` format specification
49/// - BSLS_LOG_ERROR: write error message using `printf` format specification
50/// - BSLS_LOG_WARN: write warning message using `printf` format specification
51/// - BSLS_LOG_INFO: write info message using `printf` format specification
52/// - BSLS_LOG_DEBUG: write debug message using `printf` format specification
53/// - BSLS_LOG_TRACE: write trace message using `printf` format specification
54///
55/// @see bsls_logseverity
56///
57/// # Description {#bsls_log-description}
58/// This component provides a set of macros, along with a
59/// namespace, `bsls::Log`, which contains a suite of utility functions for
60/// logging in low-level code. The macros and functions in this component
61/// provide a consistent interface for logging across different platforms
62/// through the use of a global cross-platform log message handler function.
63/// Users can customize the logging behavior by providing their own log message
64/// handler function. Note that this component is intended to be used only when
65/// a more fully-featured logger is not available.
66///
67/// ## Macro Reference {#bsls_log-macro-reference}
68///
69///
70/// This section provides documentation for the macros defined in this component.
71/// @code
72/// BSLS_LOG(severity, ...)
73/// If the specified 'severity' is at least as severe as
74/// 'Log::severityThreshold', write a message having 'severity' to the
75/// currently installed log message handler, which contains a formatted
76/// string that would result from applying the 'printf'-style formatting
77/// rules to the specified '...', using the first parameter as the format
78/// string and any further parameters as the expected substitutions. If
79/// 'severity' is less severe than 'severityThreshold' then this macro has
80/// no effect. The file name and line number of the point of expansion of
81/// the macro are automatically used as the file name and line number for
82/// the log message. The behavior is undefined unless the first parameter
83/// of '...' is a valid 'printf'-style format string, and all substitutions
84/// needed by the format string are in the subsequent elements of '...'.
85///
86/// BSLS_LOG_FATAL(...)
87/// BSLS_LOG_ERROR(...)
88/// BSLS_LOG_WARN(...)
89/// BSLS_LOG_INFO(...)
90/// BSLS_LOG_DEBUG(...)
91/// BSLS_LOG_TRACE(...)
92/// Instantiate the 'BSLS_LOG' macro with the severity appropriate for
93/// the macros name. Note that this is syntactic sugar, to avoid the
94/// complete text "bsls::LogSeverity::e_" being needed each time a message
95/// is logged with 'BSLS_LOG'.
96///
97/// BSLS_LOG_SIMPLE(severity, msg)
98/// If the specified 'severity' is at least as severe as
99/// 'Log::severityThreshold', write a message having 'severity' and the
100/// specified 'msg' to the currently installed log message handler, with the
101/// file name and line number of the point of expansion of the macro
102/// automatically used as the file name and line number of the log. If
103/// 'severity' is less severe than 'severityThreshold' then this macro has
104/// no effect.
105/// @endcode
106///
107/// ## Motivation {#bsls_log-motivation}
108///
109///
110/// Using the functionality of this component instead of writing messages
111/// directly to `stderr` has the following advantages:
112///
113/// * Users have the freedom to customize the default logging behavior.
114/// A user may want all logs to be automatically redirected to a file or may
115/// want to add some custom formatting or handling. These abilities are not
116/// available if the output stream is predetermined.
117/// * The logging mechanism behaves correctly on all platforms by default.
118/// Some platforms have particular restrictions on the use of the standard
119/// output streams. For example, Windows applications running in non-console
120/// mode do not have a concept of `stdout` or `stderr`; writing directly to
121/// either of these streams is known to hang the process when no console is
122/// attached.
123///
124/// ## Functionality {#bsls_log-functionality}
125///
126///
127/// This section describes the functionality provided by this component in more
128/// detail.
129///
130/// ### Log Message Handler {#bsls_log-log-message-handler}
131///
132///
133/// The `bsls::Log` class provides two `static` methods, `logMessageHandler` and
134/// `setLogMessageHandler`, which can be used, respectively, to retrieve and set
135/// the globally installed log message handler through which all log messages
136/// are written. All log message handlers must follow the signature and
137/// contract requirements of the `bsls::Log::LogMessageHandler` `typedef`.
138///
139/// The log message handler `bsls::Log::platformDefaultMessageHandler` is
140/// installed by default as the global handler. This handler writes all log
141/// messages to `stderr`, except in Windows non-console mode where the
142/// destination of the `OutputDebugString` function is used.
143///
144/// In addition to the default handler, the log message handlers
145/// `bsls::Log::stdoutMessageHandler` and `bsls::Log::stderrMessageHandler` are
146/// provided as a set of simple handlers that write log messages to `stdout` and
147/// `stderr`, respectively.
148///
149/// ### Writing Log Messages {#bsls_log-writing-log-messages}
150///
151///
152/// There are four ways to invoke the currently installed log message handler,
153/// depending on the specific behavior required: The macro `BSLS_LOG` allows a
154/// formatted message to be written using a `printf`-style format string. The
155/// macro `BSLS_LOG_SIMPLE` allows a simple, unformatted string to be written.
156/// Both of the macros automatically use the file name and line number of the
157/// point that the macro was invoked. The `static` methods
158/// `bsls::Log::logFormattedMessage` and `bsls::Log::logMessage` provide the
159/// same functionality as `BSLS_LOG` and 'BSLS_LOG_SIMPLE, respectively, except
160/// that these two methods allow a file name and line number to be passed in as
161/// parameters. This is described in table form as follows:
162/// @code
163/// .=========================================================================.
164/// | Mechanism | Formatted | Automatic File & Line |
165/// |=========================================================================|
166/// | BSLS_LOG | YES | YES |
167/// |--------------------------------|--------------|-------------------------|
168/// | BSLS_LOG_[LEVEL] | YES | YES |
169/// |--------------------------------|--------------|-------------------------|
170/// | BSLS_LOG_SIMPLE | NO | YES |
171/// |--------------------------------|--------------|-------------------------|
172/// | bsls::Log::logFormattedMessage | YES | NO |
173/// |--------------------------------|--------------|-------------------------|
174/// | bsls::Log::logMessage | NO | NO |
175/// `-------------------------------------------------------------------------'
176/// @endcode
177///
178/// ### Log Severity and the Severity Threshold {#bsls_log-log-severity-and-the-severity-threshold}
179///
180///
181/// Clients submitting a message to `bsls::Log` (either through a function or
182/// one of the macros) either implicitly or explicitly provide a severity level
183/// describing the relative importance of that message to clients. The possible
184/// severity levels are FATAL, ERROR, WARNING, INFO, DEBUG, and TRACE (these are
185/// enumerated in @ref bsls_logseverity ).
186///
187/// The severity of a logged message is used to determine whether the message
188/// is published to the log using the currently installed `LogMessageHandler`
189/// callback. Also, typically a `LogMessageHandler` callback implementation
190/// will report a message's severity along side that message in the log.
191///
192/// Clients can configure the severity threshold, at or above which a log
193/// message will be published, using `setSeverityThreshold`. For example:
194/// @code
195/// // Messages having 'e_WARN' or higher severity will be output to the log.
196///
197/// bsls::Log::setSeverityThreshold(bsls::LogSeverity::e_WARN);
198/// @endcode
199///
200/// ## Usage {#bsls_log-usage}
201///
202///
203/// This section illustrates the intended use of this component.
204///
205/// ### Example 1: Logging Formatted Messages {#bsls_log-example-1-logging-formatted-messages}
206///
207///
208/// Suppose that we want to write a formatted log message using `printf`-style
209/// format specifiers when the preconditions of a function are not met. The
210/// `BSLS_LOG` macro can be used for this purpose.
211///
212/// First, we begin to define a function, `add`, which will return the sum of
213/// two positive integer values:
214/// @code
215/// // myapp.cpp
216///
217/// unsigned int add(int a, int b)
218/// // Return the sum of the specified 'a' and the specified 'b'. The
219/// // behavior is undefined unless 'a' and 'b' are not negative.
220/// {
221/// @endcode
222///
223/// Now, we check the precondition of the function, and use the `BSLS_LOG_ERROR`
224/// macro to write a log message if one of the input parameters is less than 0:
225/// @code
226/// if(a < 0 || b < 0) {
227/// BSLS_LOG_ERROR("Invalid input combination (%d, %d).", a, b);
228/// return 0; // RETURN
229/// }
230///
231/// return static_cast<unsigned int>(a) + static_cast<unsigned int>(b);
232/// }
233/// @endcode
234///
235/// Next, we may erroneously call the `add` function with a negative argument:
236/// @code
237/// unsigned int x = add(3, -100);
238/// @endcode
239/// Finally, assuming the default log message handler is currently installed, we
240/// observe the following output printed to `stderr` or to the Windows debugger:
241/// @code
242/// ERROR myapp.cpp:8 Invalid input combination (3, -100).
243/// @endcode
244/// Note that an arbitrary string should never be passed to `BSLS_LOG` as the
245/// format string. If the string happens to contain `printf`-style format
246/// specifiers but the expected substitutions are not present, it will lead to
247/// undefined behavior.
248/// @}
249/** @} */
250/** @} */
251
252/** @addtogroup bsl
253 * @{
254 */
255/** @addtogroup bsls
256 * @{
257 */
258/** @addtogroup bsls_log
259 * @{
260 */
261
262#include <bsls_atomicoperations.h>
263#include <bsls_logseverity.h>
264#include <bsls_pointercastutil.h>
265#include <bsls_types.h>
266
267
268namespace bsls {
269
270 // =========
271 // class Log
272 // =========
273
274/// This class serves as a namespace containing a suite of utility functions
275/// that allow low-level code to write log messages to a configurable,
276/// globally controlled destination.
277///
278/// See @ref bsls_log
279class Log {
280
281 public:
282 // TYPES
283
284 /// The `LogMessageHandler` `typedef` represents a type of function that
285 /// handles log messages in an unspecified way (e.g., by writing the log
286 /// message to an output stream or to a file). Because they can be
287 /// called concurrently from multiple threads, log message handlers
288 /// must be thread-safe. While installed, handlers must exhibit only
289 /// defined behavior if the specified `file` is a null-terminated
290 /// string, the specified `line` is not negative, and the specified
291 /// `message` is a null-terminated string.
293 const char *file,
294 int line,
295 const char *message);
296
297 private:
298 // CLASS DATA
299 static bsls::AtomicOperations::AtomicTypes::Pointer
300 s_logMessageHandler; // the currently
301 // installed log
302 // message handler
303 // (not owned)
304
305 static bsls::AtomicOperations::AtomicTypes::Int
306 s_severityThreshold; // the current
307 // severity
308 // threshold
309 public:
310 // CLASS METHODS
311
312 /// If the specified `severity` is at least as severe as
313 /// `severityThrehold`, invoke the currently installed log message
314 /// handler with `severity` and the specified `file` and `line`, as
315 /// well as a message string created by calling `sprintf` on the
316 /// specified `format` with the specified variadic arguments; otherwise
317 /// (if `severity` is less severe), this operation has no effect. The
318 /// behavior is undefined unless `0 <= line`, and `format` is a valid
319 /// `sprintf` format specification for the supplied variadic arguments.
321 const char *file,
322 int line,
323 const char *format,
324 ...);
325
326 /// If the specified `severity` is at least as severe as
327 /// `severityThreshold`, invoke the currently installed log message
328 /// handler with `severity`, as well as the specified `file`, `line`,
329 /// and `message`; otherwise (if `severity` is less severe), this
330 /// operation has no effect. The behavior is undefined unless
331 /// `0 <= line`.
332 static void logMessage(bsls::LogSeverity::Enum severity,
333 const char *file,
334 int line,
335 const char *message);
336
337 /// Return the address of the currently installed log message handler.
339
340 /// Write, to a platform-specific destination, a string composed of the
341 /// specified `severity`, `file` name, `line` number, and `message`. On
342 /// *non*-Windows systems, write the log record to the `stderr` output
343 /// stream. On *Windows* systems: If the current process is running in
344 /// *console* *mode*, write the log record to the `stderr` output
345 /// stream. If the current process is running in *non-console* *mode*,
346 /// write the log record to the Windows process debugger. The behavior
347 /// is undefined unless `0 <= line`. Note that this function is used as
348 /// the default log message handler. Also note that this function will
349 /// write the message irrespective of the current `severityThreshold`.
352 const char *file,
353 int line,
354 const char *message);
355
356 /// Install the specified `handler` as the current log message handler.
357 static void setLogMessageHandler(Log::LogMessageHandler handler);
358
359 /// Set the severity threshold at which log records are written by
360 /// `logMessage` and `logFormattedMessage` to the specified `severity`.
361 static void setSeverityThreshold(bsls::LogSeverity::Enum severity);
362
363 /// Return the currently configured severity threshold at or above which
364 /// records are written by `logMessage` and `logFormattedMessage`.
366
367 /// Write, to the `stderr` output stream, a string composed of the
368 /// specified `severity`, `file` name, `line` number, and the `message`.
369 /// The behavior is undefined unless `0 <= line`. Note that this
370 /// function provides an implementation of the `LogMessageHandler`
371 /// function prototype, and will write the message irrespective of the
372 /// current `severityThreshold`.
374 const char *file,
375 int line,
376 const char *message);
377
378 /// Write, to the `stdout` output stream, a string composed of the
379 /// specified `severity`, `file` name, `line` number, and the `message`.
380 /// The behavior is undefined unless `0 <= line`. Note that this
381 /// function provides an implementation of the `LogMessageHandler`
382 /// function prototype, and will write the message irrespective of the
383 /// current `severityThreshold`.
385 const char *file,
386 int line,
387 const char *message);
388};
389
390} // close package namespace
391
392
393 // ==========================
394 // BSLS_LOG Macro Definitions
395 // ==========================
396
397
398#define BSLS_LOG(severity, ...) \
399 do { \
400 if (severity <= BloombergLP::bsls::Log::severityThreshold()) { \
401 BloombergLP::bsls::Log::logFormattedMessage((severity), \
402 __FILE__, \
403 __LINE__, \
404 __VA_ARGS__); \
405 } \
406 } while(false)
407
408#define BSLS_LOG_FATAL(...) BSLS_LOG(BloombergLP::bsls::LogSeverity::e_FATAL,\
409 __VA_ARGS__)
410#define BSLS_LOG_ERROR(...) BSLS_LOG(BloombergLP::bsls::LogSeverity::e_ERROR,\
411 __VA_ARGS__)
412#define BSLS_LOG_WARN(...) BSLS_LOG(BloombergLP::bsls::LogSeverity::e_WARN, \
413 __VA_ARGS__)
414#define BSLS_LOG_INFO(...) BSLS_LOG(BloombergLP::bsls::LogSeverity::e_INFO, \
415 __VA_ARGS__)
416#define BSLS_LOG_DEBUG(...) BSLS_LOG(BloombergLP::bsls::LogSeverity::e_DEBUG,\
417 __VA_ARGS__)
418#define BSLS_LOG_TRACE(...) BSLS_LOG(BloombergLP::bsls::LogSeverity::e_TRACE,\
419 __VA_ARGS__)
420
421#define BSLS_LOG_SIMPLE(severity, msg) \
422 (BloombergLP::bsls::Log::logMessage((severity), __FILE__, __LINE__, (msg)))
423
424
425namespace bsls {
426
427// ============================================================================
428// INLINE DEFINITIONS
429// ============================================================================
430
431 // =========
432 // class Log
433 // =========
434
435// CLASS METHODS
436inline
438 const char *file,
439 int line,
440 const char *message)
441{
442 if (severity <= severityThreshold()) {
443 (logMessageHandler())(severity, file, line, message);
444 }
445}
446
447inline
449{
450 return PointerCastUtil::cast<LogMessageHandler>(
451 bsls::AtomicOperations::getPtrAcquire(&s_logMessageHandler));
452}
453
454inline
456{
458 &s_logMessageHandler, PointerCastUtil::cast<void *>(handler));
459}
460
461inline
463{
464 bsls::AtomicOperations::setIntRelaxed(&s_severityThreshold, severity);
465}
466
467inline
473
474} // close package namespace
475
476
477#endif
478
479// ----------------------------------------------------------------------------
480// Copyright 2013 Bloomberg Finance L.P.
481//
482// Licensed under the Apache License, Version 2.0 (the "License");
483// you may not use this file except in compliance with the License.
484// You may obtain a copy of the License at
485//
486// http://www.apache.org/licenses/LICENSE-2.0
487//
488// Unless required by applicable law or agreed to in writing, software
489// distributed under the License is distributed on an "AS IS" BASIS,
490// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
491// See the License for the specific language governing permissions and
492// limitations under the License.
493// ----------------------------- END-OF-FILE ----------------------------------
494
495/** @} */
496/** @} */
497/** @} */
Definition bsls_log.h:279
static bsls::LogSeverity::Enum severityThreshold()
Definition bsls_log.h:468
static Log::LogMessageHandler logMessageHandler()
Return the address of the currently installed log message handler.
Definition bsls_log.h:448
static void platformDefaultMessageHandler(bsls::LogSeverity::Enum severity, const char *file, int line, const char *message)
static void logMessage(bsls::LogSeverity::Enum severity, const char *file, int line, const char *message)
Definition bsls_log.h:437
static void logFormattedMessage(bsls::LogSeverity::Enum severity, const char *file, int line, const char *format,...)
static void stdoutMessageHandler(bsls::LogSeverity::Enum severity, const char *file, int line, const char *message)
static void setSeverityThreshold(bsls::LogSeverity::Enum severity)
Definition bsls_log.h:462
void(* LogMessageHandler)(bsls::LogSeverity::Enum severity, const char *file, int line, const char *message)
Definition bsls_log.h:292
static void stderrMessageHandler(bsls::LogSeverity::Enum severity, const char *file, int line, const char *message)
static void setLogMessageHandler(Log::LogMessageHandler handler)
Install the specified handler as the current log message handler.
Definition bsls_log.h:455
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlt_iso8601util.h:691
static void * getPtrAcquire(AtomicTypes::Pointer const *atomicPtr)
Definition bsls_atomicoperations.h:2312
static void setIntRelaxed(AtomicTypes::Int *atomicInt, int value)
Definition bsls_atomicoperations.h:1552
static int getIntRelaxed(AtomicTypes::Int const *atomicInt)
Definition bsls_atomicoperations.h:1534
static void setPtrRelease(AtomicTypes::Pointer *atomicPtr, void *value)
Definition bsls_atomicoperations.h:2345
Enum
Definition bsls_logseverity.h:125