3232#include < util/fs.h>
3333#include < util/result.h>
3434#include < util/signalinterrupt.h>
35+ #include < util/string.h>
3536#include < util/task_runner.h>
37+ #include < util/time.h>
3638#include < util/translation.h>
3739#include < validation.h>
3840#include < validationinterface.h>
4446#include < exception>
4547#include < functional>
4648#include < iterator>
47- #include < list>
4849#include < memory>
4950#include < span>
5051#include < stdexcept>
@@ -171,6 +172,14 @@ constexpr util::log::Level get_bclog_level(btck_LogLevel level)
171172 return LOG_LEVELS[level].bclog ;
172173}
173174
175+ btck_LogLevel get_btck_level (util::log::Level level)
176+ {
177+ for (size_t i = 0 ; i < LOG_LEVELS.size (); ++i) {
178+ if (LOG_LEVELS[i].bclog == level) return static_cast <btck_LogLevel>(i);
179+ }
180+ assert (false );
181+ }
182+
174183struct LogCategoryMapping {
175184 BCLog::LogFlags bclog;
176185 std::string_view name;
@@ -200,6 +209,14 @@ constexpr BCLog::LogFlags get_bclog_flag(btck_LogCategory category)
200209 return LOG_CATEGORIES[category].bclog ;
201210}
202211
212+ btck_LogCategory get_btck_category (BCLog::LogFlags flag)
213+ {
214+ for (size_t i = 0 ; i < LOG_CATEGORIES.size (); ++i) {
215+ if (LOG_CATEGORIES[i].bclog == flag) return static_cast <btck_LogCategory>(i);
216+ }
217+ assert (false );
218+ }
219+
203220btck_SynchronizationState cast_state (SynchronizationState state)
204221{
205222 switch (state) {
@@ -225,47 +242,45 @@ btck_Warning cast_btck_warning(kernel::Warning warning)
225242}
226243
227244struct LoggingConnection {
228- std::unique_ptr<std::list<std::function< void ( const std::string&)>>::iterator> m_connection ;
245+ util::log::Dispatcher::CallbackHandle m_callback_handle ;
229246 void * m_user_data;
230247 std::function<void (void * user_data)> m_deleter;
231248
232249 LoggingConnection (btck_LogCallback callback, void * user_data, btck_DestroyCallback user_data_destroy_callback)
250+ : m_user_data{user_data}, m_deleter{user_data_destroy_callback}
233251 {
234- LOCK (cs_main);
235-
236- auto connection{LogInstance ().PushBackCallback ([callback, user_data](const std::string& str) { callback (user_data, str.c_str (), str.length ()); })};
237-
238- // Only start logging if we just added the connection.
239- if (LogInstance ().NumConnections () == 1 && !LogInstance ().StartLogging ()) {
240- LogError (" Logger start failed." );
241- LogInstance ().DeleteCallback (connection);
242- if (user_data && user_data_destroy_callback) {
243- user_data_destroy_callback (user_data);
252+ m_callback_handle = util::log::g_dispatcher ().RegisterCallback ([callback, user_data](const util::log::Entry& entry) {
253+ const auto timestamp_ns{Ticks<std::chrono::nanoseconds>(entry.timestamp .time_since_epoch ())};
254+ std::string_view file_name{entry.source_loc .file_name ()};
255+ std::string_view function_name{entry.source_loc .function_name_short ()};
256+ // Some log statements are manually suffixed with a newline.
257+ std::string_view message{util::RemoveSuffixView (entry.message , " \n " )};
258+
259+ btck_LogEntry btck_entry{
260+ .message = {message.data (), message.size ()},
261+ .file_name = {file_name.data (), file_name.size ()},
262+ .function_name = {function_name.data (), function_name.size ()},
263+ .thread_name = {entry.thread_name .data (), entry.thread_name .size ()},
264+ .timestamp_ns = timestamp_ns,
265+ .line = entry.source_loc .line (),
266+ .level = get_btck_level (entry.level ),
267+ .category = get_btck_category (static_cast <BCLog::LogFlags>(entry.category )),
268+ };
269+ try {
270+ callback (user_data, &btck_entry);
271+ } catch (const std::exception& e) {
272+ LogError (" Logging callback threw unexpected exception: %s" , e.what ());
244273 }
245- throw std::runtime_error (" Failed to start logging" );
246- }
247-
248- m_connection = std::make_unique<std::list<std::function<void (const std::string&)>>::iterator>(connection);
249- m_user_data = user_data;
250- m_deleter = user_data_destroy_callback;
274+ });
251275
252276 LogDebug (BCLog::KERNEL, " Logger connected." );
253277 }
254278
255279 ~LoggingConnection ()
256280 {
257- LOCK (cs_main);
258281 LogDebug (BCLog::KERNEL, " Logger disconnecting." );
282+ util::log::g_dispatcher ().UnregisterCallback (m_callback_handle);
259283
260- // Switch back to buffering by calling DisconnectTestLogger if the
261- // connection that we are about to remove is the last one.
262- if (LogInstance ().NumConnections () == 1 ) {
263- LogInstance ().DisconnectTestLogger ();
264- } else {
265- LogInstance ().DeleteCallback (*m_connection);
266- }
267-
268- m_connection.reset ();
269284 if (m_user_data && m_deleter) {
270285 m_deleter (m_user_data);
271286 }
@@ -773,6 +788,7 @@ void btck_logging_disable()
773788
774789btck_LoggingConnection* btck_logging_connection_create (btck_LogCallback callback, void * user_data, btck_DestroyCallback user_data_destroy_callback)
775790{
791+ assert (callback);
776792 try {
777793 return btck_LoggingConnection::create (callback, user_data, user_data_destroy_callback);
778794 } catch (const std::exception&) {
0 commit comments