tl;dr: kernel logging is cumbersome. This PR enables structured logging and a much simplified kernel logging interface. Closes #34062.
Motivation
The bitcoinkernel library (#27587) exposes functionality to interface with the kernel logging. This includes registering callbacks for log statements, level/category filtering, string formatting options, and more.
Kernel logging has a few problems:
- callbacks operate on formatted strings, so users need to parse the string to get the timestamp, category, level, … based on which options are set. This is cumbersome, brittle, and inefficient.
- the filtering interface is not really intuitive, requiring users to call combinations of
btck_logging_set_level_categoryandbtck_logging_enable_categorywhen they want to producedebugortracelogs. The level/category system makes sense for node, because it directly controls what gets written to disk and stdout, and there are quite a lot more categories producing logs. Kernel doesn’t really need this - users control what happens to the logs, and can do any filtering/manipulation in the callback they provide. - the node logging infrastructure has quite a bit more functionality than is necessary for a library, including ratelimiting, log formatting, outputting, buffering, … This introduces unnecessary code and interface complexity.
Approach
Most of the logic in logging.h is not necessary for bitcoinkernel, so we first separate it into util/log.h and logging.h (common), then upgrade the bitcoinkernel logging interface, and finally remove the logging.cpp dependency from kernel entirely.
- Separate log generation: Add a minimal
util::log::Dispatcherthat is used to generate logs, and forwards structured log entries to registered callbacks. No formatting, rate-limiting, or output handling - that’s the consumer’s responsibility. Dispatcher can be configured with afilterpredicate (e.g.WillLogCategoryLevel()fornode, or a simpler levels-based filter forbitcoinkernel) to avoid unnecessary string formatting and other overhead. - Register
BCLog::Loggeron Dispatcher: Register a callback on the global Dispatcher to receive entries and handle node-specific concerns (formatting, rate-limiting, file output) without changing most of its logic. - Move logging macros to
util/log.h: Allows the entire codebase (including kernel code) to use the same macros without depending onlogging.h. - Update bitcoinkernel C API: Replace the string-based callback with
btck_LogEntrycontaining full metadata. Removebtck_LoggingOptionsand category enable/disable functions. Addbtck_logging_set_min_level()for early filtering. - Move
logging.cpptocommon: remove it as a kernel dependency entirely.
Appendix
bitcoinkernel C logging interface
0struct btck_LogEntry {
1 const char* message; //!< Log message
2 size_t message_len; //!< Log message length
3 const char* file_name; //!< Source file name
4 size_t file_name_len; //!< Source file name length
5 const char* function_name; //!< Source function name
6 size_t function_name_len; //!< Source function name length
7 const char* thread_name; //!< Thread name
8 size_t thread_name_len; //!< Thread name length
9 int64_t timestamp_ns; //!< Timestamp in nanoseconds since epoch
10 uint32_t line; //!< Source line number
11 btck_LogLevel level; //!< Log level
12 btck_LogCategory category; //!< Log category
13};
14
15typedef void (*btck_LogCallback)(void* user_data, const btck_LogEntry* entry);
16
17BITCOINKERNEL_API void btck_logging_set_min_level(btck_LogLevel level);
18
19BITCOINKERNEL_API btck_LoggingConnection* BITCOINKERNEL_WARN_UNUSED_RESULT btck_logging_connection_create(
20 btck_LogCallback log_callback,
21 void* user_data,
22 btck_DestroyCallback user_data_destroy_callback) BITCOINKERNEL_ARG_NONNULL(1);
23
24BITCOINKERNEL_API void btck_logging_connection_destroy(btck_LoggingConnection* logging_connection);