ImFusion SDK 4.3

Lightweight logging framework of the ImFusion SDK. More...

+ Collaboration diagram for Logging:

Detailed Description

Lightweight logging framework of the ImFusion SDK.

The ImFusion::Log namespace provides the lightweight logging framework used by the ImFusion SDK. Its customization points allow for writing custom loggers sinks (some frameworks refer to them as appenders) and for easy integration with other third-party logging frameworks.

Using ImFusionLog

First you need to initialize the logging framework. You can choose between the synchronous and asynchronous operation mode. In synchronous mode, all log events are directly forwarded to all registered sinks and a call to Log::log() does not return before all sinks have finished logging the event. In asynchronous mode, all log events are temporarily stored by the worker and forwarded to the sinks on a separate thread. A call to log() will return immediately, however the log events are not necessarily processed by all sinks at this point.

// initialize logging
// add two logger sinks, one to the console and one to a log file
@ UseColor
Use colored console output.
Definition ConsoleSink.h:24
@ Truncate
Clear the log file.
Definition FileSink.h:28
void addSink(std::unique_ptr< Sink > sink)
Registers the given sink so that it will receive future log events.
void init(Level globalMinimumLevel, Mode operationMode)
Initialize the logging framework.
@ Trace
Particularly verbose debugging messages for internal debugging.
Definition Log.h:25
T make_unique(T... args)
@ Synchronous
All log events are synchronously forwarded to all registered loggers.
Definition Log.h:38

Furthermore, you will need to register a set of Sinks that will receive the individual log events/captures. Each sink will then decide how a log capture is handled and can for instance forward it to the attached console window or append it to a log file.

Log messages are emitted using one of the available LOG_XYZ macros. You can use the stream operator << to put in any type that has a known conversion to a std::ostream.

// Plain Logging without a category
LOG_TRACE("Message number #" << i);
LOG_DEBUG("Message number #" << i);
LOG_INFO("Message number #" << i);
LOG_WARN("Message number #" << i);
LOG_ERROR("Message number #" << i);
LOG_FATAL("Message number #" << i);
#define LOG_INFO(...)
Emits a log message of Log::Level::Info, optionally with a category.
Definition Log.h:247
#define LOG_TRACE(...)
Emits a log message of Log::Level::Trace, optionally with a category.
Definition Log.h:237
#define LOG_DEBUG(...)
Emits a log message of Log::Level::Debug, optionally with a category.
Definition Log.h:242
#define LOG_FATAL(...)
Emits a log message of Log::Level::Fatal, optionally with a category.
Definition Log.h:262
#define LOG_ERROR(...)
Emits a log message of Log::Level::Error, optionally with a category.
Definition Log.h:257
#define LOG_WARN(...)
Emits a log message of Log::Level::Warning, optionally with a category.
Definition Log.h:252

You can add an optional message category as first argument to the log macro. This allows for enhanced filtering of messages by the sinks (see Log Filtering).

// Plain Logging without a category
LOG_TRACE("Message.Category", "Message number #" << i);
LOG_DEBUG("Message.Category", "Message number #" << i);
LOG_INFO("Message.Category", "Message number #" << i);
LOG_WARN("Message.Category", "Message number #" << i);
LOG_ERROR("Message.Category", "Message number #" << i);
LOG_FATAL("Message.Category", "Message number #" << i);

Specifying a Default Log Category per File

You can redefine the IMFUSION_LOG_DEFAULT_CATEGORY define in a cpp file in order to set a default log message category for subsequent calls to the single-argument LOG_XYZ macros.

#include <ImFusion/Core/Log.h>
[...]
// preferably at the top of the cpp file but after the includes
#undef IMFUSION_LOG_DEFAULT_CATEGORY
#define IMFUSION_LOG_DEFAULT_CATEGORY "My.Message.Category"
[...]
// anywhere below in the code
LOG_INFO("My log message"); // message will have "My.Message.Category" as category
Warning
Be aware of the implications of redefining a preprocessor define: it will affect all subsequent code. Therefore, we strongly advise you to do this only in cpp files and never in header files.

Log Filtering

Log events can be filtered on two levels:

Logging the Message Origin

Log messages can optionally contain information about the source location (filename + line number) from where it was originally emitted. You must set the IMFUSION_LOG_CAPTURE_ORIGIN preprocessor define to enable this feature.

A FileSink will always write the origin's source location if available. A ConsoleSink only if you opt-in via the ConsoleSink::PrintSourceInfo configuration option.

Extending ImFusionLog

You can implement custom sinks by inheriting from the Log::Sink interface. This enables you to write custom log receivers, for instance in order to forward ImFusion log messages to another log framework that you use. You need to implement at least the two pure virtual functions of the interface

Namespaces

namespace  ImFusion::Log
 Logging framework.
 

Classes

class  ConsoleSink
 Default implementation for a Logger that prints to the attached console/terminal. More...
 
class  FileSink
 Default implementation for a Logger that writes to the filesystem. More...
 
class  Sink
 Interface for a logger sink that can receive individual log events. More...
 

Macros

#define LOG_TRACE(...)
 Emits a log message of Log::Level::Trace, optionally with a category.
 
#define LOG_DEBUG(...)
 Emits a log message of Log::Level::Debug, optionally with a category.
 
#define LOG_INFO(...)
 Emits a log message of Log::Level::Info, optionally with a category.
 
#define LOG_WARN(...)
 Emits a log message of Log::Level::Warning, optionally with a category.
 
#define LOG_ERROR(...)
 Emits a log message of Log::Level::Error, optionally with a category.
 
#define LOG_FATAL(...)
 Emits a log message of Log::Level::Fatal, optionally with a category.
 
#define LOG_FORMAT_MONO   "\033[0;11m"
 Enables monospace formatting when prepended to a log message, usage example: LOG_INFO(LOG_FORMAT_MONO << "message");
 

Enumerations

enum class  Level {
  Trace = 0 , Debug = 1 , Info = 2 , Warning = 3 ,
  Error = 4 , Fatal = 5 , Quiet = 6
}
 Severity of the log event. More...
 

Functions

void init (Level globalMinimumLevel, Mode operationMode)
 Initialize the logging framework.
 
void deinit ()
 Deinitialize the logging framework.
 
bool isInitialized ()
 Return whether the logging framework has been initialized.
 
bool isAccepted (Level level, const char *category) noexcept
 Checks whether a log message is accepted by at least one of the registered sinks.
 
Level globalLevel ()
 Return the global minimum log level/severity that is going to be handled.
 
Level setGlobalLevel (Level maximumLevel)
 Set the global minimum log level/severity that is going to be handled.
 
void log (Level level, const char *category, const std::string &message, const char *fileName="", int line=-1)
 Logs the given message on all registered loggers.
 
void flush ()
 Ensures that all log messages have been fully written, also in async mode.
 
void addSink (std::unique_ptr< Sink > sink)
 Registers the given sink so that it will receive future log events.
 
std::unique_ptr< SinkremoveSink (Sink *sink)
 Removes a previously added sink so that it will no longer receive log events.
 
std::vector< Sink * > getSinks ()
 Returns a list of all registered logger sinks.
 

Macro Definition Documentation

◆ LOG_TRACE

#define LOG_TRACE ( ...)

#include <ImFusion/Core/Log.h>

Value:
LOG_EXPAND(LOG_GET_MACRO(__VA_ARGS__, LOG_TRACE_NAMED, LOG_TRACE_ROOT)(__VA_ARGS__))

Emits a log message of Log::Level::Trace, optionally with a category.

◆ LOG_DEBUG

#define LOG_DEBUG ( ...)

#include <ImFusion/Core/Log.h>

Value:
LOG_EXPAND(LOG_GET_MACRO(__VA_ARGS__, LOG_DEBUG_NAMED, LOG_DEBUG_ROOT)(__VA_ARGS__))

Emits a log message of Log::Level::Debug, optionally with a category.

◆ LOG_INFO

#define LOG_INFO ( ...)

#include <ImFusion/Core/Log.h>

Value:
LOG_EXPAND(LOG_GET_MACRO(__VA_ARGS__, LOG_INFO_NAMED, LOG_INFO_ROOT)(__VA_ARGS__))

Emits a log message of Log::Level::Info, optionally with a category.

Examples
DicomWorklist.cpp, ExampleMeshAlgorithm.cpp, ExamplePointCloudAlgorithm.cpp, and Filesystem.cpp.

◆ LOG_WARN

#define LOG_WARN ( ...)

#include <ImFusion/Core/Log.h>

Value:
LOG_EXPAND(LOG_GET_MACRO(__VA_ARGS__, LOG_WARN_NAMED, LOG_WARN_ROOT)(__VA_ARGS__))

Emits a log message of Log::Level::Warning, optionally with a category.

◆ LOG_ERROR

#define LOG_ERROR ( ...)

#include <ImFusion/Core/Log.h>

Value:
LOG_EXPAND(LOG_GET_MACRO(__VA_ARGS__, LOG_ERROR_NAMED, LOG_ERROR_ROOT)(__VA_ARGS__))

Emits a log message of Log::Level::Error, optionally with a category.

◆ LOG_FATAL

#define LOG_FATAL ( ...)

#include <ImFusion/Core/Log.h>

Value:
LOG_EXPAND(LOG_GET_MACRO(__VA_ARGS__, LOG_FATAL_NAMED, LOG_FATAL_ROOT)(__VA_ARGS__))

Emits a log message of Log::Level::Fatal, optionally with a category.

Enumeration Type Documentation

◆ Level

enum class Level
strong

#include <ImFusion/Core/Log.h>

Severity of the log event.

Enumerator
Trace 

Particularly verbose debugging messages for internal debugging.

Debug 

Info messages targeting developers and not end-users.

Info 

Info messages targeting end-users and not developers.

Warning 

Error messages where the emitting code can continue but the result might be unexpected/bad.

Error 

Error messages where the emitting code is aborted.

Fatal 

Serious error messages where the entire program execution should be aborted (cf. Log::log()).

Quiet 

Not an actual logging severity but can be passed to setGlobalLevel() or to Sink filters to disable all logging.

Function Documentation

◆ init()

void init ( Level globalMinimumLevel,
Mode operationMode )

#include <ImFusion/Core/Log.h>

Initialize the logging framework.

Parameters
globalMinimumLevelMinimum log level/severity that is going to be handled. All events with a lower level will be discarded right away.
operationModeOperation mode of the log worker (synchronous/asynchronous).
Examples
PacsExample.cpp.

◆ isAccepted()

bool isAccepted ( Level level,
const char * category )
noexcept

#include <ImFusion/Core/Log.h>

Checks whether a log message is accepted by at least one of the registered sinks.

See also
Sink::isAccepted()

◆ globalLevel()

Level globalLevel ( )
inline

#include <ImFusion/Core/Log.h>

Return the global minimum log level/severity that is going to be handled.

All log events that have a lower level are going to be discarded right away before reaching any registered Logger.

◆ setGlobalLevel()

Level setGlobalLevel ( Level maximumLevel)

#include <ImFusion/Core/Log.h>

Set the global minimum log level/severity that is going to be handled.

All log events that have a lower level are going to be discarded right away before reaching any registered Logger. Returns the previously configured global level for convenience.

◆ log()

void log ( Level level,
const char * category,
const std::string & message,
const char * fileName = "",
int line = -1 )

#include <ImFusion/Core/Log.h>

Logs the given message on all registered loggers.

Parameters
levelSeverity of the log event
categoryCategory of the log event
messageLog message
fileNameOptional file name where the log message originates from
lineOptional line number where the log message originates from
Note
If level equals Level::Fatal the method will terminate the application by calling std::exit(-106);

◆ addSink()

void addSink ( std::unique_ptr< Sink > sink)

#include <ImFusion/Core/Log.h>

Registers the given sink so that it will receive future log events.

Parameters
sinkSink instance that shall be added.

◆ removeSink()

std::unique_ptr< Sink > removeSink ( Sink * sink)

#include <ImFusion/Core/Log.h>

Removes a previously added sink so that it will no longer receive log events.

The removed Sink instance is returned as std::unique_ptr so that you can get back ownership if needed.

Parameters
sinkSink instance that shall be removed.
Search Tab / S to search, Esc to close