Skip to content

Commit 4042df5

Browse files
committed
Added AI porting comments
1 parent 4ca8c2a commit 4042df5

21 files changed

+645
-94
lines changed

src/PerfProblemSimulator/Controllers/ConfigController.cs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,42 @@
55
namespace PerfProblemSimulator.Controllers;
66

77
/// <summary>
8-
/// Provides client-side configuration settings.
8+
/// Provides client-side configuration settings to the dashboard UI.
99
/// </summary>
1010
/// <remarks>
11-
/// This controller exposes non-sensitive configuration to the frontend,
12-
/// allowing dynamic customization via Azure App Service environment variables.
11+
/// <para>
12+
/// <strong>PURPOSE:</strong>
13+
/// This controller exposes non-sensitive configuration to the frontend JavaScript,
14+
/// allowing runtime customization without rebuilding the application. This is essential
15+
/// for environments like Azure App Service where environment variables are the primary
16+
/// configuration mechanism.
17+
/// </para>
18+
/// <para>
19+
/// <strong>FEATURE REQUIREMENTS:</strong>
20+
/// <list type="bullet">
21+
/// <item>Return the app title (customizable per deployment)</item>
22+
/// <item>Return optional page footer HTML (for branding/legal notices)</item>
23+
/// <item>All values should have sensible defaults if not configured</item>
24+
/// </list>
25+
/// </para>
26+
/// <para>
27+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
28+
/// <list type="bullet">
29+
/// <item>PHP: Use $_ENV or getenv() to read environment variables</item>
30+
/// <item>Node.js: Use process.env.VARIABLE_NAME</item>
31+
/// <item>Java: Use System.getenv() or Spring @Value annotations</item>
32+
/// <item>Python: Use os.environ.get('VARIABLE_NAME', 'default')</item>
33+
/// <item>Ruby: Use ENV['VARIABLE_NAME'] || 'default'</item>
34+
/// </list>
35+
/// </para>
36+
/// <para>
37+
/// <strong>RELATED FILES:</strong>
38+
/// <list type="bullet">
39+
/// <item>Models/ProblemSimulatorOptions.cs - Configuration model</item>
40+
/// <item>wwwroot/js/dashboard.js - Frontend consumer (fetchConfig function)</item>
41+
/// <item>All HTML pages - Footer display logic</item>
42+
/// </list>
43+
/// </para>
1344
/// </remarks>
1445
[ApiController]
1546
[Route("api/[controller]")]

src/PerfProblemSimulator/Controllers/MetricsController.cs

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,44 @@
66
namespace PerfProblemSimulator.Controllers;
77

88
/// <summary>
9-
/// Controller for retrieving current metrics and health status.
9+
/// REST API endpoints for retrieving current metrics and health status.
1010
/// </summary>
1111
/// <remarks>
1212
/// <para>
13-
/// <strong>Educational Note:</strong>
13+
/// <strong>PURPOSE:</strong>
14+
/// Provides HTTP polling endpoints as an alternative to the real-time SignalR/WebSocket
15+
/// channel. While the dashboard uses SignalR for live updates, these REST endpoints serve:
1416
/// </para>
17+
/// <list type="bullet">
18+
/// <item>External monitoring systems that can't use WebSockets (Azure Monitor, Prometheus scrapers)</item>
19+
/// <item>Scripted health checks (curl, PowerShell, automation pipelines)</item>
20+
/// <item>Manual debugging and testing via browser or API tools</item>
21+
/// <item>Integration with Azure App Service health probes</item>
22+
/// </list>
1523
/// <para>
16-
/// This controller provides REST endpoints for polling metrics.
17-
/// While the dashboard uses SignalR for real-time updates, these endpoints
18-
/// are useful for:
24+
/// <strong>DESIGN DECISION - REST vs SignalR:</strong>
25+
/// The dashboard UI uses SignalR because it needs sub-second updates for visualizing
26+
/// performance problems in real-time. These REST endpoints return cached data (not live
27+
/// calculations) and are suitable for 5-30 second polling intervals.
1928
/// </para>
29+
/// <para>
30+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
2031
/// <list type="bullet">
21-
/// <item>External monitoring systems that can't use WebSockets</item>
22-
/// <item>Scripted health checks (curl, PowerShell, etc.)</item>
23-
/// <item>Debugging and manual testing</item>
24-
/// <item>Integration with Azure App Service health probes</item>
32+
/// <item>PHP: Standard REST controller returning JSON</item>
33+
/// <item>Node.js/Express: app.get('/api/metrics/current', ...)</item>
34+
/// <item>Java/Spring: @RestController with @GetMapping</item>
35+
/// <item>Python/Flask: @app.route('/api/metrics/current')</item>
36+
/// <item>Ruby/Rails: Standard controller action rendering JSON</item>
2537
/// </list>
38+
/// </para>
39+
/// <para>
40+
/// <strong>RELATED FILES:</strong>
41+
/// <list type="bullet">
42+
/// <item>Services/MetricsCollector.cs - Provides the cached metrics data</item>
43+
/// <item>Models/MetricsSnapshot.cs - Data structure returned</item>
44+
/// <item>Hubs/MetricsHub.cs - Real-time alternative (SignalR)</item>
45+
/// </list>
46+
/// </para>
2647
/// </remarks>
2748
[ApiController]
2849
[Route("api/[controller]")]

src/PerfProblemSimulator/Hubs/IMetricsClient.cs

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,42 @@
44
namespace PerfProblemSimulator.Hubs;
55

66
/// <summary>
7-
/// Interface for SignalR metrics client methods.
7+
/// Contract defining real-time messages that can be pushed from server to connected dashboard clients.
88
/// </summary>
99
/// <remarks>
1010
/// <para>
11-
/// <strong>Educational Note:</strong>
11+
/// <strong>PURPOSE:</strong>
12+
/// This interface defines the "server-to-client" message contract for the real-time communication
13+
/// channel. Each method represents a distinct message type that the server can push to browsers.
14+
/// The dashboard JavaScript registers handlers for each message type.
1215
/// </para>
1316
/// <para>
14-
/// This interface defines the methods that can be called on connected clients.
15-
/// SignalR uses this for strongly-typed hub methods, providing compile-time
16-
/// safety instead of magic strings.
17+
/// <strong>MESSAGE TYPES:</strong>
18+
/// <list type="bullet">
19+
/// <item><term>ReceiveMetrics</term><description>Periodic metrics snapshot (CPU, memory, threads) - every 1 second</description></item>
20+
/// <item><term>ReceiveLatency</term><description>Health probe latency measurement - every 1 second</description></item>
21+
/// <item><term>SimulationStarted/Completed</term><description>Simulation lifecycle events (fire-and-forget)</description></item>
22+
/// <item><term>ReceiveSlowRequestLatency</term><description>Slow request completion with queue time breakdown</description></item>
23+
/// <item><term>ReceiveLoadTestStats</term><description>Load test statistics summary - every 60 seconds during load</description></item>
24+
/// </list>
1725
/// </para>
1826
/// <para>
19-
/// When the server calls <c>Clients.All.ReceiveMetrics(snapshot)</c>, SignalR
20-
/// automatically serializes the snapshot and sends it to all connected browsers
21-
/// via WebSockets (or fallback transports).
27+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
28+
/// <list type="bullet">
29+
/// <item>PHP: Not applicable - use REST polling or external WebSocket library</item>
30+
/// <item>Node.js/Socket.io: socket.emit('receiveMetrics', snapshot)</item>
31+
/// <item>Java/Spring: SimpMessagingTemplate.convertAndSend("/topic/metrics", snapshot)</item>
32+
/// <item>Python/Flask-SocketIO: socketio.emit('receive_metrics', snapshot)</item>
33+
/// <item>Ruby/ActionCable: MetricsChannel.broadcast_to(user, snapshot)</item>
34+
/// </list>
35+
/// </para>
36+
/// <para>
37+
/// <strong>RELATED FILES:</strong>
38+
/// <list type="bullet">
39+
/// <item>Hubs/MetricsHub.cs - The hub that sends these messages</item>
40+
/// <item>Services/MetricsBroadcastService.cs - Background service that triggers broadcasts</item>
41+
/// <item>wwwroot/js/dashboard.js - JavaScript handlers for each message type</item>
42+
/// </list>
2243
/// </para>
2344
/// </remarks>
2445
public interface IMetricsClient

src/PerfProblemSimulator/Hubs/MetricsHub.cs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -5,46 +5,52 @@
55
namespace PerfProblemSimulator.Hubs;
66

77
/// <summary>
8-
/// SignalR hub for real-time metrics broadcasting to dashboard clients.
8+
/// WebSocket/SignalR hub for real-time metrics broadcasting to dashboard clients.
99
/// </summary>
1010
/// <remarks>
1111
/// <para>
12-
/// <strong>Educational Note:</strong>
12+
/// <strong>PURPOSE:</strong>
13+
/// Provides a persistent bidirectional communication channel between the server and
14+
/// connected browser clients. This enables real-time dashboard updates without polling.
1315
/// </para>
1416
/// <para>
15-
/// SignalR provides real-time communication between server and browser clients.
16-
/// This hub pushes metrics to all connected dashboard instances automatically.
17+
/// <strong>ALGORITHM:</strong>
18+
/// <list type="number">
19+
/// <item>Browser connects to /hubs/metrics endpoint (WebSocket preferred, with fallbacks)</item>
20+
/// <item>On connect: immediately send current metrics so client doesn't wait for next tick</item>
21+
/// <item>Every 1 second: MetricsBroadcastService pushes metrics to all connected clients</item>
22+
/// <item>On simulation events: push notifications so UI can update status indicators</item>
23+
/// <item>On disconnect: clean up resources (automatic via framework)</item>
24+
/// </list>
1725
/// </para>
1826
/// <para>
19-
/// <strong>How it works:</strong>
20-
/// </para>
21-
/// <list type="number">
22-
/// <item>Browser connects to /hubs/metrics via WebSocket (with fallback)</item>
23-
/// <item>MetricsCollector fires MetricsCollected event every second</item>
24-
/// <item>This hub broadcasts the snapshot to all connected clients</item>
25-
/// <item>Browser JavaScript receives the data and updates charts</item>
27+
/// <strong>WHY REAL-TIME vs POLLING:</strong>
28+
/// <list type="bullet">
29+
/// <item>Sub-second updates are essential for visualizing performance problems as they happen</item>
30+
/// <item>Push-based is more efficient than clients polling every second</item>
31+
/// <item>Connection state enables cleanup when browsers close</item>
32+
/// <item>Transport fallback (WebSocket → SSE → Long Polling) ensures broad compatibility</item>
2633
/// </list>
34+
/// </para>
2735
/// <para>
28-
/// <strong>Why SignalR over polling?</strong>
36+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
37+
/// <list type="bullet">
38+
/// <item>PHP: Use Ratchet or ReactPHP for WebSocket server, or external service like Pusher</item>
39+
/// <item>Node.js: Use Socket.IO - nearly identical concept with io.on('connection', socket => ...)</item>
40+
/// <item>Java/Spring: Use @MessageMapping with SimpMessagingTemplate for WebSocket STOMP</item>
41+
/// <item>Python: Use Flask-SocketIO with @socketio.on('connect') handlers</item>
42+
/// <item>Ruby: Use ActionCable with channel subscriptions</item>
43+
/// </list>
2944
/// </para>
45+
/// <para>
46+
/// <strong>RELATED FILES:</strong>
3047
/// <list type="bullet">
31-
/// <item>
32-
/// <term>Efficiency</term>
33-
/// <description>Single connection, push-based updates</description>
34-
/// </item>
35-
/// <item>
36-
/// <term>Real-time</term>
37-
/// <description>Sub-second latency vs polling intervals</description>
38-
/// </item>
39-
/// <item>
40-
/// <term>Scalability</term>
41-
/// <description>SignalR handles connection management</description>
42-
/// </item>
43-
/// <item>
44-
/// <term>Transport flexibility</term>
45-
/// <description>WebSocket → Server-Sent Events → Long Polling fallback</description>
46-
/// </item>
48+
/// <item>Hubs/IMetricsClient.cs - Message contract (what can be sent to clients)</item>
49+
/// <item>Services/MetricsBroadcastService.cs - Background service that triggers broadcasts</item>
50+
/// <item>wwwroot/js/dashboard.js - JavaScript SignalR client connection</item>
51+
/// <item>Program.cs - Hub endpoint mapping (/hubs/metrics)</item>
4752
/// </list>
53+
/// </para>
4854
/// </remarks>
4955
public class MetricsHub : Hub<IMetricsClient>
5056
{

src/PerfProblemSimulator/Middleware/ProblemEndpointGuard.cs

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,41 @@ namespace PerfProblemSimulator.Middleware;
1010
/// </summary>
1111
/// <remarks>
1212
/// <para>
13-
/// <strong>Educational Note:</strong> This middleware implements a safety mechanism that allows
14-
/// the application to be deployed in production-like environments without the risk of
15-
/// accidentally triggering performance problems. This is a common pattern for feature flags
16-
/// and kill switches in production systems.
13+
/// <strong>PURPOSE:</strong> Implements a "kill switch" pattern that allows deploying the app
14+
/// to production-like environments without risk of accidentally triggering performance problems.
15+
/// This is a common pattern for feature flags and kill switches in production systems.
16+
/// </para>
17+
/// <para>
18+
/// <strong>ALGORITHM:</strong>
19+
/// 1. Check if request path matches guarded prefixes (/api/trigger-*, /api/allocate-*, /api/release-*)
20+
/// 2. If guarded AND DISABLE_PROBLEM_ENDPOINTS=true, return 403 Forbidden with JSON error body
21+
/// 3. Otherwise, pass request to next middleware in pipeline
1722
/// </para>
1823
/// <para>
1924
/// The middleware checks the environment variable at request time, not at startup, which
20-
/// allows for dynamic enabling/disabling without restarting the application. However,
21-
/// for most deployment scenarios, the value would be set at deployment time.
25+
/// allows for dynamic enabling/disabling without restarting the application.
26+
/// </para>
27+
/// <para>
28+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
29+
/// This middleware pattern exists in all major web frameworks:
30+
/// <list type="bullet">
31+
/// <item>PHP/Laravel: Create a middleware class, register in Kernel.php</item>
32+
/// <item>Node/Express: app.use((req, res, next) => { if (blocked) res.status(403).json(...); else next(); })</item>
33+
/// <item>Java/Spring: @Component implementing Filter, check path in doFilter()</item>
34+
/// <item>Python/Flask: @app.before_request decorator, return Response if blocked</item>
35+
/// <item>Ruby/Rails: Rack middleware or before_action in ApplicationController</item>
36+
/// </list>
37+
/// Key concepts to port: RequestDelegate (_next) = next middleware function,
38+
/// InvokeAsync = the filter method, short-circuit by not calling _next.
2239
/// </para>
2340
/// <para>
2441
/// <strong>Azure App Service Note:</strong> In Azure App Service, you can set this
2542
/// environment variable in the Configuration blade under Application Settings.
2643
/// </para>
44+
/// <para>
45+
/// <strong>RELATED FILES:</strong>
46+
/// Program.cs (middleware registration), Models/ErrorResponse.cs (JSON response format)
47+
/// </para>
2748
/// </remarks>
2849
public class ProblemEndpointGuard
2950
{

src/PerfProblemSimulator/Models/DetailedMetrics.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,22 @@ namespace PerfProblemSimulator.Models;
33
/// <summary>
44
/// Detailed CPU metrics for the health status endpoint.
55
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// <strong>PURPOSE:</strong>
9+
/// Provides CPU-specific metrics for the /api/metrics/health endpoint.
10+
/// These values help diagnose whether the application is CPU-bound or I/O-bound.
11+
/// </para>
12+
/// <para>
13+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
14+
/// <list type="bullet">
15+
/// <item>PHP: Use sys_getloadavg() on Linux or exec('wmic cpu') on Windows</item>
16+
/// <item>Node.js: Use os.cpus() and calculate usage from idle/total times</item>
17+
/// <item>Java: Use OperatingSystemMXBean.getProcessCpuLoad()</item>
18+
/// <item>Python: Use psutil.cpu_percent() and psutil.cpu_count()</item>
19+
/// </list>
20+
/// </para>
21+
/// </remarks>
622
public class CpuMetrics
723
{
824
/// <summary>

src/PerfProblemSimulator/Models/MemoryReleaseResult.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,31 @@ namespace PerfProblemSimulator.Models;
33
/// <summary>
44
/// Result of releasing allocated memory blocks.
55
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// <strong>PURPOSE:</strong>
9+
/// Response model for the memory release endpoint. Confirms how much memory was freed
10+
/// and whether garbage collection was triggered. This helps users understand memory
11+
/// management behavior when releasing pressure.
12+
/// </para>
13+
/// <para>
14+
/// <strong>WHY TRACK RELEASED BLOCKS:</strong>
15+
/// <list type="bullet">
16+
/// <item>Confirms the release actually happened (blocks weren't already freed)</item>
17+
/// <item>Shows bytes freed so user can verify expected amount</item>
18+
/// <item>Indicates whether GC was forced (affects timing of actual memory return to OS)</item>
19+
/// </list>
20+
/// </para>
21+
/// <para>
22+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
23+
/// <list type="bullet">
24+
/// <item>PHP: Memory is automatically freed when variables go out of scope</item>
25+
/// <item>Node.js: Set arrays to null and optionally call global.gc() if --expose-gc flag set</item>
26+
/// <item>Java: Clear references and call System.gc() (advisory)</item>
27+
/// <item>Python: del references and call gc.collect()</item>
28+
/// </list>
29+
/// </para>
30+
/// </remarks>
631
public class MemoryReleaseResult
732
{
833
/// <summary>

src/PerfProblemSimulator/Models/ProblemSimulatorOptions.cs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,40 @@
11
namespace PerfProblemSimulator.Models;
22

33
/// <summary>
4-
/// Configuration options for the Performance Problem Simulator.
5-
/// Loaded from the "ProblemSimulator" section of appsettings.json.
4+
/// Application-wide configuration options loaded from appsettings.json or environment variables.
65
/// </summary>
6+
/// <remarks>
7+
/// <para>
8+
/// <strong>PURPOSE:</strong>
9+
/// Centralized configuration that can be customized per deployment environment.
10+
/// Follows the Options pattern for dependency injection.
11+
/// </para>
12+
/// <para>
13+
/// <strong>CONFIGURATION SOURCES (in priority order):</strong>
14+
/// <list type="number">
15+
/// <item>Environment variables (highest priority, e.g., ProblemSimulator__AppTitle)</item>
16+
/// <item>appsettings.{Environment}.json (Development, Production)</item>
17+
/// <item>appsettings.json (base settings)</item>
18+
/// <item>Default values in this class (lowest priority)</item>
19+
/// </list>
20+
/// </para>
21+
/// <para>
22+
/// <strong>AZURE APP SERVICE CONFIGURATION:</strong>
23+
/// In Azure Portal > App Service > Configuration > Application settings:
24+
/// - Name: ProblemSimulator__AppTitle
25+
/// - Value: "My Custom Title"
26+
/// The double underscore (__) translates to colon (:) for nested JSON properties.
27+
/// </para>
28+
/// <para>
29+
/// <strong>PORTING TO OTHER LANGUAGES:</strong>
30+
/// <list type="bullet">
31+
/// <item>PHP: Use $_ENV or .env files with vlucas/phpdotenv</item>
32+
/// <item>Node.js: Use dotenv package and process.env</item>
33+
/// <item>Java/Spring: Use @ConfigurationProperties or application.properties</item>
34+
/// <item>Python: Use python-dotenv and os.environ</item>
35+
/// </list>
36+
/// </para>
37+
/// </remarks>
738
public class ProblemSimulatorOptions
839
{
940
/// <summary>

0 commit comments

Comments
 (0)