Skip to content
Maxime ROUFFET edited this page Mar 29, 2024 · 11 revisions

Helper C++ Macros are provided for user-friendly logging.

See example main.cpp for more examples.

SA_LOG

The SA_LOG macro is used to log anything with an optional level, channel and details:

SA_LOG(_str, _lvl = Normal, _channel = Default, _details = "");

Examples:

SA_LOG("Hello");                                                 // Log with 'Normal' level in 'Default' channel.
SA_LOG(myInt);                                                   // Automatically convert to string using SA::ToString()
SA_LOG("Initialization success", Info);                          // 'Info' level in 'Default' channel.
SA_LOG("Initialization success", Info, MyAPIChannel);            // 'Info' level in 'MyAPIChannel' channel.
SA_LOG(("Hello with params: %1 %2", myInt, myStr), Info);	 // String with parameter formatting.
SA_LOG("Hello", Info, MyChannel, "My details");			 // Additional details.
SA_LOG("Hello", Info, MyChannel, ("My details %1", myInt));      // Use string formatting for details.
[19:2:10][0] {Normal - Default}    main.cpp:53 - int main()
Msg:    Hello

[19:2:10][0] {Normal - Default}    main.cpp:54 - int main()
Msg:    2

[19:2:10][0] {Info - Default}      main.cpp:55 - int main()
Msg:    Initialization success

[19:2:10][0] {Info - MyAPIChannel} main.cpp:56 - int main()
Msg:    Initialization success

[19:2:10][0] {Info - Default}      main.cpp:57 - int main()
Msg:    Hello with params: 2 myString

[19:2:10][0] {Info - MyChannel}    main.cpp:58 - int main()
Msg:    Hello
Dets:   My details

[19:2:10][0] {Info - MyChannel}    main.cpp:59 - int main()
Msg:    Hello
Dets:   My details 2

The _str and _details parameters can use StringFormatting

SA_LOG_RAII

The SA_LOG_RAII macro is used to delay SA_LOG at the end of the current scope { } using the RAII design.
It is used the exact same way as SA_LOG.

{
    SA_LOG_RAII("Log RAII 1", Info, SA.RAIIChan);

    SA_LOG("Normal log", Error);

    {
        SA_LOG_RAII("RAII 2!", Warning, SA.RAIIChan, L"After Normal and Before RAII 1")
    }
}
[15:46:27][0] {Error - Default}    main.cpp:84 - int main()
Msg:    Normal log!

[15:46:27][0] {Warning - SA.RAIIChan}      main.cpp:87 - int main()
Msg:    RAII 2!
Dets:   After Normal and Before RAII 1

[15:46:27][0] {Info - SA.RAIIChan} main.cpp:82 - int main()
Msg:    RAII 1!

SA_WARN

The SA_WARN macro is used to conditionally (on false predicate) log a warning in an optional channel with details.
The predicate as a string is automatically logged:

SA_WARN(_predicate, _channel = Default, _details = "", _postCmd);

Examples:

SA_WARN(myInt == 1);                                          // Log "'myValue == 1' evaluated to false" if myValue != 1
                                                              // with 'Warning' level in 'Default' channel.

SA_WARN(myInt == 1, MyAPIChannel);                            // Optional 'MyAPIChannel' channel.
SA_WARN(myInt == 1, MyAPIChannel, "My details");              // Additional details (formatting possible).
SA_WARN(myInt == 1, MyAPIChannel, ("myInt == %1", myInt));    // Use string formatting for details.
[19:3:9][0] {Warning - Default}    main.cpp:53 - int main()
Msg:    { myInt == 1 }  evaluated to false!

[19:3:9][0] {Warning - MyAPIChannel}       main.cpp:56 - int main()
Msg:    { myInt == 1 }  evaluated to false!

[19:3:9][0] {Warning - MyAPIChannel}       main.cpp:57 - int main()
Msg:    { myInt == 1 }  evaluated to false!
Dets:   My details

[19:3:9][0] {Warning - MyAPIChannel}       main.cpp:58 - int main()
Msg:    { myInt == 1 }  evaluated to false!
Dets:   myInt == 2

The _details parameter can use StringFormatting

An optional post-log command can be added, usually to easily add a return value, and will be used only on false predicate:

SA_WARN(myInt == 1, MyAPIChannel, ("myInt == %1", myInt), return -1);

// Same as

#if SA_DEBUG

if(myInt != -1)
{
    SA_LOG("{ " SA_STR(myInt) " == 1 } evaluated to false!", Warning, MyAPIChannel, ("myInt == %1", myInt));
    return -1;
}

#endif

Any instruction can be used as a post command, such as return, continue, break, or any custom code.

SA_ERROR

The SA_ERROR macro is used to conditionally (on false predicate) log an error in an optional channel with details.
The predicate as a string is automatically logged:

SA_ERROR(_predicate, _channel = Default, _details = "", _postCmd);

Examples:

SA_ERROR(myInt == 1);                                          // Log "'myValue == 1' evaluated to false" if myValue != 1
                                                               // with 'Error' level in 'Default' channel.

SA_ERROR(myInt == 1, MyAPIChannel);                            // Optional 'MyAPIChannel' channel.
SA_ERROR(myInt == 1, MyAPIChannel, "My details");              // Additional details (formatting possible).
SA_ERROR(myInt == 1, MyAPIChannel, ("myInt == %1", myInt));    // Use string formatting for details.
[19:4:38][0] {Error - Default}     main.cpp:53 - int main()
Msg:    { myInt == 1 }  evaluated to false!

[19:4:38][0] {Error - MyAPIChannel}        main.cpp:56 - int main()
Msg:    { myInt == 1 }  evaluated to false!

[19:4:38][0] {Error - MyAPIChannel}        main.cpp:57 - int main()
Msg:    { myInt == 1 }  evaluated to false!
Dets:   My details

[19:4:38][0] {Error - MyAPIChannel}        main.cpp:58 - int main()
Msg:    { myInt == 1 }  evaluated to false!
Dets:   myInt == 2

The _details parameter can use StringFormatting

An optional post-log command can be added, usually to easily add a return value, and will be used only on false predicate:

SA_ERROR(myInt == 1, MyAPIChannel, ("myInt == %1", myInt), return -1);

// Same as

#if SA_DEBUG

if(myInt != -1)
{
    SA_LOG("{ " SA_STR(myInt) " == 1 } evaluated to false!", Error, MyAPIChannel, ("myInt == %1", myInt));
    return -1;
}

#endif

Any instruction can be used as a post command, such as return, continue, break, or any custom code.

SA_ASSERT

the SA_ASSERT macro is used to conditionally (on false exception's predicate) throw an exception in a channel with details. On predicate success (no throw), the exception is simply logged with the level 'AssertionSuccess'. Arguments to build the exception must be provided:

SA_ASSERT((_exceptionType, _params...), _channel = Default, _details = "");

Examples:

int myIndex = 2;
int minBound = 0;
int maxBound = 10;

SA_ASSERT((OutOfRange, myIndex, minBound, maxBound), Default);	// Doesn't throw Exception_OutOfBound: 2 is in the range [0, 10].
SA_ASSERT((OutOfRange, myIndex, 5, maxBound), Default, "My Details!");	// Throw Exception_OutOfBound: 2 is not in the range [5, 10].
[19:7:39][0] {AssertSuccess - Default}     main.cpp:54 - int main()
Msg:    Index 'myIndex' [2] is out of range ['minBound';'maxBound'] => [0;10]

[19:7:39][0] {AssertFailure - Default}     main.cpp:55 - int main()
Msg:    Index 'myIndex' [2] is out of range ['5';'maxBound'] => [5;10]
Dets:   My Details!

terminate called after throwing an instance of 'SA::Exception_OutOfRange'

The _details parameter can use StringFormatting

See Exceptions for the list of provided exception types and how to implement custom exception types.

SA_LOG_END_OF_FRAME

The SA_LOG_END_OF_FRAME macro is used to increment the frame number tracked by the logger, which is then output during logging.
The frame number loops in the range [0;999].

SA_LOG_END_OF_FRAME()

Example:

while(bIsRunning)
{
    SA_LOG("Hello");

    SA_LOG_END_OF_FRAME()
}
[9:38:7][0] {Normal - Default}     main.cpp:59 - int main()
Msg:    Hello

[9:38:7][1] {Normal - Default}     main.cpp:59 - int main()
Msg:    Hello

[9:38:7][2] {Normal - Default}     main.cpp:59 - int main()
Msg:    Hello
...