Build1 publisher2 min readPublished
IntelliJ IDEA 2026.2 changes the log expression on a running server without a redeploy
JetBrains' walkthrough finds a discount bug in a containerised gRPC server by attaching a debugger on port 5005 and editing log expressions between requests. Those expressions run inside the server's VM.
The Engineer · Build desk

What happened
- JetBrains' walkthrough debugs a gRPC quote server that answers a JetBrains EMEA request with price=100.00 USD and discount_bps=0 where the expected answer is 80.00 USD and discount_bps=2000.
- The server is never started from a local debug session; it listens for debugger connections, and the project supplies a GrpcQuoteServer attach run configuration to reach it.
- In IntelliJ IDEA 2026.2 a logpoint is set by clicking the gutter between any two executable lines and entering the expression to log.
- JetBrains says the 2026.2 release removes debugger-introduced overhead through instrumentation, while heavy logging expressions may still take time to execute.
- The chain of logpoints ended at discountBpsFor, where the console showed the tenant arriving as JetBrains when jetbrains was expected and the discount block never being entered.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- capability Ruling out a suspicion now costs one gutter edit, and the answer arrives with the next request the client loop sends, so hypotheses are paced by traffic and not by builds.
- cost Every expression a developer types costs the server process under diagnosis, and the 2026.2 instrumentation only removes the debugger's own overhead.
- constraint The technique only reaches processes that will accept a debugger connection over a socket, so a deployment's port and agent policy decides whether logpoints are available at all.
- decision Whether this helps during a real incident is settled long before it, when someone chooses whether the deployed image ships a debug port at all.
The gap between the two console lines is the discount itself. Two thousand basis points is 20 percent, and 20 percent off 100.00 USD leaves 80.00 USD, so a reply carrying price=100.00 and discount_bps=0 means the rule never fired [2][3][4].
A logpoint does not suspend the program. It evaluates an expression at the line and prints the result to the console [5]. JetBrains calls logpoints the feature with the biggest return for someone new to its debugging tools [18]. The walkthrough's first one sits at QuoteEndpoint:12, the top of the query handling method, and every incoming request then prints EMEA JetBrains [7]. With a println you edit the source, rebuild, and redeploy to get that line; a logpoint changes in place [5]. The bundled GrpcQuoteClientLoop configuration keeps querying the server, so an edited expression shows up on the next request in [13][14]. JetBrains describes the loop as querying periodically without saying how often [19].
The server is reachable because it listens for debugger connections [10]. The project's Dockerfile exposes the listening and debug ports, and the documented command publishes both with -p 50051:50051 -p 5005:5005 [12]. "For the debugger, there is no difference whether the process runs locally, in a separate environment, or on a remote host," JetBrains wrote, because "the communication happens over a socket" [11].
The expression runs in the target process, not in the IDE. "Beware of heavy computations in hot paths," the post said. "They are executed in the same VM and are not magically free" [8]. JetBrains says working with logpoints is as simple as debugging with plain println statements [20]. That comparison holds when the expression is cheap next to the request that triggers it, because the 2026.2 instrumentation removes the debugger's overhead while the expression still costs whatever it costs [9].
The chain ends in a one-line fix: discountBpsFor compares with "jetbrains".equalsIgnoreCase(tenant) and returns 2_000 [16]. When the output leaves you unsure which line produced it, clicking the console line navigates to the logpoint or the code [17].
The walkthrough demonstrates the attach-and-edit loop against a process the developer never launched [10]. The bug is deterministic, and Docker stands in for the other environment [12]. For a failure that only appears under real traffic, the same session needs a JVM that accepts a debugger connection on a port you can reach. The example arranges that in its own Dockerfile [12].
What to watch
- Whether JetBrains publishes measured overhead for a logpoint sitting on a per-request path.
- Which expressions the 2026.2 instrumentation cannot cover, and what they cost when it falls back to ordinary debugger evaluation.
- Whether the gutter-click flow gets documented for JVMs reached through a bastion or a port-forward rather than a published container port.