Getting Started with Slic¶
This section illustrates some of the key concepts and capabilities of Slic by
presenting a short walk-through of a C++ application. The complete
Slic Application Code Example is included in the
Appendix section and is also available within the Slic source
This example illustrates the following concepts:
- Initializing the Slic Logging Environment,
- Prescribing the Log Message Format,
- Basic logging to the console using the Generic Output Stream, and,
- Using some of the various Slic Macros Used in Axom to log messages.
Step 1: Add Header Includes¶
First, the Slic header must be included to make all the Slic functions and classes accessible to an application:
// Slic includes #include "axom/slic.hpp"
All the classes and functions in Slic are encapsulated within the
Step 2: Initialize Slic¶
Prior to logging any messages, the Slic Logging Environment is initialized by the following:
This creates the root logger instance. However, in order to log messages, an application must first specify an output destination and optionally, prescribe the format of the log messages. These steps are demonstrated in the following sections.
Step 3: Set the Message Format¶
The Log Message Format is specified as a string consisting of keywords,
< ... >, that Slic knows how to interpret when assembling
the log message.
1 2 3
std::string format = std::string("<TIMESTAMP>\n") + std::string("[<LEVEL>]: <MESSAGE> \n") + std::string("FILE=<FILE>\n") + std::string("LINE=<LINE>\n\n");
For example, the
format string in the code snippet above indicates that
the resulting log messages will have the following format:
- A line with the message time stamp
- A line consisting of the Log Message Level, enclosed in
[ ], followed by the user-supplied message,
- A third line with the name of the file where the message was emitted and
- The corresponding line number location within the file, in the fourth line.
See the Log Message Format section for the complete list of keyword options available that may be used to customize the format of the messsages.
This step is optional. If the format is not specified, a Default Message Format will be used to assemble the message.
Step 4: Set Severity Level¶
The severity of log messages to be captured may also be adjusted at runtime to
the desired Log Message Level by calling
This provides another knob that the application can use to filter the type and
level of messages to be captured.
All log messages with the specified severity level or higher are captured. For example, the following code snippet sets the severity level to debug.
This indicates that all log messages that are debug or higher are captured otherwise, the messages are ignored. Since debug is the lowest severity level, all messages will be captured in this case.
Step 5: Register a Log Stream¶
The following code snippet uses the Generic Output Stream object,
one of the Built-In Log Streams provided by Slic, to specify
as the output destination for messages at each Log Message Level.
slic::addStreamToAllMsgLevels(new slic::GenericOutputStream(&std::cout, format));
Instead of calling
slic::addStreamToAllMsgLevels() an application
slic::addStreamToMsgLevel() that allows more fine grain
control of how to bind Log Stream objects to each
Log Message Level. Consult the Slic Doxygen API Documentation
for more information.
The Generic Output Stream, takes two arguments in its constructor:
- A C++
std::ostreamobject that specifies the destination of messages. Consequently, output of messages can be directed to the console, by passing
std::cerr, or to a file by passing a C++
std::ofstreamobject. In this case,
std::coutis specified as the output destination.
- A string corresponding to the Log Message Format, discussed in Step 3: Set the Message Format.
Slic maintains ownership of all registered Log Stream instances and
will deallocate them when
slic::finalize() is called.
Step 5: Log Messages¶
Once the output destination of messages is specified, messages can be logged using the Slic Macros Used in Axom, as demonstrated in the code snippet below.
1 2 3 4
SLIC_DEBUG("Here is a debug message!"); SLIC_INFO("Here is an info mesage!"); SLIC_WARNING("Here is a warning!"); SLIC_ERROR("Here is an error message!");
SLIC_ERROR() will print the specified message and a stacktrace
to the corresponding output destination and call axom::utilities::processAbort() to
gracefully abort the application. This behavior can be toggled by calling
slic::disableAbortOnError(). Additionally, a custom abort function can be
slic::setAbortFunction(). See the Slic Doxygen API Documentation
for more details.
Step 6: Finalize Slic¶
Before the application terminates, the Slic Logging Environment must be finalized, as follows:
slic::finalize() will properly deallocate the registered
Log Stream objects and terminate the Slic Logging Environment.
Step 7: Run the Example¶
The resulting output should look similar to the following:
Fri Apr 26 14:29:53 2019 [DEBUG]: Here is a debug message! FILE=/Users/zagaris2/dev/AXOM/source/axom/src/axom/slic/examples/basic/logging.cpp LINE=44 Fri Apr 26 14:29:53 2019 [INFO]: Here is an info mesage! FILE=/Users/zagaris2/dev/AXOM/source/axom/src/axom/slic/examples/basic/logging.cpp LINE=45 Fri Apr 26 14:29:53 2019 [WARNING]: Here is a warning! FILE=/Users/zagaris2/dev/AXOM/source/axom/src/axom/slic/examples/basic/logging.cpp LINE=46 Fri Apr 26 14:29:53 2019 [ERROR]: Here is an error message! ** StackTrace of 3 frames ** Frame 1: axom::slic::logErrorMessage(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) Frame 2: main Frame 3: start ===== FILE=/Users/zagaris2/dev/AXOM/source/axom/src/axom/slic/examples/basic/logging.cpp LINE=47 Abort trap: 6