Mastering VS Code Debugging: Conditional Breakpoints & Logpoints
Stop using console.log! Learn how to use VS Code conditional breakpoints and logpoints to trace code execution without stopping your app's flow.
We’ve all been there: chasing a bug that only triggers under specific, rare conditions. Your first instinct is usually to sprinkle console.log statements throughout your functions, rebuild, and hope you catch the state at the right moment. It’s messy, it clutters your git history, and it’s a massive hit to your developer productivity when you have to clean it all up later.
I stopped doing that about two years ago. Instead, I started relying on VS Code debugging features like conditional breakpoints and logpoints. These tools allow you to inspect the runtime state without altering a single line of your source code.
Why You Should Stop Using console.log
When you hardcode logs, you're modifying the very environment you're trying to debug. If you're working on a high-frequency loop or a complex async chain, console.log can actually change the timing of your execution, potentially masking race conditions.
Using native debugger features keeps your code clean. It also prevents those "oops, I pushed a debug log to production" moments that we’ve all suffered through.
Setting Up Conditional Breakpoints
A standard breakpoint stops execution every time the line is hit. If you're inside a loop that runs 500 times, that’s useless. A conditional breakpoint only pauses execution when a specific expression evaluates to true.
To set one up:
- Right-click in the gutter next to your line number.
- Select Add Conditional Breakpoint.
- Type your expression (e.g.,
user.id === undefinedorcount > 10).
The debugger will ignore the breakpoint until that condition is met. It’s a surgical way to catch state-related bugs without manually stepping through hundreds of iterations.
Tracing with VS Code Logpoints
Sometimes you don't actually need to pause execution; you just need to know what a variable is at a specific point in time. That’s where VS Code logpoints shine. They act like console.log but are injected into the runtime by the debugger itself.
- Right-click the gutter and select Add Logpoint.
- Enter your message in the text box.
- Use curly braces to inject variables:
User data: {user.name} at {new Date().toISOString()}.
The output appears in your Debug Console without ever needing to modify your actual code. It’s a clean, non-intrusive way to track code execution tracing in real-time.
Quick Comparison: Debugging Methods
| Method | Pause Execution? | Code Modified? | Best For |
|---|---|---|---|
| Standard Breakpoint | Yes | No | Investigating a specific line |
| Conditional Breakpoint | Yes | No | Hard-to-reproduce state bugs |
| Logpoint | No | No | Monitoring flow/variables |
console.log | No | Yes | Quick, dirty, and temporary |
Pro-Tips for Better Debugging
If you're working on distributed systems or remote environments, remember that these tools work just as well when you're connected to remote containers. I've found that combining these with VS Code Remote Tunnels for Live Microservices Debugging makes it possible to debug production-like issues without needing a full local environment recreation.
Also, keep your Debug Console clean. If you're running a complex session, right-click the console and clear it periodically so you don't lose track of new logs.
FAQ
Q: Do logpoints affect performance as much as console.log?
A: Generally, no. Since they are handled by the debugger's hook into the engine, they are more efficient and don't require re-compiling or restarting your dev server.
Q: Can I use logpoints in production? A: No. These features require a debugger connection. If you need production-grade observability, look into structured logging frameworks or OpenTelemetry.
Q: My breakpoint isn't hitting. What gives? A: Check your sourcemaps. If your compiled code doesn't map perfectly to your source, the debugger won't know where to pause.
Next time you feel the urge to add a log statement, take thirty seconds to set a logpoint instead. It’s a small shift, but it’ll save you hours of cleanup and help you build a much more disciplined workflow. I’m still figuring out how to better integrate these with automated test suites—if you have a clean way to trigger debugger events from within Jest or Vitest, I’d love to hear how you’re handling it.