Use the Kanzi logging system to print messages to the Log window, the Kanzi debug console, standard output, and the system log on your target device. For example, use logging to find problems in your Kanzi application, and to inform the user about the status of your application.
You can:
Use the Kanzi logging macros to print messages to the log. Most of the logging macros use a fixed log level to indicate the severity of the information in the message. See Setting the log level.
Do not use application critical code in the logging macro calls. If you place application critical code as an argument to the logging macro call, and during compilation you disable the log level or the log category assigned to the message in the call, the preprocessor removes the logging macro call together with the application critical code.
Kanzi has these logging macros:
Logging macro | Description |
---|---|
kzLogError
|
Log error messages using the Default Logger (DefaultLogger ), the error (KZ_LOG_LEVEL_ERROR ) log level, and the log category that you provide as an input parameter. |
kzLogWarning
|
Log warning messages using the Default Logger (DefaultLogger ), the warning (KZ_LOG_LEVEL_WARNING ) log level, and the log category that you provide as an input parameter. |
kzLogInfo
|
Log info messages using the Default Logger (DefaultLogger ), the info (KZ_LOG_LEVEL_INFO ) log level, and the log category that you provide as an input parameter. |
kzLogTrace
|
Log trace messages using the Default Logger (DefaultLogger ), the trace (KZ_LOG_LEVEL_TRACE ) log level, and the log category that you provide as an input parameter. |
kzLogDebug
|
Log debug messages using the Default Logger (DefaultLogger ), the info (KZ_LOG_LEVEL_INFO ) log level, and the log category KZ_LOG_CATEGORY_DEBUG . |
kzLog
|
Log messages using a custom logger, and the log level and category that you provide as input parameters. See Creating a custom logger. |
To print log messages:
// Print "This is a debug message.". kzLogDebug(("This is a debug message."));Prints to the log:
info:debug> This is a debug message.
// Print "This is an error message." using the log category MY_LOG_CATEGORY. // Use log categories to group your log messages based on the functionality to which they are related. See Using log categories. kzLogError(MY_LOG_CATEGORY, ("This is an error message."));Prints to the log the path to the file, the line number where the error originated, and the error message:
error:My category:c:\kanziworkspace\projects\myproject\application\src\myproject.cpp:196> This is an error message.
// Print "1 plus 2 equals 3." using the log category MY_LOG_CATEGORY. See Using log categories. kzLogInfo(MY_LOG_CATEGORY, ("{} plus {} equals {}.", 1, 2, 1+2)); int length = 100; // Print "The length is 100.". kzLogInfo(MY_LOG_CATEGORY, ("The length is {}.", length));Prints to the log:
info:My category> 1 plus 2 equals 3. info:My category> The length is 100.
Use log levels to show log messages based on their severity. For example, to log critical issues during application execution, use the error
log level (KZ_LOG_LEVEL_ERROR
).
The Kanzi logging system has these log levels:
Log level | Name | Severity | Description |
---|---|---|---|
KZ_LOG_LEVEL_ERROR
|
error
|
1 | Logs critical malfunction messages. Create detailed error messages so that you can receive enough information about an issue. |
KZ_LOG_LEVEL_WARNING
|
warning
|
2 | Logs facts that require attention, which are not necessarily malfunctions. For example, use a warning message to notify the user about an outcome from which the application can recover, such as a missing parameter that has a default value, or an event that can lead to performance degradation, but is not a failure. |
KZ_LOG_LEVEL_INFO
|
info
|
3 | Logs information that gives a brief overview of what is happening in the system, log states passed, static information about configuration, and so on. |
KZ_LOG_LEVEL_TRACE
|
trace
|
4 | Logs the maximum amount of information about the system. This is the most verbose log level. Use this level to troubleshoot issues. |
These log levels are enabled by default:
To set the log level, use the KZ_LOG_LEVEL_ENABLED_THRESHOLD
macro.
For example, to set a log level that enables all log levels:
#define KZ_LOG_LEVEL_ENABLED_THRESHOLD KZ_LOG_LEVEL_TRACE
You can create you own log levels. See KZ_LOG_CREATE_LEVEL
.
Use log categories to group log messages that contain information related to specific functionality.
The Kanzi logging system has these default log categories:
Log category | Description |
---|---|
KZ_LOG_CATEGORY_DEBUG
|
Collects debug messages. |
KZ_LOG_CATEGORY_GRAPHICS_MESH_EXTRA
|
Collects graphics mesh log messages. |
KZ_LOG_CATEGORY_EGL_EXTRA
|
Collects EGL log messages. |
KZ_LOG_CATEGORY_GENERIC
|
Collects log messages that you have not assigned to any other log category. It is recommended to always explicitly assign a log message to one of the log categories, or create a new log category. |
To create and use a log category:
KZ_LOG_CREATE_CATEGORY
macro:// Create a log category named "My category" and set the state of the category to enabled.
// The Kanzi logging system uses category state to filter log messages.
// To disable a log category, use KZ_LOG_DISABLED_CATEGORY
.
#define MY_LOG_CATEGORY KZ_LOG_CREATE_CATEGORY(KZ_LOG_ENABLED_CATEGORY, "My category")
// Print to the log "This is an info message." using the MY_LOG_CATEGORY log category. kzLogInfo(MY_LOG_CATEGORY, ("This is an info message."));
info:My category> This is an info message.
To redirect log messages, you can implement a custom logger class, which inherits from AbstractLogger
, and push the custom logger to the Kanzi logging system. Make your logger class override the AbstractLogger::writeOverride
function.
To write log messages using your custom logger, use the kzLog
macro.
If you want to use your custom logger to write all the application log messages, register the logger in the Default Logger (DefaultLogger
). The Default Logger inherits from AbstractLogger
and contains a chain of loggers through which every log message passes. These loggers are by default registered in the Default Logger:
Default logger | Destination of log messages |
---|---|
CoutLogger
|
Standard output |
AndroidLogger
|
Android system log |
Win32DebugLogger
|
Kanzi debug console on Windows |
To implement a logger:
// Use this logger to store log messages in a container for later retrieval. // // This class inherits from kanzi::AbstractLogger and implements the writeOverride() function. It stores logs in the container. // To retrieve the logs, use the get() function. class SimpleLogger : public AbstractLogger { public: // Kanzi calls this function to write messages to the log. // // This function stores the log message in a container. To retrieve all log messages, use the get() function. // Each log message includes: // - The message text // - The log level // - The log category // - If the message is an error, the file name and the line number where the error occured // // \param level The log level of the message. // \param levelName The string representation of the log level. // \param categoryName The string representation of the log category. // \param fileName The name of the file in which the message originated. // \param lineNumber The number of the line on which the message originated. // \param message The message. virtual void writeOverride(LogLevel level, string_view levelName, string_view categoryName, string_view fileName, size_t lineNumber, string_view message) { // Start the log with the level name. string logMessage(levelName); // Separate the log level and the log category with a colon. logMessage += ':'; // Add the category name. logMessage.append(categoryName.data(), categoryName.length()); if (level == LogLevelError) { // The error is reported. // To show where in the code the error was reported, add the file name and the line number to the message. logMessage.append(fileName.data(), fileName.length()); // Separate the file name and the line number with a colon. logMessage += ':'; logMessage += to_string(lineNumber); } // Add an angle bracket and the message text. logMessage += "> "; logMessage.append(message.data(), message.length()); // Append the log message to the log vector. m_log.push_back(logMessage); } // Get log vector reference. vector<string>& getLog() { return m_log; } private: // Log vector. vector<string> m_log; };
To use a logger explicitly:
// SimpleLogger inherits from kanzi::AbstractLogger and implements writeOverride. SimpleLogger simpleLogger; // Write a log message using the SimpleLogger. kzLog(simpleLogger, KZ_LOG_LEVEL_INFO, KZ_LOG_CATEGORY_GENERIC, ("Lets log 1 + 2 = {}.", 1 + 2));
To use a logger in a logger chain:
// SimpleLogger inherits from kanzi::AbstractLogger and implements writeOverride. AbstractLoggerUniquePtr simpleLogger(new SimpleLogger()); // Before adding SimpleLogger to the logger chain, get the pointer to it. // After you add SimpleLogger to the logger chain, the logger chain controls the lifetime of SimpleLogger. SimpleLogger* simpleLoggerPtr = static_cast<SimpleLogger*>(simpleLogger.get()); // Push SimpleLogger to the logger chain. Now both SimpleLogger and the rest of the loggers handle every logged message. DefaultLogger::pushLogger(kanzi::move(simpleLogger)); // Write a log message. SimpleLogger handles this message. kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Lets log 1 + 2 = {}.", 1 + 2));
To set your logger to handle all the log messages:
// SimpleLogger inherits from kanzi::AbstractLogger and implements writeOverride. AbstractLoggerUniquePtr simpleLogger(new SimpleLogger()); // Before adding SimpleLogger to the logger chain, get the pointer to it. // After you add SimpleLogger to the logger chain, the logger chain controls the lifetime of SimpleLogger. SimpleLogger* simpleLoggerPtr = static_cast<SimpleLogger*>(simpleLogger.get()); // Remove all default loggers from the logger chain. // This way you make only SimpleLogger, which you push to the chain later, handle the logged messages. DefaultLogger::popAllLoggers(); // Push SimpleLogger to the logger chain. Now only SimpleLogger handles every logged message. DefaultLogger::pushLogger(kanzi::move(simpleLogger)); // Write a log message. SimpleLogger handles this message. kzLogInfo(KZ_LOG_CATEGORY_GENERIC, ("Lets log 1 + 2 = {}.", 1 + 2));
Measuring application performance
Troubleshooting the performance of your application
Logging Kanzi Engine performance profiling data
Logging application code performance profiling data