{
 "number": 34775,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/34775",
 "title": "kernel: make logging callback global",
 "author": "stickies-v",
 "author_association": "MEMBER",
 "created_at": "2026-03-09T08:35:36Z",
 "updated_at": "2026-09-17T11:46:35Z",
 "age_days": 192,
 "draft": false,
 "labels": [
  "Validation"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "f40aeb12ed85201b0127317a9bb1bf6cdb258eab",
 "head_ref": "2026-02/kernel-logging-global",
 "head_repo": "stickies-v/bitcoin",
 "head_history": [
  {
   "t": "2026-09-17T11:24:48Z",
   "sha": "f40aeb12ed85201b0127317a9bb1bf6cdb258eab"
  }
 ],
 "additions": 105,
 "deletions": 66,
 "changed_files": 5,
 "commit_count": 1,
 "size_bucket": "M",
 "mergeable_state": "unstable",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "concept_ack": [
     {
      "login": "sedited",
      "url": "https://github.com/bitcoin/bitcoin/pull/34775#issuecomment-4022995511"
     }
    ],
    "approach_ack": [
     {
      "login": "w0xlt",
      "url": "https://github.com/bitcoin/bitcoin/pull/34775#issuecomment-4792069971"
     }
    ]
   },
   "conflicts": [
    {
     "number": 35322,
     "title": "logging: streamline Logger state and drop redundant methods",
     "author": "ryanofsky"
    },
    {
     "number": 34374,
     "title": "kernel: use struct-based logging and simplify logging interface",
     "author": "stickies-v"
    }
   ]
  }
 },
 "acks_parsed": {
  "w0xlt": {
   "kind": "approach_ack",
   "hash": null,
   "t": "2026-06-24T17:41:45Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 1,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": [
   "purpleKarrot",
   "ryanofsky",
   "sedited",
   "w0xlt"
  ]
 },
 "signals": {
  "needs_rebase": false,
  "ci_failed": false,
  "mergeable_state": "unstable",
  "last_author_activity": "2026-09-17T11:46:35Z",
  "last_reviewer_activity": "2026-08-27T11:04:39Z",
  "last_reviewer": "sedited",
  "author_silent_days": 0,
  "waiting_on_author_days": 0,
  "days_since_update": 0
 },
 "refs": {
  "mentioned": [
   30342,
   34374
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34374,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "kernel: use struct-based logging and simplify logging interface"
   },
   {
    "number": 30342,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "kernel, logging: Pass Logger instances to kernel objects"
   }
  ],
  "conflicts": [
   35322,
   34374
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [
  "src/kernel/bitcoinkernel.cpp",
  "src/kernel/bitcoinkernel_wrapper.h",
  "src/test/kernel/test_kernel.cpp"
 ],
 "body": "The underlying `LogInstance()` is a process-wide singleton, and all logging configuration (categories, levels, options) are already global. The per-connection `btck_LoggingConnection` handle gives the false impression of independent logger instances.\n\nFix this by explicitly making the entire kernel logging interface explicitly global, simplifying its usage. Replaces `btck_LoggingConnection` and its `{create,destroy}` functions with a single `btck_logging_set_callback` function. The `KernelLogger` class is introduced to hold global kernel logging state, which will be used in future work such as #34374.\n\nTo an extent, this approach is an alternative to #30342 which contextualizes logging. While I do believe contextualized logging would be a natural fit for the kernel interface, it seems there is currently (in my view) too little demand for the scope of changes necessary. That's why I've opened this PR as a much more straightforward way to fix kernel's current logging weirdness. If you believe kernel logging should be contextualized right away, please go review #30342 instead.",
 "commits": [
  {
   "sha": "f40aeb12ed85201b0127317a9bb1bf6cdb258eab",
   "date": "2026-09-17T11:24:40Z",
   "message": "kernel: make logging callback global\n\nThe underlying LogInstance() is a process-wide singleton, and all\nlogging configuration (categories, levels, options) are already\nglobal. The per-connection btck_LoggingConnection handle gives the\nfalse impression of independent logger instances.\n\nReplace btck_logging_connection_create/destroy with a single\nbtck_logging_set_callback that sets or clears the global callback.\nInternally, a KernelLogger singleton manages the LoggingConnection\nlifetime, intentionally leaked on exit to avoid static destruction\norder issues (matching LogInstance).\n\nThe C++ wrapper keeps Logger as the RAII owner of the global callback:\nit sets the callback on construction and resets it on destruction, so\nconsumers keep the scoped lifetime the handle gave them, and a test\ncannot leak its callback into later tests. Constructing a second Logger\nwhile one exists throws, since they would share the single slot."
  }
 ],
 "timeline": [
  {
   "t": "2026-03-09T11:12:37Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nIt really isn't a feature/issue that is sorely missed for the foreseeable future in the kernel library. There are a few applications where it would be a nice to have. Logs coming from different sources, for example in the units tests, can be a little confusing sometimes, but even that has been manageable, and I don't think I've heard many complain about that.\n\nNot having separate connections seems simpler. Clients of the library can still multiplex the single callback on their side in whatever fashion they wish to. There are many other (and more interesting problems imo) to be working on, so this seems like the pragmatic thing to do for now.\n\nConcept ACK"
  },
  {
   "t": "2026-03-09T13:12:49Z",
   "kind": "comment",
   "who": "purpleKarrot",
   "assoc": "MEMBER",
   "text": "I would go a step further. Since the log function is global, there is no need for local user data. It can be a simple function pointer, even in the C++ wrapper."
  },
  {
   "t": "2026-03-09T14:35:51Z",
   "kind": "comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "text": "[quoted text omitted]\n\nForcing the user to use globals if they need state seems unnecessary, when using `user_data` is I think a well-established pattern in C APIs? Unless I'm misunderstanding your suggested approach?"
  },
  {
   "t": "2026-03-09T15:09:15Z",
   "kind": "comment",
   "who": "ryanofsky",
   "assoc": "MEMBER",
   "text": "I think it would be a mistake to limit functionality of the logging/debuging/tracing API prematurely, in a way that seems difficult to reverse and does not seem to provide a noticeable simplification (possible I missed it, I have not reviewed the code much yet!). Anyway I have many more thoughts on this topic and can post them later.\n\nOne thing I did want to say is I don't think https://github.com/bitcoin/bitcoin/pull/30342 is the only alternative to this and other approaches should be possible. Also I am actively working on #30342, and will push a significant update to it today or tomorrow. So if there are problems with that approach, I would like to at least try to pin them down and address them.\n\nMy preference in terms of review & development effort would be to undraft your other PR #34374. I rebased that PR recently https://github.com/bitcoin/bitcoin/pull/34374#issuecomment-4012333941 and think is ready for review, and that it makes improvements that should have many more benefits to applications than this PR. Personally, I would like to review it and see it merged ASAP."
  },
  {
   "t": "2026-06-04T20:16:16Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "@stickies-v I'm not sure how we should proceed here. Are you still looking for review here, or should we work towards #34374?"
  },
  {
   "t": "2026-06-05T20:22:33Z",
   "kind": "comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "text": "My apologies for not responding earlier @ryanofsky\n\n[quoted text omitted]\nIt's a +76/-72 diff, I don't think this will be particularly hard to reverse? If you're talking about breaking the interface: it is unversioned and we're quite explicit about breaking it when we want to, so I don't think that's a concern either. Of course, we shouldn't merge this when it seems like there is strong conceptual support for an alternative.\n\n[quoted text omitted]\nI think having an interface that looks like it makes sense to have multiple logging connections, when it actually doesn't is unnecessarily confusing. While having documentation is good, having a self-explanatory interface is better.\n\nGenerally, I don't think this PR should or will prevent future changes that improve contextualized logging. It just seems to me like there currently isn't a lot of support for those improvements, so I think it's better to clean up the interface since that's such a straightforward change. I'm not opposed to contextualized logging, but I won't be reviewing it myself as I think it's currently not worth the effort.\n\n[quoted text omitted]\nThese changes are orthogonal to #34374 (they both use a `KernelLogger` class, but that's an implementation detail). So yes, I'm still looking for review here."
  },
  {
   "t": "2026-06-11T11:56:50Z",
   "kind": "review_comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "path": "src/kernel/bitcoinkernel.cpp",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": null,
   "text": "Does this have to be a raw pointer?"
  },
  {
   "t": "2026-06-11T12:03:24Z",
   "kind": "review_comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "path": "src/test/kernel/test_kernel.cpp",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": null,
   "text": "I think this shows the downside of exposing a global function for this: Even though this function is scoped to this test, it now enables logging for all the the other unit tests too. Maybe add another call to set the callback to null at the end of the test?"
  },
  {
   "t": "2026-06-11T12:05:50Z",
   "kind": "review_comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "path": "src/kernel/bitcoinkernel_wrapper.h",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": null,
   "text": "How about calling this `logging_reset_callback` and removing the argument?"
  },
  {
   "t": "2026-06-24T17:41:45Z",
   "kind": "comment",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "text": "Approach ACK"
  },
  {
   "t": "2026-07-16T00:08:03Z",
   "kind": "review_comment",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/kernel/test_kernel.cpp",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": 3395661504,
   "text": "Yes, any test that installs the global logging callback now needs to clear it before returning to prevent state leakage into later tests.\n`logging_tests` already does this, so `btck_chainman_tests` would need to do the same.\n\n```diff\ndiff --git a/src/test/kernel/test_kernel.cpp b/src/test/kernel/test_kernel.cpp\nindex cfd02ea495..1413d5be22 100644\n--- a/src/test/kernel/test_kernel.cpp\n+++ b/src/test/kernel/test_kernel.cpp\n@@ -758,6 +758,7 @@ BOOST_AUTO_TEST_CASE(btck_chainman_tests)\n     BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/true));\n     BOOST_CHECK(chainman_opts.SetWipeDbs(/*wipe_block_tree=*/false, /*wipe_chainstate=*/false));\n     ChainMan chainman{context, chainman_opts};\n+    logging_set_callback(nullptr);\n }\n\n std::unique_ptr<ChainMan> create_chainman(TestDirectory& test_directory,\n```"
  },
  {
   "t": "2026-07-16T00:22:06Z",
   "kind": "review_comment",
   "who": "w0xlt",
   "assoc": "CONTRIBUTOR",
   "path": "src/test/kernel/test_kernel.cpp",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": 3395661504,
   "text": "I think the C++ wrapper could retain RAII while still exposing a single global logging callback."
  },
  {
   "t": "2026-08-27T11:04:39Z",
   "kind": "comment",
   "who": "sedited",
   "assoc": "MEMBER",
   "text": "@stickies-v what is the status here?"
  },
  {
   "t": "2026-09-16T06:39:41Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "src/kernel/bitcoinkernel.cpp",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": 3395620071,
   "text": "I think so, to avoid running consumer code from static destructors. The order of destruction of static objects is undefined, so a plain static would run the consumer's destroy callback at some point during process teardown that they can't control, e.g. after objects their `user_data` refers to are already destroyed, or after a language runtime like Python has shut down. It's more important for #34374, where we also want to avoid log statements referencing a logger that's already destroyed, but it seems sensible to leak it here too."
  },
  {
   "t": "2026-09-17T11:24:48Z",
   "kind": "force_push",
   "who": "stickies-v",
   "commit": "f40aeb12ed85201b0127317a9bb1bf6cdb258eab"
  },
  {
   "t": "2026-09-17T11:43:55Z",
   "kind": "comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "text": "Force-pushed to rebase onto latest master, and to:\n- address @w0xlt's [suggestion](https://github.com/bitcoin/bitcoin/pull/34775#discussion_r3591661659) to have an RAII `Logger` in the C++ wrapper instead of free functions\n- align naming etc better with the updated approach in #34374\n\nMy apologies for once again a slow follow-up here. I wanted to first figure out my approach in #34374, and that took me much longer than I had anticipated."
  },
  {
   "t": "2026-09-17T11:46:08Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "src/test/kernel/test_kernel.cpp",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": 3395661504,
   "text": "[quoted text omitted]\n\nYeah, this seems like the most elegant approach to me. In fact, I think it makes sense to not expose the free logging functions at all in the wrapper. The `Logger` class should offer all required functionality, in a way that is much harder to abuse.\n\nThank you both for your ideas and suggestions. I've updated the PR with this approach."
  },
  {
   "t": "2026-09-17T11:46:35Z",
   "kind": "review_comment",
   "who": "stickies-v",
   "assoc": "MEMBER",
   "path": "src/kernel/bitcoinkernel_wrapper.h",
   "commit": "dafe5eec14f896b7a431e255aeb8915aa21ede7b",
   "in_reply_to": 3395677816,
   "text": "I agree, but this is no longer relevant in the latest version as per https://github.com/bitcoin/bitcoin/pull/34775#discussion_r4036445255."
  }
 ],
 "labels_log": [
  {
   "t": "2026-03-09T08:35:39Z",
   "action": "labeled",
   "label": "Validation",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 8469,
 "text_tokens_estimate": 2117,
 "changed_paths": [
  "src/kernel/bitcoinkernel.cpp",
  "src/kernel/bitcoinkernel.h",
  "src/kernel/bitcoinkernel_wrapper.h",
  "src/test/kernel/test_kernel.cpp",
  "test/sanitizer_suppressions/valgrind.supp"
 ],
 "files": [
  {
   "path": "src/kernel/bitcoinkernel.cpp",
   "add": 37,
   "del": 12
  },
  {
   "path": "src/kernel/bitcoinkernel.h",
   "add": 22,
   "del": 41
  },
  {
   "path": "src/kernel/bitcoinkernel_wrapper.h",
   "add": 27,
   "del": 7
  },
  {
   "path": "src/test/kernel/test_kernel.cpp",
   "add": 12,
   "del": 6
  },
  {
   "path": "test/sanitizer_suppressions/valgrind.supp",
   "add": 7,
   "del": 0
  }
 ],
 "test_lines": 25,
 "git": {
  "head": "f40aeb12ed85201b0127317a9bb1bf6cdb258eab",
  "head_matches_backup": true,
  "base": "d32a515fb0bbe7ce5be723ff37e532a8220bc3ce",
  "commits": [
   {
    "sha": "f40aeb12ed",
    "subject": "kernel: make logging callback global",
    "files": 5,
    "add": 105,
    "del": 66
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "a5b01afa90edcc78",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}