Kanzi  3.9.7
Kanzi Engine API
log_argument_format.hpp File Reference

Namespaces

 kanzi
 Easing functions that require external dependencies for calculation.
 

Functions

template<typename T >
string kanzi::logArgumentToString (const T &value)
 The logging subsystem uses this function to convert a value to string. More...
 

Detailed Description

Log message formatting

A log message is either a scalar value or a format specification string followed by the format arguments. For example:

// Define a log category named "my category".
#define MY_LOG_CATEGORY KZ_LOG_CREATE_CATEGORY(KZ_LOG_ENABLED_CATEGORY, "my category")
// The log message is an integer constant.
kzLogInfo(MY_LOG_CATEGORY, (100));
// Log integer variable.
int length = 100;
// Output: 100
kzLogInfo(MY_LOG_CATEGORY, (length));
// Log a string literal.
// Output: Single log message.
kzLogInfo(MY_LOG_CATEGORY, ("Single log message."));
// Log a formatted message.
// Format string: "{} plus {} equals {}.".
// Format arguments: 1, 2, 1+2.
// Output: 1 plus 2 equals 3.
kzLogInfo(MY_LOG_CATEGORY, ("{} plus {} equals {}.", 1, 2, 1+2));

The format specification string is a literal text that can contain the format argument references in curly braces:

"Text {...} text {...} ... {...} ..."

When the logger writes the message, it replaces the argument references with a string representation of the values of the referred argument, and keeps the rest of the literal text unchanged. This is the structure of the format argument reference:

{[argument index][:format specification]}

The format argument index and format specification are optional.

Note
Place a colon ahead of the format specification part.
To prevent interpreting an opening brace '{' as the format argument reference, prefix it with two backslashes:
\\{ 
Note that if it is followed by a closing brace '}', it is not removed and remains in the log message output. The sole string literal is not considered a format string and is not parsed for format argument references.

For example:

// Log message consists of format string and one argument.
// Output: {} { some text }
kzLogInfo(MY_LOG_CATEGORY, ("\\{} \\{ {} } { this text is removed ", "some text"));
// Single string literals are not parsed as log message format string.
// Output: This text is string literal. Braces are kept {}, and { this text remains.
kzLogInfo(MY_LOG_CATEGORY, ("This text is string literal. Braces are kept {}, and { this text remains."));

The format argument index is a position of the format argument in the argument list. The first format argument has the index 0, followed by the argument with index 1, and so on. The last format argument has the index N-1, where N is the total number of the format arguments.

The format specification part of the format argument reference describes how to convert the referenced argument to the string when the reference is substituted with the string representation of the argument. See Log message argument format specification section for details.

When the log message is written, the format argument references found in the message format string are replaced with a string representation of the corresponding arguments.

In the simplest case the format arguments are referenced by empty braces '{}':

// Format message arguments are referenced one by one using empty braces.
// Output: 1 2 3.
kzLogInfo(MY_LOG_CATEGORY, ("{} {} {}.", 1, 2, 3));
// Output: 1 plus 2 equals 3.
kzLogInfo(MY_LOG_CATEGORY, ("{} plus {} equals {}.", 1, 2, 1+2));

You can also reference the format arguments using the argument index explicitly:

// Log values in custom order.
// Output: 3 1 2 3 5.
kzLogInfo(MY_LOG_CATEGORY, ("{2} {0} {1} {2} {4}.", 1, 2, 3, 4, 5));
// Log values in custom order using implicit argument indexing.
// Note: The argument reference '{1}' followed by '{}'.
// Output: argument #4 = 5, argument #0 = 1, argument #2 = 3, argument #3 = 4, argument #4 = 5.
kzLogInfo(MY_LOG_CATEGORY, ("argument #4 = {4}, argument #0 = {0}, argument #2 = {2}, argument #3 = {}, argument #4 = {}.", 1, 2, 3, 4, 5));

In the last example you can see that the indexed argument reference '{2}' is followed by argument reference without index '{}'. In such a case the argument referenced without index is the one (#3 in this case) following the argument referenced with index (#2 in this case).

Log message argument format specification

The log message format argument reference consists of argument index and format specification. The format specification describes how the log message format argument value is converted to a string and how it is positioned when the message is written to the log. The logging system takes the format argument value type into account when converting the value to the textual representation, making logging typesafe.

The format specification has this structure:

[align][sign][#][0][width][.precision][specifier]

The align format argument sets the positioning of the resulting text. This table lists the available values for align.

Align value Output
< Text aligned to the left within the available space.
> Text aligned to the right within the available space. This is the default setting.

The sign is valid for numeric types only. This table lists the available values for sign.

Sign value Output
+ The sign of the number for both positive and negative numbers.
- The sign of the number for negative numbers. This is the default setting.
space Leading space for positive numbers, and a minus sign for negative numbers.

The # format argument is valid for octal or hexadecimal specifier of integer types. If present, the output is prefixed by '0' for the o specifier or by '0x'/'0X' for the x/X specifier.

The 0 format argument pads the number with zeroes to the left instead of spaces when the value converted to string consumes less characters than width.

The width format argument is an integer number describing the minimum width of the output text. If the text does not consume the whole width, the remaining space is padded with spaces or, if the 0 format argument is specified, with zeros.

The precision format argument is only valid for floating point types and describes how many digits to display after decimal point.

The precision format argument denotes the notation to use when converting the format argument value to a string. The available specifier values depend on the format argument type. This table lists the available values for specifier.

Argument type Specifier Output
Character c Single character. This is the default for signed characters.
d The number in base 10.
u Unsigned number in base 10. This is the default for unsigned characters.
o The number in base 8.
x The number in base 16 using lowercase letters a - f.
X The number in base 16 using uppercase letters A - F.
Integer d The number in base 10. This is the default for signed integers.
u Unsigned number in base 10. This is the default for unsigned integers.
o The number in base 8.
x The number in base 16 using lower case letters a - f.
X The number in base 16 using upper case letters A - F.
Floating point e The number in scientific notation. The letter 'e' denotes the exponent part.
E The number in scientific notation. The letter 'E' denotes the exponent part.
f The number in decimal floating point notation, lowercase. This is the default for floating point numbers.
F The number in decimal floating point notation, upper case.
g The number in the shortest possible representation : 'e' or 'f'.
G The number in the shortest possible representation : 'E' or 'F'.
a The number in hexadecimal floating point notation, lower case.
A The number in hexadecimal floating point notation, upper case.
x The same as 'a'.
X The same as 'A'.
Pointer p The pointer address. This is the default for pointers.
Note
If the argument type does not match the specifier field, the default specifier for the argument type is used to convert the argument value to a string.

If the type of the format argument is a pointer, the Logging subsystem writes to the log the address stored in the pointer. If the type of the format argument is array (T[]), the Logging subsystem writes to the log the address of the first element of that array. Only string literals of type const char[] or char[] are written to the log as text.

To write to the log the string pointed to by the const char* or char* pointer, you can use the string_view object. You can initialize the string_view object with the pointer to the string that you want to log and then use that object as a log format argument. If you pass a pointer to the string as a format argument, only the address of that string is written to the log.

You can use objects of user-defined type as log format arguments. The Logging subsystem uses the kanzi::logArgumentToString template function to convert objects of user-defined type to string. Only the align format argument is applicable for user-defined types. The Logging subsystem specializes kanzi::logArgumentToString for several user-defined types. See Default logArgumentToString specializations.

Examples

To log a message using various argument specifiers:

// Log the value of 10 in different base systems.
// Output: decimal: 10, octal: 012, hexadecimal: 0xa.
kzLogInfo(MY_LOG_CATEGORY, ("decimal: {}, octal: {:#o}, hexadecimal: {:#x}.", 10, 10, 10));
// Using argument index could be shortened to:
// added in resulting text to octal or hexadecimal presentation.
// Output: decimal: 10, octal: 012, hexadecimal: 0xa.
kzLogInfo(MY_LOG_CATEGORY, ("decimal: {}, octal: {0:#o}, hexadecimal: {0:#x}.", 10));
// Field width is 4 characters.
// Output: decimal: 10.
kzLogInfo(MY_LOG_CATEGORY, ("decimal:{:4}.", 10));
// Field width is 4 characters, left aligned.
// Output: decimal:10 .
kzLogInfo(MY_LOG_CATEGORY, ("decimal:{:<4}.", 10));
// Field width is 4 characters, zero filled.
// Output: decimal:0010.
kzLogInfo(MY_LOG_CATEGORY, ("decimal:{:04}.", 10));
// Field width is 4 characters, with sign and left aligned.
// Output: decimal:+10 .
kzLogInfo(MY_LOG_CATEGORY, ("decimal:{:<+4}.", 10));

To use string format arguments:

const char* message = "Hello world!!!";
// Write message to the log:
// Output: Message: Hello World!!!
kzLogInfo(MY_LOG_CATEGORY, ("Message: {}", string_view(message)));
// Write string literal to the log:
// Output: Message: String literal message.
kzLogInfo(MY_LOG_CATEGORY, ("Message: {}", "String literal message."));