# Diagnostics

#### <a class="anchor" id="bkmrk-"></a>Description

This tutorial describes several aspects of diagnostic support during development and post-development phases.

#### **Assertions** 

For using assertions include *FeatStd/Diagnostics/Debug.h* in your program.

##### <a class="anchor" id="bkmrk--1"></a>Compile Time Checks

Best time to catch an error is at compile time before the program starts. If the assertion is a constant expression, then the compiler is able to check it.

Use

<div class="contents" id="bkmrk-featstd_compiletime_"><div class="contents"><div class="textblock">- [FEATSTD\_COMPILETIME\_ASSERT(assertion)](http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#gaeee202e9a6abec1fa3a162c6a1324500)

</div></div></div>##### <a class="anchor" id="bkmrk--2"></a>Runtime Checks

These kinds of assertions should be used to document logically impossible situations and discover programming errors.

Use

<div class="contents" id="bkmrk-featstd_debug_assert"><div class="contents"><div class="textblock">- FEATSTD\_DEBUG\_ASSERT(condition)
- FEATSTD\_DEBUG\_FAIL()
- FEATSTD\_DEBUG\_REENTRANCE\_GUARD()
- FEATSTD\_DEBUG\_BREAK()

</div></div></div>FEATSTD\_DEBUG\_ASSERT() and FEATSTD\_DEBUG\_FAIL() allow the user to check **pre-conditions** and also **post-conditions** as well as **invariants**, sometimes known as "embedded testing".

```
bool CgiApp::LoadAsset(const Char* filePath)
{
    FEATSTD_DEBUG_ASSERT(filePath != 0);

    ClearLoadedAsset();
    m_assetConfig.AddFileRepository(filePath);
```

```
                if ((*tempName >= '0') && (*tempName <= '9')) {
                    hash += (<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___u_t_i_l_s.html#gae299c392c2a207dfa2036cb528451eb7">ToUInt32</a>(*tempName) - static_cast<UInt32>('0'));
                }
                else if ((*tempName >= 'A') && (*tempName <= 'F')) {
                    hash += (<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___u_t_i_l_s.html#gae299c392c2a207dfa2036cb528451eb7">ToUInt32</a>(*tempName) - (static_cast<UInt32>('A') - 10U));
                }
                else if ((*tempName >= 'a') && (*tempName <= 'f')) {
                    hash += (<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___u_t_i_l_s.html#gae299c392c2a207dfa2036cb528451eb7">ToUInt32</a>(*tempName) - (static_cast<UInt32>('a') - 10U));
                }
                else {
                    // failure
                    FEATSTD_DEBUG_FAIL();
                }
```

FEATSTD\_DEBUG\_REENTRANCE\_GUARD() allows to check that a part of code isn't entered twice:

```
void Appender::Append(const LogEvent& logEvent)
{
    FEATSTD_DEBUG_REENTRANCE_GUARD();
```

  
Be aware that all FEATSTD\_**DEBUG**\_... macros are expanded in Debug-Versions only. This avoids codesize and performance penalty in Release-Versions.

For a distinction between ErrorHandling and Assertions please see [http://en.wikipedia.org/wiki/Assertion\_(computing)](http://en.wikipedia.org/wiki/Assertion_(computing))

##### <a class="anchor" id="bkmrk--3"></a>Customizing

The behavior can be adapted by implementing

<div class="contents" id="bkmrk-either-a-platform-sp"><div class="contents"><div class="textblock">- either a platform specific FeatStd::Platform::Diagnostic class
- or a **DebugControlHook** class derived from FeatStd::Diagnostics::IDebugControlHook, activated via FeatStd::Diagnostics::DebugControl::SetHook.

</div></div></div>  
See UnitTests\\Diagnostics\\DebugControlTest.cpp and the FeatStd::UnitTestHelper::DebugOutputChecker implementation for details.

#### **Logging** 

##### <a class="anchor" id="bkmrk--4"></a>Description

Logging is an important feature while programming (debugging), but also during the post-development phase to detect the reasons for system and software crashes.

In contrast to classical "printf" debugging, the FeatStd implementation is "two-dimensionally" configurable.

<div class="contents" id="bkmrk-first%2C-the-framework"><div class="contents"><div class="textblock">- First, the framework is structured in various **realms**.
- Second, for every realm the **level of detail** (FeatStd::Diagnostics::LogLevel::Enum, Candera::Diagnostics::LogLevel::Enum) can be chosen separately.

</div></div></div>Free configurable **appenders** decide which channel(s) should be used to output the log messages.   
See [FeatStd::Diagnostics::Appender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_appender.html) (and subclasses) for details.

#####   
**Configure Log Output** 

##### <a class="anchor" id="bkmrk--6"></a>Default Log Output

By default, [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") produces logging output with LogLevel "Warning" for all realms on the console. This chapter explains how to adapt those default logging configuration in an application.

To configure logging support include *Log.h* in your program.

##### <a class="anchor" id="bkmrk--7"></a>Set LogRealm and LogLevel

To modify LogLevel for one, more, or even all realms, use

<div class="contents" id="bkmrk-featstd%3A%3Adiagnostics"><div class="contents"><div class="textblock">- [FeatStd::Diagnostics::LogControl::SetLogLevel&lt;LogRealm&gt;()](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_log_control.html#aad6be2658a44e5710d395b3a0d4b1649).
- The convenience function [FeatStd::Diagnostics::LogControl::SetLogLevel()](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_log_control.html#aad6be2658a44e5710d395b3a0d4b1649) sets the requested level for all realms.

</div></div></div>For a list of all LogRealms supported by FeatStd, refer to *FeatStd/Diagnostics/LogRealm.h*:

```
FEATSTD_LOG_DECLARE_REALM(FeatStdSystem);
FEATSTD_LOG_DECLARE_REALM(FeatStdPlatform);
FEATSTD_LOG_DECLARE_REALM(FeatStdIO);
FEATSTD_LOG_DECLARE_REALM(FeatStdMemoryManagement);
FEATSTD_LOG_DECLARE_REALM(FeatStdMonitor);
FEATSTD_LOG_DECLARE_REALM(FeatStdAsync);
```

Use the macro FEATSTD\_LOG\_SET\_REALM to activate a realm (see also chapter <span style="color: rgb(230, 126, 35);">[Custom Log Output](#bkmrk-custom-log-output%C2%A0)</span>), e.g. FeatStd class FileAppender will produce logging output under the realm "FeatStdSystem", because of the following declaration:

```
class FileAppender : public Appender
{
    typedef Appender Base;

    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ga1c81a9c5191e30fa4d7119772b6edb47">FEATSTD_LOG_SET_REALM</a>(Diagnostics::LogRealm::FeatStdSystem);
```

For each realm different log levels can be set, see log levels defined in FeatStd/Diagnostics/Loglevel.h.

```
enum Enum
{
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0ab1ef5245ddb4e605054fc70baa0d1f96" title="All.">All</a> = 0,        
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0af5dfc3720ca935220d7c86cf1bb2aa27" title="Debug.">Debug</a> = <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0ab1ef5245ddb4e605054fc70baa0d1f96" title="All.">All</a>,    
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0a4022bc360aafc7b5692c92639c5d975b" title="Info.">Info</a> = 1,       
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0a87cb3271087cc2730a2062f0e5c990e6" title="Warning = Default.">Warning</a> = 2,    
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0a0fd982e4d51e3751a94e4fd79188c009" title="Error.">Error</a> = 3,      
    <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0ad18182830c1767d5dd8a8ad2f72af949" title="Fatal.">Fatal</a> = 4,      
    Off = 5         
};
```

Use [FeatStd::Diagnostics::LogControl::SetLogLevel&lt;LogRealm&gt;()](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_log_control.html#aad6be2658a44e5710d395b3a0d4b1649) to set the desired log level.

```
    LogControl::SetAppender(&CgiAppLogAppender::GetCgiAppLogAppenderInstance());
    LogControl::SetLogLevel<CgiAppLog>(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0ab1ef5245ddb4e605054fc70baa0d1f96" title="All.">LogLevel::All</a>);
```

<div class="contents" id="bkmrk-the-default-log-leve"><div class="contents"><div class="textblock"><div class="fragment">  
</div><dl class="note"><dd><p class="callout info">The default log level is *Warning*.</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--8"></a>Output Channel - Log Appenders

Logging output is handled by instances of [FeatStd::Diagnostics::Appender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_appender.html) - for this purpose, all [FeatStd::Diagnostics::Logger](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_logger.html) instances share a list of appenders.

FeatStd provides following appenders:

<div class="contents" id="bkmrk-featstd%3A%3Adiagnostics-0"><div class="contents"><div class="textblock">- [FeatStd::Diagnostics::ConsoleAppender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_console_appender.html)
- [FeatStd::Diagnostics::FileAppender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_file_appender.html "[FEATSTD_LOG_SET_REALM_H]")
- [FeatStd::UnitTestHelper::MemorizeAppender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_unit_test_helper_1_1_memorize_appender.html)

</div></div></div>By default, a ConsoleAppender is configured, means once an application doesn't configure anything regarding Logging, log messages from [Candera](http://dev.doc.cgistudio.at/APILINK/namespace_candera.html "[DataBinding_RefTypeSample]") will be sent to the console.

The list of appenders can be modified by [FeatStd::Diagnostics::LogControl::SetAppender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_log_control.html#a517c5f22e2a3c97d45f15193eb4f5262), AppendAppender and RemoveAppender.

##### <a class="anchor" id="bkmrk--9"></a>Implement a Custom Appender

A custom appender class has to be derived from [FeatStd::Diagnostics::Appender](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_appender.html) and implement the abstract method [FeatStd::Diagnostics::Appender.DoAppend()](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_appender.html#a46e866a6eff038a3a691ec2ee6c4326e).

A custom **CgiAppLogAppender** has been created for modifying the LogLevel::Info output.

```
void CgiAppLogAppender::DoAppend(const LogEvent& logEvent)
{
    // Info traces will be outputted as is, for all others keep ConsoleAppender implementation
    if (logEvent.mLogLevel <= <a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0a4022bc360aafc7b5692c92639c5d975b" title="Info.">LogLevel::Info</a>) {
        FeatStd::Internal::Diagnostic::ConsoleOut("%s\n", logEvent.mMessage);
        FeatStd::Internal::Diagnostic::DebuggerOut("%s\n", logEvent.mMessage);
    } else {
        <a class="code" href="http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_console_appender.html#a5e13c2d5b02c6e57c228efc31b6fa7a3">FeatStd::Diagnostics::ConsoleAppender::DoAppend</a>(logEvent);
    }
}
```

This custom appender is set to LogControl and activated for all log levels.

```
    LogControl::SetAppender(&CgiAppLogAppender::GetCgiAppLogAppenderInstance());
    LogControl::SetLogLevel<CgiAppLog>(<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ggad2cbc908487f2a3b4340020c0f69bda0ab1ef5245ddb4e605054fc70baa0d1f96" title="All.">LogLevel::All</a>);
```

##### **Custom Log Output** 

##### <a class="anchor" id="bkmrk--10"></a>Player Logging Support

This chapter explains how to create logging output from a custom application.

Include *Log.h* in your program.

##### <a class="anchor" id="bkmrk--11"></a>Default Application Realm

FeatStd predefines a default application realm:

```
FEATSTD_LOG_DECLARE_REALM(User);
```

To activate this realm for an application, use the macro [FEATSTD\_LOG\_SET\_REALM()](http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ga1c81a9c5191e30fa4d7119772b6edb47) with the default application realm as parameter:

```
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ga1c81a9c5191e30fa4d7119772b6edb47">FEATSTD_LOG_SET_REALM</a>(LogRealm::User);
```

##### <a class="anchor" id="bkmrk--12"></a>Produce Logging Output

Output itself is done by calling level specific **FEATSTD\_LOG\_&lt;level&gt;** macros in your code:

<div class="contents" id="bkmrk-featstd_log_debug%28.."><div class="contents"><div class="textblock">- FEATSTD\_LOG\_DEBUG(...)
- FEATSTD\_LOG\_INFO(...)
- FEATSTD\_LOG\_WARN(...)
- FEATSTD\_LOG\_ERROR(...)
- FEATSTD\_LOG\_FATAL(...)

</div></div></div>FEATSTD\_LOG\_&lt;level&gt; macros provide a **printf-like** interface, which means that a format string has to be given as first argument, followed by a variable number of arguments (referenced in the format string).

  
**FEATSTD\_LOG\_INFO()** example when loading a Scene.

```
bool CgiApp::LoadScene(const Char* sceneName) {
    FEATSTD_LOG_INFO(" -> Loading scene '%s'", sceneName);
```

**FEATSTD\_LOG\_ERROR()** example when loading a asset configuration fails.

```
    bool result =  LoadAssetConfig();
    if (!result) {
        FEATSTD_LOG_ERROR("\n%s\n", m_loadError);
        m_assetConfig.ClearRepositoryList();
    }
```

<div class="contents" id="bkmrk-the-length-of-the-as"><div class="contents"><div class="textblock"><div class="fragment">  
</div><dl class="note"><dt></dt><dd><p class="callout info">The length of the assembled information **must be** less than 511 characters!</p>

</dd></dl></div></div></div>##### <a class="anchor" id="bkmrk--13"></a>Define Custom Realms

For simple applications the usage of the predefined realm **LogRealm::User** may suffice but more sophisticated applications possibly want to structure the output by further realms.

To do so, first define a [LogRealm](http://dev.doc.cgistudio.at/APILINK/namespace_log_realm.html "[COURIER_LogRealm_Declare]") class by using the FEATSTD\_LOG\_DECLARE\_REALM(name\_of\_the\_realm) macro.

```
#include <FeatStd/FeatStd.h>

namespace CgiApplication {

FEATSTD_LOG_DECLARE_REALM(CgiAppLog);
FEATSTD_LOG_DECLARE_REALM(TutorialWidgets);
```

See LightPlayer/CgiAppLogRealm.\[h|cpp\] for details.

<div class="contents" id="bkmrk-the-new-realm-doesn%27"><div class="contents"><div class="textblock"><dl class="note"><dt></dt><dd><p class="callout info">The new realm doesn't take part in any iteration functionality (e.g. [FeatStd::Diagnostics::LogControl::SetLogLevel()](http://dev.doc.cgistudio.at/APILINK/namespace_feat_std_1_1_diagnostics_1_1_log_control.html#aad6be2658a44e5710d395b3a0d4b1649)) until the realm (Logger) is used a first time (instantiated).</p>

</dd></dl></div></div></div>So it is good practice to implement an initialization function (using FEATSTD\_LOG\_DEFINE\_REALM(name\_of\_the\_realm))

```
void CgiApp_LoggerInitialization()
{
    FEATSTD_LOG_DEFINE_REALM(CgiAppLog);
    FEATSTD_LOG_DEFINE_REALM(TutorialWidgets);
}
```

and to call it at an early point in program execution.

Finally, the new custom realms must be set for the application, which shall log on that realm:

```
<a class="code" href="http://dev.doc.cgistudio.at/APILINK/group___f_e_a_t_s_t_d___d_i_a_g_n_o_s_t_i_c_s.html#ga1c81a9c5191e30fa4d7119772b6edb47">FEATSTD_LOG_SET_REALM</a>(CgiAppLog);
```

Use an appropriate **FEATSTD\_LOG\_&lt;level&gt;** macro to output the message.