Pipeline Runtime Observation β€” FlowProxy + RingBufferObserver (v1.52.0)

Make your class partial and the generator emits a FlowProxy β€” always-on tracing via svc.Flow.Process() and single-trace debug via svc.Flow.Debug.Process(). Per-node output values, error types, and elapsed milliseconds for every execution.

Always-on tracing (multiple calls, full ring buffer):

using REslava.Result.Observers;

// Make the class partial β€” FlowProxy is generated automatically:
public partial class OrderService { ... }

var ringBuffer = new RingBufferObserver(capacity: 50);
PipelineObserver.Register(ringBuffer);

var result = svc.Flow.Process(userId, productId);  // wraps the real method

PipelineObserver.Unregister();
ringBuffer.Save();  // β†’ reslava-traces.json in bin/ β€” VSIX Debug panel picks it up

foreach (var trace in ringBuffer.GetTraces())
{
    Console.WriteLine($"{trace.MethodName} β†’ {(trace.IsSuccess ? "βœ“" : "βœ— " + trace.ErrorType)}  ({trace.ElapsedMs}ms)");
    foreach (var node in trace.Nodes)
        Console.WriteLine($"  [{node.Index}] {node.NodeId,-8}: {node.OutputValue}  ({node.ElapsedMs}ms)");
}

Single-trace debug (one call, one trace, auto-saved):

svc.Flow.Debug.Process(userId, productId);
// β†’ reslava-debug-Process.json saved to bin/
// β†’ VSIX file watcher fires β†’ Debug panel opens automatically

The DebugProxy creates its own RingBufferObserver(capacity: 1), captures exactly one execution, and calls Save() in the finally block β€” no manual setup required.

RingBufferObserver API:

var obs = new RingBufferObserver(capacity: 100); // bounded; evicts oldest on overflow
PipelineObserver.Register(obs);
// ... run pipelines ...
var traces = obs.GetTraces();   // snapshot β€” safe to iterate while pipelines run
obs.Clear();                    // reset
obs.Save();                     // β†’ reslava-traces.json (default, VSIX auto-loads)
obs.Save("my-run");             // β†’ reslava-my-run.json
obs.Save("/abs/path/out.json"); // β†’ exact path (not picked up by VSIX watcher)

Scoped registration (test / per-request isolation):

using var _ = PipelineObserver.RegisterScoped(new RingBufferObserver());
// observer is automatically unregistered when the using block exits

VSIX Debug panel β€” β–Ά Debug CodeLens (v1.53.0):

The REslava.Result Extensions VS Code extension adds a β–Ά Debug CodeLens above every .Flow.Debug. call. Clicking it opens the Debug panel β€” trace list, node stepper, and animated replay with diagram node highlight.

The extension watches **/reslava-*.json and opens the panel automatically when any trace file appears. A file picker in the panel header lets you switch between reslava-debug-Process.json, reslava-traces.json, and any custom-named save without closing the panel.

Advanced β€” HTTP endpoint (long-running / remote scenarios):

For apps where file-drop isn't convenient, add REslava.Result.Diagnostics to expose traces over HTTP:

dotnet add package REslava.Result.Diagnostics

For console / worker apps:

using REslava.Result.Diagnostics;

var buffer = new RingBufferObserver();
PipelineObserver.Register(buffer);

using var host = PipelineTraceHost.Start(buffer, port: 5297);
// GET http://localhost:5297/reslava/traces  ← Debug panel polls here

For ASP.NET Core apps:

app.MapResultFlowTraces(buffer);
// or, if you used PipelineObserver.Register above:
app.MapResultFlowTraces(); // auto-reads from PipelineObserver.Current

The default port (5297) matches the VSIX default. Change it via VS Code Settings β†’ resultflow.tracePort.