{
 "number": 35355,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/35355",
 "title": "Use atomics for determining whether trace logging is enabled",
 "author": "ajtowns",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-05-22T00:56:36Z",
 "updated_at": "2026-06-22T14:11:29Z",
 "age_days": 118,
 "draft": true,
 "labels": [
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "10e63dbb62149f1991d4eeb6076a9e9d9748a3ef",
 "head_ref": "202512-log-atomic",
 "head_repo": "ajtowns/bitcoin",
 "head_history": [
  {
   "t": "2026-05-22T03:12:14Z",
   "sha": "10e63dbb62149f1991d4eeb6076a9e9d9748a3ef"
  }
 ],
 "additions": 347,
 "deletions": 320,
 "changed_files": 24,
 "commit_count": 12,
 "size_bucket": "L",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {},
   "conflicts": [
    {
     "number": 35387,
     "title": "logging: make trace logging easily usable",
     "author": "ryanofsky"
    },
    {
     "number": 35322,
     "title": "logging: streamline Logger state and drop redundant methods",
     "author": "ryanofsky"
    },
    {
     "number": 35182,
     "title": "Replace libevent with our own HTTP and socket-handling implementation",
     "author": "pinheadmz"
    },
    {
     "number": 34778,
     "title": "logging: rewrite macros to enforce restrictions at compile-time, improve efficiency and usability",
     "author": "ryanofsky"
    },
    {
     "number": 34411,
     "title": "[POC] Full Libevent removal",
     "author": "fanquake"
    },
    {
     "number": 33847,
     "title": "kernel: Improve logging API",
     "author": "ryanofsky"
    },
    {
     "number": 33646,
     "title": "log: check fclose() results and report safely in logging.cpp",
     "author": "cedwies"
    },
    {
     "number": 29256,
     "title": "log, refactor: Allow log macros to accept context arguments",
     "author": "ryanofsky"
    },
    {
     "number": 19461,
     "title": "multiprocess: Add bitcoin-gui -ipcconnect option",
     "author": "ryanofsky"
    },
    {
     "number": 19460,
     "title": "multiprocess: Add bitcoin-wallet -ipcconnect option",
     "author": "ryanofsky"
    },
    {
     "number": 10102,
     "title": "Multiprocess bitcoin",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {},
 "acks_tally": {
  "ack": 0,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 0,
  "changes_requested": 0,
  "distinct_reviewers": []
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-05-22T03:12:14Z",
  "last_reviewer_activity": null,
  "last_reviewer": null,
  "author_silent_days": 118,
  "waiting_on_author_days": 0,
  "days_since_update": 87
 },
 "refs": {
  "mentioned": [
   28318,
   34038,
   34806,
   35322
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 28318,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2024-01-10",
    "title": "logging: Simplify API for level based logging"
   },
   {
    "number": 34038,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "logging: replace -loglevel with -trace, expose trace logging via RPC"
   },
   {
    "number": 34806,
    "type": "pull",
    "state": "closed",
    "merged": true,
    "merged_at": "2026-05-22",
    "title": "refactor: logging: Various API improvements"
   },
   {
    "number": 35322,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "logging: streamline Logger state and drop redundant methods"
   }
  ],
  "conflicts": [
   35387,
   35322,
   35182,
   34778,
   34411,
   33847,
   33646,
   29256,
   19461,
   19460,
   10102
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [],
 "body": "Followup of #28318, #34038, and #34806 to simplify and optimize the logging-disabled path for `LogTrace()`.\n\nRemoves the global log level (`m_log_level`) and the unordered_map from category to level (`m_category_log_levels`) in favour of a single `atomic<uint64_t> m_trace_categories`, and reduces `ShouldDebugLog` and `ShouldTraceLog` to lock-free checks on a single atomic. Also makes `Enabled()` lock-free, to waste a little less time in the case where debugging is completely disabled.\n\nDoes a bit of clean up as well:\n * guards `m_file_path` and provides accessors\n * makes other configuration variables atomic, rather than \"write-before-createing-threads-then-treat-as-read-only\"\n * consolidates duplicated functions (SetCategoryLogLevel, Enable/Trace/DisableCategory, WillLogCategory)",
 "commits": [
  {
   "sha": "d8b6710a03957afa784fd1437d5f5bbd9e6dbd61",
   "date": "2026-05-22T03:10:04Z",
   "message": "logging: replace -loglevel arg with -trace\n\nPreviously, trace logging for a category was enabled by saying \"-debug=net\n-loglevel=net:trace\" and saying \"-loglevel=net:trace\" (without \"-debug\"\nor \"-debug=net\") would silently do nothing. Simplify this so that\n\"-debug=net\" enables debug logging for net and \"-trace=net\" enables\nboth debug and trace logging for net.\n\nNote that \"-nodebug\" and \"-notrace\" only disable previous \"-debug=xxx\" and\n\"-trace=yyy\" arguments, so \"-debug=mempool -trace=net -nodebug\" will cancel\n\"-debug=mempool\", but will still include both debug and trace logs for net."
  },
  {
   "sha": "7af81b5d384db5dce8655cc96aad2bf922ee0460",
   "date": "2026-05-22T03:10:05Z",
   "message": "rpc: Update logging RPC to support trace level debugging\n\nAlso changes the output format, to distinguish debug/trace levels.\nProvides `-deprecatedrpc=logging` if old output format is needed.\n\nCo-Authored-By: stickies-v <stickies-v@protonmail.com>"
  },
  {
   "sha": "77ac0f81cd90234667ef7a2b7c05d53fb1239bd2",
   "date": "2026-05-22T03:10:05Z",
   "message": "[doc] Release notes for user-visible logging changes"
  },
  {
   "sha": "810352a39047253524b0accdc35bb05bbdbde141",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: replace global and category log levels with atomic int\n\nSince we have reduced how much log levels can be configured (error,\nwarning and info are always logged; and only debug and trace levels can\nbe disabled), we only need two bits per category to store the information.\nWe can do this with two atomic ints, one for whether -debug is enabled,\nand the other for whether -trace is enabled.\n\nThis allows `WillLogCategoryLevel` to avoid taking a mutex, potentially\nallowing for better performance in the event that multiple threads are\nrunning many LogDebug(..) statements over categories that do not have\n-debug enabled (or LogTrace/-trace)."
  },
  {
   "sha": "54313169677dbdedb5736635a5f17d71277d1a9f",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: Make sure BCLog::Logger members are atomic or guarded"
  },
  {
   "sha": "787f095f0cbb8203647d75f746cc3be7fb08c0ac",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: Make Enabled() lock-free\n\nAdd m_any_print_callbacks as a cache for !m_print_callbacks.empty(),\nand make m_buffered atomic. Makes the Log functions almost completely\nfree when logging is completely disabled (though unlike for LogDebug\nwhen the category is disabled, arguments are still evaluated)."
  },
  {
   "sha": "b9b9d8ca335cbf3c111584808a913251848f2ae5",
   "date": "2026-05-22T03:11:08Z",
   "message": "[move-only] logging: Move Logger member variables together"
  },
  {
   "sha": "4f259fd04c14df3f857b23d656eb3d635ca982a9",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: Drop unused SetCategoryLogLevel(str,str)"
  },
  {
   "sha": "60dacd0db50fd40d65402b761682fa82b796b751",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: Replace Enable/Trace/DisableCategory(str) with SetCategoryLogLevel(str, level)"
  },
  {
   "sha": "52f90febd5b7f672f8b14ecd61c9153988e6f5a2",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: Drop Enable/Trace/DisableCategory aliases"
  },
  {
   "sha": "84dc8e422302643a1bf96e384c2a116ee509df57",
   "date": "2026-05-22T03:11:08Z",
   "message": "logging: Drop WillLogCategory* in favour of Logger::ShouldDebugLog and ShouldTraceLog"
  },
  {
   "sha": "10e63dbb62149f1991d4eeb6076a9e9d9748a3ef",
   "date": "2026-05-22T03:11:08Z",
   "message": "util/log.h: Move internal functions into detail namespace"
  }
 ],
 "timeline": [
  {
   "t": "2026-05-22T01:00:37Z",
   "kind": "comment",
   "who": "ajtowns",
   "assoc": "CONTRIBUTOR",
   "text": "I first mentioned this three years ago at https://github.com/bitcoin/bitcoin/pull/25203#issuecomment-1401126785 and had originally included it in https://github.com/bitcoin/bitcoin/pull/28318#issuecomment-1701211340 . This branch was also linked to in https://github.com/bitcoin/bitcoin/pull/34038#discussion_r2735011334 Obviously conflicts with #35322."
  },
  {
   "t": "2026-05-22T03:12:14Z",
   "kind": "force_push",
   "who": "ajtowns",
   "commit": "10e63dbb62149f1991d4eeb6076a9e9d9748a3ef"
  }
 ],
 "labels_log": [
  {
   "t": "2026-05-22T04:01:10Z",
   "action": "labeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-05-22T13:27:13Z",
   "action": "unlabeled",
   "label": "CI failed",
   "who": "DrahtBot"
  },
  {
   "t": "2026-06-22T14:11:28Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 3506,
 "text_tokens_estimate": 876,
 "changed_paths": [
  "doc/developer-notes.md",
  "doc/release-notes-34038.md",
  "src/bench/logging.cpp",
  "src/bitcoind.cpp",
  "src/httpserver.cpp",
  "src/init.cpp",
  "src/init/common.cpp",
  "src/init/common.h",
  "src/kernel/bitcoinkernel.cpp",
  "src/logging.cpp",
  "src/logging.h",
  "src/node/abort.cpp",
  "src/qt/guiutil.cpp",
  "src/rpc/client.cpp",
  "src/rpc/node.cpp",
  "src/rpc/server.cpp",
  "src/test/i2p_tests.cpp",
  "src/test/logging_tests.cpp",
  "src/test/util/setup_common.cpp",
  "src/util/log.h",
  "src/wallet/sqlite.cpp",
  "test/functional/feature_logging.py",
  "test/functional/rpc_misc.py",
  "test/functional/test_framework/test_node.py"
 ],
 "files": [
  {
   "path": "doc/developer-notes.md",
   "add": 4,
   "del": 5
  },
  {
   "path": "doc/release-notes-34038.md",
   "add": 13,
   "del": 0
  },
  {
   "path": "src/bench/logging.cpp",
   "add": 3,
   "del": 3
  },
  {
   "path": "src/bitcoind.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/httpserver.cpp",
   "add": 2,
   "del": 2
  },
  {
   "path": "src/init.cpp",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/init/common.cpp",
   "add": 23,
   "del": 30
  },
  {
   "path": "src/init/common.h",
   "add": 0,
   "del": 1
  },
  {
   "path": "src/kernel/bitcoinkernel.cpp",
   "add": 4,
   "del": 7
  },
  {
   "path": "src/logging.cpp",
   "add": 44,
   "del": 84
  },
  {
   "path": "src/logging.h",
   "add": 67,
   "del": 61
  },
  {
   "path": "src/node/abort.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/qt/guiutil.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/rpc/client.cpp",
   "add": 2,
   "del": 0
  },
  {
   "path": "src/rpc/node.cpp",
   "add": 64,
   "del": 25
  },
  {
   "path": "src/rpc/server.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "src/test/i2p_tests.cpp",
   "add": 6,
   "del": 4
  },
  {
   "path": "src/test/logging_tests.cpp",
   "add": 40,
   "del": 56
  },
  {
   "path": "src/test/util/setup_common.cpp",
   "add": 1,
   "del": 2
  },
  {
   "path": "src/util/log.h",
   "add": 10,
   "del": 6
  },
  {
   "path": "src/wallet/sqlite.cpp",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/feature_logging.py",
   "add": 37,
   "del": 22
  },
  {
   "path": "test/functional/rpc_misc.py",
   "add": 18,
   "del": 5
  },
  {
   "path": "test/functional/test_framework/test_node.py",
   "add": 4,
   "del": 1
  }
 ],
 "test_lines": 202,
 "git": {
  "head": "10e63dbb62149f1991d4eeb6076a9e9d9748a3ef",
  "head_matches_backup": true,
  "base": "735b1cf4311de81cc6877a9c2efc082e861ef8d5",
  "commits": [
   {
    "sha": "d8b6710a03",
    "subject": "logging: replace -loglevel arg with -trace",
    "files": 12,
    "add": 110,
    "del": 87
   },
   {
    "sha": "7af81b5d38",
    "subject": "rpc: Update logging RPC to support trace level debugging",
    "files": 6,
    "add": 144,
    "del": 46
   },
   {
    "sha": "77ac0f81cd",
    "subject": "[doc] Release notes for user-visible logging changes",
    "files": 1,
    "add": 13,
    "del": 0
   },
   {
    "sha": "810352a390",
    "subject": "logging: replace global and category log levels with atomic int",
    "files": 5,
    "add": 71,
    "del": 138
   },
   {
    "sha": "5431316967",
    "subject": "logging: Make sure BCLog::Logger members are atomic or guarded",
    "files": 8,
    "add": 36,
    "del": 20
   },
   {
    "sha": "787f095f0c",
    "subject": "logging: Make Enabled() lock-free",
    "files": 2,
    "add": 11,
    "del": 4
   },
   {
    "sha": "b9b9d8ca33",
    "subject": "[move-only] logging: Move Logger member variables together",
    "files": 1,
    "add": 32,
    "del": 22
   },
   {
    "sha": "4f259fd04c",
    "subject": "logging: Drop unused SetCategoryLogLevel(str,str)",
    "files": 3,
    "add": 1,
    "del": 32
   },
   {
    "sha": "60dacd0db5",
    "subject": "logging: Replace Enable/Trace/DisableCategory(str) with SetCategoryLogLevel(str, level)",
    "files": 4,
    "add": 14,
    "del": 49
   },
   {
    "sha": "52f90febd5",
    "subject": "logging: Drop Enable/Trace/DisableCategory aliases",
    "files": 5,
    "add": 9,
    "del": 13
   },
   {
    "sha": "84dc8e4223",
    "subject": "logging: Drop WillLogCategory* in favour of Logger::ShouldDebugLog and ShouldTraceLog",
    "files": 4,
    "add": 11,
    "del": 18
   },
   {
    "sha": "10e63dbb62",
    "subject": "util/log.h: Move internal functions into detail namespace",
    "files": 1,
    "add": 10,
    "del": 6
   }
  ],
  "patch_truncated": true
 },
 "input_hash": "3d881436fb5735d3",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}