DOCA SDK Documentation

DOCA Log

The DOCA logging infrastructure provides a mechanism for printing error messages, debug logs, and application-specific messages within the DOCA SDK.

To use DOCA logging, applications must include the doca_log.h header file in their source code.

Log Verbosity Level Enumerations

DOCA logging supports multiple verbosity levels, allowing applications to filter logs based on severity:

C++
enum doca_log_level {
	DOCA_LOG_LEVEL_DISABLE = 10,	/**< Disable log messages */
	DOCA_LOG_LEVEL_CRIT = 20,		/**< Critical log level */
	DOCA_LOG_LEVEL_ERROR = 30,		/**< Error log level */
	DOCA_LOG_LEVEL_WARNING = 40,	/**< Warning log level */
	DOCA_LOG_LEVEL_INFO = 50,		/**< Info log level */
	DOCA_LOG_LEVEL_DEBUG = 60,		/**< Debug log level */
	DOCA_LOG_LEVEL_TRACE = 70,		/**< Trace log level */
};

The DOCA_LOG_LEVEL_TRACE verbosity level is available only if the macro DOCA_LOGGING_ALLOW_TRACE is defined before compilation.

Refer to doca_log.h for more information.

Logging Backends

A logging backend is the destination where log messages are directed. DOCA supports multiple backend types:

  • FILE* – Any open file, including stdout or stderr

  • File descriptor – Any valid file descriptor (e.g., raw files, sockets, pipes)

  • Buffer (buf) – A memory buffer that stores log messages and triggers a callback for each message

  • Syslog – Standard system logging mechanism

Each logging backend is initialized with the following default verbosity levels:

  • Lower level – DOCA_LOG_LEVEL_INFO

  • Upper level – DOCA_LOG_LEVEL_CRIT

DOCA SDK logs and application logs have different configurations and can be controlled independently through the DOCA logging API.

All messages are sent to all backends that meet the configured verbosity level.

Enabling DOCA SDK Libraries Logging

DOCA SDK libraries automatically print debug and error messages to the configured logging backends.

The maximum number of logging backends can be queried using doca_log_get_max_num_backends_sdk().

To create a logging backend for SDK logs, use:

C++
doca_log_backend_create_with_file_sdk()
doca_log_backend_create_with_fd_sdk()
doca_log_backend_create_with_buf_sdk()
doca_log_backend_create_with_syslog_sdk()

When creating a new SDK logging backend, the first message printed is the DOCA version, which is printed in verbosity level INFO.

The following functions control SDK logging levels: 

  • doca_log_level_set_global_sdk_limit() sets global verbosity level 

    This function applies to all SDK backends.

    A newly created SDK backend’s verbosity level is set to the SDK global verbosity level value by default.

  • doca_log_backend_set_sdk_level() sets verbosity level for a specific SDK backend

  • doca_log_level_get_global_sdk_limit() gets the global SDK verbosity level

Log messages may change across DOCA versions. Do not rely on specific message formatting or content permanence.

Enabling DOCA Application Logging

Applications that use the DOCA SDK can utilize DOCA logging for structured logging

The maximum number of logging backends can be queried using doca_log_get_max_num_backends().

The total number of application logging backends that can be created can be queried using the following function:

C++
doca_log_get_max_num_backends()

To create an application logging backend, use:

C++
doca_log_backend_create_with_file()
doca_log_backend_create_with_fd()
doca_log_backend_create_with_buf()
doca_log_backend_create_with_syslog()

The following functions configure logging limits: 

  • doca_log_backend_set_level_{lower|upper}_limit() sets lower and/or upper verbosity levels for a backend 

    The lower and upper verbosity levels of a newly created backend are set to the default values.

  • doca_log_backend_create_standard() creates a standard, non-configurable logging setup. It creates two backends:stdout – Logs messages up to DOCA_LOG_LEVEL_INFOstderr – Logs messages from DOCA_LOG_LEVEL_WARNING to DOCA_LOG_LEVEL_CRIT

  • doca_log_backend_set_level_{lower|upper}_limit_strict() sets strict limits for a backend (prevent future changes)

  • doca_log_level_set_global_{lower|upper}_limit() sets global logging limits (affects all non-strict backends)

Logging DOCA Application Messages

To enable DOCA logging in an application, use the DOCA log registration macro at the beginning of each source file:

C++
DOCA_LOG_REGISTER(source);

This registers a logger for that file and automatically manages teardown.

The length of the source provided to DOCA_LOG_REGISTER() cannot be greater than DOCA_LOGGER_NAME_SIZE.

Log messages are printed using the following macros (similar to printf() syntax):

C++
DOCA_LOG_CRIT(format, ...);   // Critical error messages
DOCA_LOG_ERR(format, ...);    // Standard error messages
DOCA_LOG_WARN(format, ...);   // Warnings
DOCA_LOG_INFO(format, ...);   // Informational messages
DOCA_LOG_DBG(format, ...);    // Debug messages
DOCA_LOG_TRC(format, ...);    // Trace-level messages

Messages are printed to all application logging backends that fall within the configured verbosity range.

Controlling Verbosity Level of Loggers

Every logger, whether created by an SDK library or an application, operates independently. You can control the output of each logger by adjusting its individual verbosity level.

Use the following functions to create or destroy a list of active loggers:

  • doca_logger_create_list() – Generates a list of all current loggers.

  • doca_logger_destroy_list() – Frees the list memory.

Configuration changes (such as verbosity levels) are persistent and remain in effect even after the list is destroyed.

Once you have the list, you can manage individual loggers using:

  • doca_logger_set_level() – Sets the verbosity level for a specific logger.

  • doca_logger_get_level() – Retrieves the current verbosity level.

  • doca_logger_get_name() – Retrieves the name of a logger.

To locate a specific logger within the list:

  • doca_logger_find_by_name() – Returns a pointer to the logger matching the specified name.

DOCA Log Aggregation

Log aggregation offers a way to optimize performance in multi-threaded environments by reducing contention on log backends (for example, multiple threads attempting to write concurrently to the same file). Log aggregation enables each worker thread to write log messages to an in-memory buffer. A dedicated background thread then periodically flushes these messages to the configured log backends.

This approach significantly improves worker thread efficiency, as application threads can continue processing without being delayed by logging operations or backend contention. All existing DOCA Log functionality is retained. No change to logging code is required beyond starting the aggregation thread and the shutdown considerations below.

Log Aggregation uses fixed size buffers to obtain maximum performance, therefore messages may be dropped when under heavy load. The log Aggregation API enables configuration of the backend to modify the impact of this based on the applications needs.

To guarantee all log messages are written, log aggregation should not be used; however, this will negatively impact performance.

  • Only messages with a severity lower than max_unaggregated_level may be dropped

  • Messages with a severity greater than or equal to max_unaggregated_level are guaranteed to be written.

To enable log aggregation, the background aggregation thread must be created before specific log backends. When enabled, all messages with severity greater than or equal max unaggreagated are guaranteed to be written, while those bellow may be dropped.

If the background thread is not started, DOCA Log behaves exactly as it did previously.

Log aggregation is only supported on Linux.

Log Aggregation API

doca_log_set_max_unaggreated_level(uint32_t level) - Sets the maximum aggregated level. Messages logged at or above this severity bypass aggregation and are immediately written to the backend, along with any buffered messages. The logging thread will block until this flush is complete. Default: DOCA_LOG_LEVEL_WARNING

doca_log_set_bg_sampling period(uint32 usec) - Sets the maximum sleep interval for the background aggregation thread. If buffered messages are present, the background thread continues processing without delay, only when no buffered messages are present will the thread sleep. A value of 0 may be used to process all messages without delay. Default: 100,000 microseconds

doca_log_set_max_aggregated_size(uint32_t size) - Sets the maximum size of a single batch of aggregated messages written to the backends. Default: 128KiB

doca_log_process_msg(void *unused) - Entry point for the background aggregation thread, this function should be passed to pthread_create().

Only one aggregation thread may be running per application.

This function does not return under normal operation and runs until application shutdown.

Shutdown considerations

Because the aggregation thread runs until application termination, it may still be writing logs when the application exits, potentially leading to undefined behavior. Special considerations should be taken to shut down correctly:

  1. Force a flush of the aggregation buffers by logging a message with a severity greater than or equal to max_unaggregated_level

  2. This operation will block until all buffered messages are written.

  3. After the flush is completed, no further messages should be logged.

  4. It is now safe to clean up logging resources and terminate the application.

Example usage

C
void *log_fn(void* unused)
{
	DOCA_LOG_INFO("Log from secondary thread");
	return NULL;
}

int main()
{
	pthread_t aggregator_thread;
	pthread_create(&aggregator_thread, NULL, doca_log_process_msg, NULL);
	pthread_detatch(aggregator_thread);

	struct doca_log_backend *backend;
	FILE *log_file = fopen("/path/to/file.log", "w");
	doca_log_backend_create_with_file_sdk(log_file, &backend);

	pthread_t log_thread;
	ptherad_create(&log_thread, NULL, log_fn, NULL);

	DOCA_LOG_INFO("Log from primary thread");
	
	/* Force the aggregation buffers to be flushed */
	DOCA_LOG_WARN("Flush buffers");

	/* Clean up and exit */
	pthread_join(log_thread, NULL);
	fclose(log_file);

	return 0;
}

DOCA Log Samples

All the DOCA LOG samples described in this section are governed under the BSD-3 software license agreement.

Log_limits_client Sample

The doca_log_limits_clientsample demonstrates how to send a single UDP command (get-limits, set-lower-limits, or set-upper-limits) to a doca_log_limits_server to either read the current DOCA_LOG level limits or set the lower/upper DOCA_LOG level limit value.
This sample does not accept multiple commands, only the first valid command is sent to the log_limits_server.

Sample usage: 

Usage: doca_log_limits_client [DOCA Flags] [Program Flags]

DOCA Flags:
  -h, --help                        Print a help synopsis
  -v, --version                     Print program version information
  -l, --log-level                   Set the (numeric) log level for the program <10=DISABLE, 20=CRITICAL, 30=ERROR, 40=WARNING, 50=INFO, 60=DEBUG, 70=TRACE>
  --sdk-log-level                   Set the SDK (numeric) log level for the program <10=DISABLE, 20=CRITICAL, 30=ERROR, 40=WARNING, 50=INFO, 60=DEBUG, 70=TRACE>
  --log-filter                      Filter logs from specific modules, separated by comma
  -j, --json <path>                 Parse command line flags from an input json file

Program Flags:
  -p, --port                        Server UDP port (default: 9999), should be a port number > 1024 to avoid "sudo" requirement
  -i, --ip                          Server IPv4 address (default: 127.0.0.1), only IPv4 is supported. A valid IPv4 address is expected to be 4 dot-separated numbers.
  -g, --get-limits                  Get both lower and upper log limits from the server
  -sl, --set-lower-limit            Set the lower log limit on the server, valid values must be >=10 and <=70 and a multiple of 10
  -su, --set-upper-limit            Set the upper log limit on the server, valid values must be >=10 and <=70 and a multiple of 10
# Read current global DOCA_LOG lower and upper level limits from the log_limits_server
./doca_log_limits_client [-i <server_ip>] [-p <port>] -g

# Set the log_limits_server's global DOCA_LOG lower level limit to DOCA_LOG_LEVEL_DEBUG
./doca_log_limits_client [-i <server_ip>] [-p <port>] -sl 60

# Set  the log_limits_server's global DOCA_LOG upper level limit to DOCA_LOG_LEVEL_CRIT
./doca_log_limits_client [-i <server_ip>] [-p <port>] -su 20

Log Limits Server Sample

The doca_log_limits_server sample demonstrates how to dynamically adjust global log level limits using the DOCA_LOG API. It operates as a UDP server that continuously generates DOCA LOG messages across all severity levels (CRIT, ERROR, WARN, INFO, DEBUG, and TRACE).

Client-Server Interaction

The server provisions a UDP socket to accept incoming connections from a doca_log_limits_client. It parses and executes the following commands:

Client Command

Executed DOCA APIs

Server Behavior & Response

get-limits

doca_log_level_get_global_lower_limit

doca_log_level_get_global_upper_limit

Returns the current lower and upper limit values directly to the client.

set-lower-limit

doca_log_level_set_global_lower_limit

No response is sent to the client. The dynamic level change is immediately visible in the server's continuous log output.

set-upper-limit

doca_log_level_set_global_upper_limit

No response is sent to the client. The dynamic level change is immediately visible in the server's continuous log output.

The server continues running and outputting log messages to demonstrate the impact of the limit changes until it is terminated via Ctrl+C.

This sample runs as a UDP server that continuously prints DOCA LOG messages at various levels (CRIT, ERROR, WARN, INFO, DEBUG, TRACE):

Execution and Usage

Start the server:

$ ./doca_log_limits_server [-p <port>]

Command line flags: 

Usage: doca_log_limits_server [DOCA Flags] [Program Flags]

DOCA Flags:
  -h, --help                        Print a help synopsis
  -v, --version                     Print program version information
  -l, --log-level                   Set the (numeric) log level for the program <10=DISABLE, 20=CRITICAL, 30=ERROR, 40=WARNING, 50=INFO, 60=DEBUG, 70=TRACE>
  --sdk-log-level                   Set the SDK (numeric) log level for the program <10=DISABLE, 20=CRITICAL, 30=ERROR, 40=WARNING, 50=INFO, 60=DEBUG, 70=TRACE>
  --log-filter                      Filter logs from specific modules, separated by comma
  -j, --json <path>                 Parse command line flags from an input json file

Program flags:

Short Flag

Long Flag

Default

Description

-p

--port

9999

The server UDP port. It is highly recommended to use a port number > 1024 to avoid requiring sudo (root) privileges.

Last updated: