Skip to content

Cherrypick diagnostics changes to stable/21.x - #13419

Merged
JDevlieghere merged 8 commits into
swiftlang:stable/21.xfrom
JDevlieghere:lldb-diagnostics-report-21.x
Jul 20, 2026
Merged

Cherrypick diagnostics changes to stable/21.x#13419
JDevlieghere merged 8 commits into
swiftlang:stable/21.xfrom
JDevlieghere:lldb-diagnostics-report-21.x

Conversation

@JDevlieghere

Copy link
Copy Markdown

The first seven are upstream cherry-picks. The last is downstream-only change.

…lvm#206129)

Host::OpenURL was only defined for Darwin (in Host.mm). Add a portable
implementation in the common Host.cpp: on Unix it launches xdg-open; on
Windows it returns "unsupported" for now. xdg-open is run without a
shell (run_in_shell=false) so query-string metacharacters in the URL are
never interpreted by the shell.

Also add Host::URLEncode, an RFC 3986 percent-encoder for assembling
tracker URLs. These are the building blocks for an upcoming "diagnostics
report" command that opens a pre-filled bug URL, and the encoder is
shared with a downstream tap-to-radar reporter.

(cherry picked from commit dbd4528)
The Diagnostics framework had a callback registry (AddCallback /
RemoveCallback) so subsystems could contribute files to a diagnostics
directory, intended to also run during crash handling. That crash-time
path never materialized, and the sole registered callback was the
Debugger copying its file-backed logs. If you had no logging enabled,
the directory would be empty, confusing the users.

Remove the registry and the callback loop in Diagnostics::Create (which
now just writes the in-memory log), and expose the log copying as
Debugger::CopyLogFilesToDirectory, which "diagnostics dump" calls
directly. The dump command now copies the invoking debugger's logs
rather than every debugger's, which is the more useful behavior I want
to double down on.

(cherry picked from commit 9f34f1c)
Nothing in the Utility or Host layers uses Diagnostics. Its only callers
are Debugger (the always-on log feeder), SBDebugger, and the
SystemInitializerCommon lifecycle. Those all live in Core or above. The
header depends only on Utility primitives (FileSpec, Log, Error), and
lldbInitialization already links lldbCore, so the move adds no new link
dependency anywhere.

Relocating it to Core lets Diagnostics reach Debugger, Target,
CommandInterpreter, and Host, which simplifies an upcoming change that
collect a richer diagnostics bundle (statistics, command snapshots,
invocation, etc) and allows us to implement that directly in the
Diagnostics class.

(cherry picked from commit 2ceab13)
…6189)

Add Diagnostics::Collect, which gathers the state a triager needs into a
directory, best-effort (one failed section never sinks the rest): the
always-on log plus the debugger's file logs, statistics.json from
DebuggerStats, and a snapshot of the commands run first when triaging
(target list, image list, thread list, backtraces, image lookup, frame
variable).

It returns a Diagnostics::Report with the LLDB version, host, and how
LLDB was invoked, plus an Attachments holding the bundle directory and
the files written into it. Each file is recorded as it is written, so a
file that could not be created is simply absent from the list. The
report is expected to grow more fields over time.

`diagnostics dump` now calls Collect and prints the report as JSON to
the terminal instead of only reporting where the directory was written.
Here's what this all looks like:

```
(lldb) diagnostics dump
{
  "attachments": {
    "directory": "/var/folders/6b/3sb80ks56rz5vwlhsdvpsxmh0000gn/T/diagnostics-4b5e9f",
    "files": [
      "diagnostics.log",
      "statistics.json",
      "commands.txt"
    ]
  },
  "invocation": "./build/bin/count",
  "os": "arm64-apple-macosx platform=host os=27.0 build=26A374",
  "version": "lldb version 23.0.0git (git@github.com:llvm/llvm-project.git revision 85fa95f)\n  clang revision 85fa95f\n  llvm revision 85fa95f"
}
```

This is in preparation for a future PR which adds the ability to take
all this information and pre-fill a bug report with it.

(cherry picked from commit a873660)
…06578)

Introduce a BugReporter plugin kind that files an assembled
Diagnostics::Report through a pluggable destination, plus a "diagnostics
report" command (aliased "bugreport") that collects the bundle and files
it through the first registered reporter.

CreateBugReporterInstance() returns the first registered reporter, so a
reporter registered earlier wins and a downstream tree can take over by
registering ahead of the built-ins. BugReporterNone is the
always-registered, last-in-order fallback. Its File() returns an error
pointing at LLDB_BUG_REPORT_URL, so the command surfaces "no tracker
configured" through the normal error path instead of special-casing it.

"diagnostics report" writes the bundle, prints a review warning, and
files it unless --no-open is given. The upcoming GitHub reporter, gated
by a CMake option, is the first real destination.

(cherry picked from commit 8cf09c5)
Add a BugReporter plugin that files a diagnostics bundle as an
llvm/llvm-project GitHub issue. File() renders a short Markdown body
from the Diagnostics::Report (version, host, invocation, and a pointer
to the bundle directory to attach), truncates it under a GET-safe URL
length on a UTF-8 character boundary, and opens a pre-filled issues/new
page with Host::OpenURL.

It is gated by LLDB_ENABLE_GITHUB_BUG_REPORTER (default on) and
registers ahead of the no-op fallback, so it is the default destination
for "diagnostics report" while a downstream tree can still register its
own reporter ahead of it.

(cherry picked from commit 1556da0)
Add a hook that lets a subsystem contribute a file to the diagnostics
bundle, without breaking layering and making Core depend on it. A plugin
registers an ArtifactProvider callback and a file name via AddArtifactProvider.
Providers run when a bundle is collected, and each one that yields
content is written into the bundle and recorded in the report's
attachments.

This restores, in a simpler form, the collection point that the removed
Diagnostics callback mechanism offered. The motivating consumer is the
downstream Swift health check, which registers a provider to write its
"swift-healthcheck.log" into the bundle. Unlike the old callback, a
provider does not open or write its own file: it just returns the
contents as a string and Diagnostics handles the rest.

(cherry picked from commit 2120490)
The Swift language plugin added swift-healthcheck.log to the
diagnostics directory through the Diagnostics callback registry, which
the bundle series removed. Port it to the artifact provider mechanism
(llvm#210417): LogChannelSwift returns the health log's contents on demand
and Diagnostics writes the file, so it lands in the bundle's
attachments and the plugin no longer touches the filesystem itself.
@JDevlieghere
JDevlieghere requested a review from a team as a code owner July 17, 2026 21:55
@JDevlieghere

Copy link
Copy Markdown
Author

@swift-ci test

@JDevlieghere

Copy link
Copy Markdown
Author
17:22:37  ======UPDATE FAILURES======
17:22:37  [boringssl] 'git checkout 0226f30467f540a3f62ef48d453f93927da199b6' returned (128) with the following fatal: unable to read tree (0226f30467f540a3f62ef48d453f93927da199b6)

@swift-ci test Windows

@JDevlieghere
JDevlieghere merged commit eefeaf4 into swiftlang:stable/21.x Jul 20, 2026
3 checks passed
@JDevlieghere
JDevlieghere deleted the lldb-diagnostics-report-21.x branch July 20, 2026 00:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants