Skip to content

Implement log breakpoints#1086

Merged
lionel- merged 4 commits intomainfrom
feature/log-breakpoints
Mar 8, 2026
Merged

Implement log breakpoints#1086
lionel- merged 4 commits intomainfrom
feature/log-breakpoints

Conversation

@lionel-
Copy link
Copy Markdown
Contributor

@lionel- lionel- commented Mar 5, 2026

Branched from #1064.
Addresses posit-dev/positron#12360

Adds support for DAP log breakpoints (logpoints). When a breakpoint has a log message template instead of (or in addition to) a condition, it evaluates the template at hit time, prints the result to the debug console, and does not stop execution. This is the DAP "logpoint" feature.

The log message template uses {expression} placeholders for interpolation, as mandated by the DAP spec. On the R side, interpolation is handled by glue::glue() if we detect a { character. This fails actionnably (message in Console output) if glue is not installed. If there is no { character, the template is returned as is, allowing simple messages to work without the glue dependency.

Log breakpoints respect conditions: if a breakpoint has both a condition and a log message, the condition is evaluated first and the log message only fires when the condition is met. This naturally extends to hit-count breakpoints in the future (see #1087).

Output is emitted through the same emit_breakpoint_output path as conditional breakpoints, using the ```breakpoint fenced block with a clickable file link. When there's no condition, the condition header line (#> ...) is omitted and only the log message content is shown.

Screenshot 2026-03-05 at 10 43 18

With an error we get:

Screenshot 2026-03-05 at 10 55 23

QA Notes

Tested on the backend side.

To test manually:

foo <- function(x) {
  y <- x * 2
  y + 1
}
for (i in 1:5) {
  foo(i)
}
  1. Set a log breakpoint on y <- x * 2 with message x is {x}, y will be {x * 2}. Run the loop — should see 5 log messages in the console without stopping.
  2. Add a condition x > 3 to the same log breakpoint. Run the loop — should only see messages for x = 4 and x = 5.
  3. Try a log message referencing a nonexistent variable like {nonexistent}: should show an inline error without stopping.
  4. Without glue installed: a log message without glue syntax like checkpoint reached should work. A log message with glue syntax should fail actionably (error in console output).

Comment thread crates/ark/src/dap/dap.rs
@@ -74,6 +74,10 @@ pub struct Breakpoint {
/// We keep this as a string instead of a parsed expression for safety,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something seems to not work right in untitled files. It works if I actually save the file. The main annoying thing is that it looks active

Screen.Recording.2026-03-06.at.4.12.29.PM.mov

Copy link
Copy Markdown
Contributor Author

@lionel- lionel- Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a general pre-existing issue with breakpoints due to the default way breakpoints look like in the frontend. We don't get breakpoint events with untitiled files.

Comment thread crates/ark/src/modules/positron/eval.R
Comment thread crates/ark/src/dap/dap.rs Outdated
Comment thread crates/ark/src/dap/dap.rs Outdated
Comment on lines +655 to +657
pub(crate) fn get_breakpoint(&self, uri: &Url, id: i64) -> Option<&Breakpoint> {
let (_, breakpoints) = self.breakpoints.get(uri)?;
let bp = breakpoints.iter().find(|bp| bp.id == id)?;
Some((bp.line, bp.condition.as_deref()?))
breakpoints.iter().find(|bp| bp.id == id)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems much nicer!

@lionel- lionel- force-pushed the feature/conditional-breakpoints branch from 04a5d55 to 8228f28 Compare March 8, 2026 17:03
@lionel- lionel- force-pushed the feature/log-breakpoints branch from 1fb6c9b to 48fb3aa Compare March 8, 2026 17:15
Base automatically changed from feature/conditional-breakpoints to main March 8, 2026 20:39
@lionel- lionel- force-pushed the feature/log-breakpoints branch from 04f45bb to 22a9677 Compare March 8, 2026 20:40
@lionel- lionel- merged commit 7583268 into main Mar 8, 2026
9 checks passed
@lionel- lionel- deleted the feature/log-breakpoints branch March 8, 2026 20:40
@github-actions github-actions Bot locked and limited conversation to collaborators Mar 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants