{
 "number": 34730,
 "repo": "bitcoin/bitcoin",
 "url": "https://github.com/bitcoin/bitcoin/pull/34730",
 "title": "util/log: Combine the warning/error log levels into a single alert level",
 "author": "ajtowns",
 "author_association": "CONTRIBUTOR",
 "created_at": "2026-03-04T12:03:15Z",
 "updated_at": "2026-07-21T01:29:58Z",
 "age_days": 197,
 "draft": true,
 "labels": [
  "Needs rebase"
 ],
 "milestone": null,
 "base": "master",
 "head_sha": "4ce720ba8738b480fbd9244776ce1c7b01fc591a",
 "head_ref": "202603-logalert",
 "head_repo": "ajtowns/bitcoin",
 "head_history": [],
 "additions": 63,
 "deletions": 57,
 "changed_files": 7,
 "commit_count": 2,
 "size_bucket": "M",
 "mergeable_state": "dirty",
 "bot": {
  "drahtbot": {
   "present": true,
   "reviews": {
    "ack": [
     {
      "login": "ryanofsky",
      "url": "https://github.com/bitcoin/bitcoin/pull/34730#pullrequestreview-3906010759"
     }
    ]
   },
   "conflicts": [
    {
     "number": 34865,
     "title": "logging: better use of log::Entry internally",
     "author": "stickies-v"
    },
    {
     "number": 34778,
     "title": "logging: rewrite macros to add ratelimit option, avoid unused strprintf, clarify confusing errors",
     "author": "ryanofsky"
    },
    {
     "number": 30361,
     "title": "doc: Drop description of LogError messages as fatal",
     "author": "ryanofsky"
    },
    {
     "number": 30343,
     "title": "wallet, logging: Replace WalletLogPrintf() with LogInfo()",
     "author": "ryanofsky"
    },
    {
     "number": 29256,
     "title": "log, refactor: Allow log macros to accept context arguments",
     "author": "ryanofsky"
    }
   ]
  }
 },
 "acks_parsed": {
  "ryanofsky": {
   "kind": "ack",
   "hash": "4ce720ba8738b480fbd9244776ce1c7b01fc591a",
   "t": "2026-03-06T21:00:00Z",
   "stale": false
  }
 },
 "acks_tally": {
  "ack": 1,
  "stale_ack": 0,
  "concept_ack": 0,
  "approach_ack": 0,
  "nack": 0,
  "concept_nack": 0,
  "approach_nack": 0
 },
 "reviews": {
  "approved": 1,
  "changes_requested": 0,
  "distinct_reviewers": [
   "ryanofsky"
  ]
 },
 "signals": {
  "needs_rebase": true,
  "ci_failed": false,
  "mergeable_state": "dirty",
  "last_author_activity": "2026-03-04T12:04:30Z",
  "last_reviewer_activity": "2026-03-06T21:00:00Z",
  "last_reviewer": "ryanofsky",
  "author_silent_days": 197,
  "waiting_on_author_days": 194,
  "days_since_update": 58
 },
 "refs": {
  "mentioned": [
   30348,
   30364,
   34038
  ],
  "depends_on": [],
  "fixes": [],
  "linked_issues": [],
  "references": [
   {
    "number": 34038,
    "type": "pull",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "logging: replace -loglevel with -trace, expose trace logging via RPC"
   },
   {
    "number": 30348,
    "type": "issue",
    "state": "open",
    "merged": false,
    "merged_at": null,
    "title": "RFC: Misused LogError and LogWarning macros"
   },
   {
    "number": 30364,
    "type": "pull",
    "state": "closed",
    "merged": false,
    "merged_at": null,
    "title": "logging: Replace LogError and LogWarning with LogAlert"
   }
  ],
  "conflicts": [
   34865,
   34778,
   30361,
   30343,
   29256
  ]
 },
 "stack": {
  "shares_commits_with": [],
  "based_on": [],
  "base_for": []
 },
 "review_paths": [],
 "body": "There's little benefit in having two error levels that the node operator should pay attention to when the only difference between them is that one means the node is about to shut down -- the admin can easily see that just by looking at whether the node did shutdown. So this PR replaces LogWarning and LogError with LogAlert, which hopefully emphasises that the point of using that level is to alert the node operator.\n\nLeaves LogWarning and LogError available as deprecated aliases to reduce code churn and avoid invalidating PRs.\n\nLeft as draft pending #34038 as the \"warning\" and \"error\" levels are currently exposed to users via the `-loglevel` config option.",
 "commits": [
  {
   "sha": "7113b17d8586f22a4df5e4cf4a2b3b159c229cef",
   "date": "2026-03-04T10:46:44Z",
   "message": "util/log: Replace LogWarning/LogError with LogAlert"
  },
  {
   "sha": "4ce720ba8738b480fbd9244776ce1c7b01fc591a",
   "date": "2026-03-04T11:41:36Z",
   "message": "scripted-diff: Convert node/blockstorage.cpp to LogAlert\n\n-BEGIN VERIFY SCRIPT-\nsed -i 's/LogWarning(/LogAlert(/g; s/LogError(/LogAlert(/g; s/\\(LogAlert(\"[^\\\"]*\\)\\\\n\\(\"[,)]\\)/\\1\\2/g' src/node/blockstorage.cpp\n-END VERIFY SCRIPT-"
  }
 ],
 "timeline": [
  {
   "t": "2026-03-04T12:04:30Z",
   "kind": "comment",
   "who": "ajtowns",
   "assoc": "CONTRIBUTOR",
   "text": "Previous discussion: #30348 and #30364"
  },
  {
   "t": "2026-03-06T21:00:00Z",
   "kind": "review",
   "who": "ryanofsky",
   "assoc": "CONTRIBUTOR",
   "state": "APPROVED",
   "commit": "4ce720ba8738b480fbd9244776ce1c7b01fc591a",
   "text": "Code review ACK 4ce720ba8738b480fbd9244776ce1c7b01fc591a. Concept -0.\n\nThis PR is definitely not the change I would make, but it seems fine and helps decrease the gap between way the macros are actually used and the way they were originally intended to be used.\n\nIMO, a more ideal solution would:\n\n1. Keep the error and warning levels instead of removing them, because `[error]` `[warning]` tags shown in log output are helpful for distinguishing actual problems from potential problems from informational messages.\n2. Make error and warning log levels conditional (users can configure whether messages are logged) instead of unconditional.\n3. Introduce a new \"critical\" level and `LogCritical` macro which is unconditional and always logs even when debug logging is turned off. To me \"critical\" sounds more negative and \"alert\" sounds more fake like \"Alert! Walmart's prices are lower than competitors\". But obviously the word choice is not important."
  }
 ],
 "labels_log": [
  {
   "t": "2026-04-23T12:40:35Z",
   "action": "labeled",
   "label": "Needs rebase",
   "who": "DrahtBot"
  }
 ],
 "state_log": [],
 "text_chars": 2008,
 "text_tokens_estimate": 502,
 "changed_paths": [
  "doc/developer-notes.md",
  "src/logging.cpp",
  "src/node/blockstorage.cpp",
  "src/test/logging_tests.cpp",
  "src/util/log.h",
  "test/functional/feature_coinstatsindex_compatibility.py",
  "test/functional/feature_config_args.py"
 ],
 "files": [
  {
   "path": "doc/developer-notes.md",
   "add": 9,
   "del": 9
  },
  {
   "path": "src/logging.cpp",
   "add": 9,
   "del": 9
  },
  {
   "path": "src/node/blockstorage.cpp",
   "add": 24,
   "del": 24
  },
  {
   "path": "src/test/logging_tests.cpp",
   "add": 12,
   "del": 8
  },
  {
   "path": "src/util/log.h",
   "add": 6,
   "del": 4
  },
  {
   "path": "test/functional/feature_coinstatsindex_compatibility.py",
   "add": 1,
   "del": 1
  },
  {
   "path": "test/functional/feature_config_args.py",
   "add": 2,
   "del": 2
  }
 ],
 "test_lines": 26,
 "git": {
  "head": "4ce720ba8738b480fbd9244776ce1c7b01fc591a",
  "head_matches_backup": true,
  "base": "17a04039bc5befd51c2f96daf081e9e4a8ed7bff",
  "commits": [
   {
    "sha": "7113b17d85",
    "subject": "util/log: Replace LogWarning/LogError with LogAlert",
    "files": 6,
    "add": 39,
    "del": 33
   },
   {
    "sha": "4ce720ba87",
    "subject": "scripted-diff: Convert node/blockstorage.cpp to LogAlert",
    "files": 1,
    "add": 24,
    "del": 24
   }
  ],
  "patch_truncated": false
 },
 "input_hash": "6bfe6bd759060166",
 "extracted_at": "2026-09-17T16:15:31+00:00"
}