@@ -100,6 +100,34 @@ public IActionResult GetStatus()
100100 . ToList ( )
101101 } ) ;
102102 }
103+
104+ /// <summary>
105+ /// Lightweight probe endpoint for latency measurement.
106+ /// </summary>
107+ /// <remarks>
108+ /// <para>
109+ /// <strong>Educational Note:</strong> This endpoint is designed for measuring
110+ /// request processing latency. It does minimal work - just returns a timestamp.
111+ /// During thread pool starvation, even this simple endpoint will show increased
112+ /// latency because the request must wait for a thread pool thread to process it.
113+ /// </para>
114+ /// <para>
115+ /// Compare the response time of this endpoint before and during thread pool
116+ /// starvation to see the dramatic impact on user-perceived performance.
117+ /// </para>
118+ /// </remarks>
119+ /// <response code="200">Returns probe timestamp for latency calculation.</response>
120+ [ HttpGet ( "probe" ) ]
121+ [ ProducesResponseType ( typeof ( ProbeResponse ) , StatusCodes . Status200OK ) ]
122+ public IActionResult Probe ( )
123+ {
124+ return Ok ( new ProbeResponse
125+ {
126+ ServerTimestamp = DateTimeOffset . UtcNow ,
127+ ThreadPoolThreads = ThreadPool . ThreadCount ,
128+ PendingWorkItems = ThreadPool . PendingWorkItemCount
129+ } ) ;
130+ }
103131}
104132
105133/// <summary>
@@ -159,3 +187,31 @@ public class ActiveSimulationSummary
159187 /// </summary>
160188 public int RunningDurationSeconds { get ; init ; }
161189}
190+
191+ /// <summary>
192+ /// Response from the latency probe endpoint.
193+ /// </summary>
194+ /// <remarks>
195+ /// <para>
196+ /// <strong>Educational Note:</strong> This response includes thread pool information
197+ /// to help correlate latency with thread pool state. During starvation, you'll see
198+ /// high pending work items and latency increasing together.
199+ /// </para>
200+ /// </remarks>
201+ public class ProbeResponse
202+ {
203+ /// <summary>
204+ /// Server timestamp when the probe was processed.
205+ /// </summary>
206+ public DateTimeOffset ServerTimestamp { get ; init ; }
207+
208+ /// <summary>
209+ /// Current number of thread pool threads.
210+ /// </summary>
211+ public int ThreadPoolThreads { get ; init ; }
212+
213+ /// <summary>
214+ /// Number of work items waiting in the thread pool queue.
215+ /// </summary>
216+ public long PendingWorkItems { get ; init ; }
217+ }
0 commit comments