Skip to content

Commit 8fddaa3

Browse files
committed
documentation and visual updates
1 parent f1fea66 commit 8fddaa3

File tree

7 files changed

+238
-288
lines changed

7 files changed

+238
-288
lines changed

src/PerfProblemSimulator/Properties/launchSettings.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,30 @@
99
}
1010
},
1111
"profiles": {
12-
"http": {
12+
"https": {
1313
"commandName": "Project",
1414
"dotnetRunMessages": true,
1515
"launchBrowser": true,
16-
"launchUrl": "swagger",
17-
"applicationUrl": "http://localhost:5221",
16+
"launchUrl": "",
17+
"applicationUrl": "https://localhost:7179;http://localhost:5221",
1818
"environmentVariables": {
1919
"ASPNETCORE_ENVIRONMENT": "Development"
2020
}
2121
},
22-
"https": {
22+
"http": {
2323
"commandName": "Project",
2424
"dotnetRunMessages": true,
2525
"launchBrowser": true,
26-
"launchUrl": "swagger",
27-
"applicationUrl": "https://localhost:7179;http://localhost:5221",
26+
"launchUrl": "",
27+
"applicationUrl": "http://localhost:5221",
2828
"environmentVariables": {
2929
"ASPNETCORE_ENVIRONMENT": "Development"
3030
}
3131
},
3232
"IIS Express": {
3333
"commandName": "IISExpress",
3434
"launchBrowser": true,
35-
"launchUrl": "swagger",
35+
"launchUrl": "",
3636
"environmentVariables": {
3737
"ASPNETCORE_ENVIRONMENT": "Development"
3838
}

src/PerfProblemSimulator/wwwroot/azure-deployment.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -652,12 +652,12 @@ <h3>Assign Contributor Role</h3>
652652
<section id="github-secrets" class="card">
653653
<h2><span class="step-number">5</span> Configure GitHub Secrets</h2>
654654

655-
<h3>Fork or Clone the Repository</h3>
655+
<h3>Clone the Repository</h3>
656656
<ol>
657-
<li><strong>Fork the Repository</strong>
657+
<li><strong>Clone the Repository</strong>
658658
<ul>
659659
<li>Go to the Performance Problem Simulator repository for your stack</li>
660-
<li>Click <strong>Fork</strong> to create your own copy</li>
660+
<li>Click <strong>Code</strong> and clone it to your own GitHub account</li>
661661
</ul>
662662
</li>
663663
</ol>

src/PerfProblemSimulator/wwwroot/azure-monitoring-guide.html

Lines changed: 6 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -893,12 +893,14 @@ <h4>1. Azure Auto-Heal with Slow Request Trigger</h4>
893893

894894
<h4>2. CLR Profiler / Azure Profiler</h4>
895895
<ol>
896-
<li>In App Service, go to <strong>Diagnose and solve problems</strong></li>
897-
<li>Search for "Profiler"</li>
896+
<li>In the dashboard, set execution time long enough that the total simulation easily exceeds 60 seconds (e.g., 25s execution, 10s interval, 6 max requests)</li>
897+
<li>Click <strong>🐌 Start Slow Requests</strong> to begin the simulation</li>
898+
<li>Wait for the first slow request to appear in the event log — this confirms health probe rate has been reduced</li>
899+
<li>In App Service, go to <strong>Diagnose and solve problems</strong> → search for "Profiler"</li>
898900
<li>Start a <strong>CPU Profiler</strong> trace (60-120 seconds recommended)</li>
899-
<li>Trigger the slow request simulation</li>
900-
<li>Download and analyze the trace</li>
901+
<li>Wait for the trace to complete, then download and analyze</li>
901902
</ol>
903+
<p><strong>Why start the simulation first?</strong> The app automatically slows health probes while slow request simulations are active. Starting the simulation before the profiler keeps health probe noise out of the trace, giving you a cleaner profile focused on the blocking patterns.</p>
902904

903905
<h3>What to Look For in CLR Profiler</h3>
904906
<p>The service uses three different sync-over-async patterns with <strong>intentionally descriptive method names</strong>:</p>
@@ -1208,172 +1210,6 @@ <h4>💡 Pro Tip: Creating Error Rate Alerts</h4>
12081210
</div>
12091211
</section>
12101212

1211-
<!-- Using the Request Latency Monitor Section -->
1212-
<section id="latency" class="doc-section">
1213-
<h2>⏱️ Using the Request Latency Monitor</h2>
1214-
<p>The dashboard includes a <strong>Request Latency Monitor</strong> that demonstrates how thread pool starvation affects request processing time.</p>
1215-
1216-
<h3>How It Works</h3>
1217-
<ol>
1218-
<li>A dedicated background thread (not from the thread pool) continuously sends probe requests to <code>/api/health/probe</code></li>
1219-
<li>The probe endpoint is lightweight - it simply returns a timestamp</li>
1220-
<li>Latency is measured from request start to response received</li>
1221-
<li>Results are broadcast via SignalR to the dashboard</li>
1222-
</ol>
1223-
1224-
<h3>What to Observe</h3>
1225-
<table class="latency-table">
1226-
<thead>
1227-
<tr>
1228-
<th>Scenario</th>
1229-
<th>Latency (Total)</th>
1230-
<th>Status</th>
1231-
<th>What's Happening</th>
1232-
</tr>
1233-
</thead>
1234-
<tbody>
1235-
<tr>
1236-
<td>Normal operation</td>
1237-
<td>&lt; 150ms</td>
1238-
<td>✅ Good</td>
1239-
<td>Thread pool threads are available</td>
1240-
</tr>
1241-
<tr>
1242-
<td>Mild starvation</td>
1243-
<td>150ms - 1s</td>
1244-
<td>⚠️ Degraded</td>
1245-
<td>Requests queued waiting for threads</td>
1246-
</tr>
1247-
<tr>
1248-
<td>Severe starvation</td>
1249-
<td>&gt; 1s</td>
1250-
<td>❌ Severe</td>
1251-
<td>Significant queuing delay</td>
1252-
</tr>
1253-
<tr>
1254-
<td>Timeout</td>
1255-
<td>30s</td>
1256-
<td>❌ Critical</td>
1257-
<td>No thread available within timeout</td>
1258-
</tr>
1259-
</tbody>
1260-
</table>
1261-
1262-
<div class="info-box">
1263-
<h4>Key Insight</h4>
1264-
<p>The probe runs on a <strong>dedicated thread</strong> (not from the thread pool), so it can always send requests. However, the ASP.NET Core server uses the thread pool to process incoming requests. During starvation:</p>
1265-
<ol>
1266-
<li>The probe request is sent immediately</li>
1267-
<li>The request sits in the ASP.NET Core queue</li>
1268-
<li>It waits for a thread pool thread to become available</li>
1269-
<li>Latency = time spent waiting + processing time</li>
1270-
</ol>
1271-
<p>This directly demonstrates how sync-over-async anti-patterns impact end-user response times.</p>
1272-
</div>
1273-
1274-
<h3>Correlating with Azure Metrics</h3>
1275-
<p>Compare the dashboard's latency chart with:</p>
1276-
<ul>
1277-
<li><strong>Application Insights</strong> &gt; Live Metrics &gt; Request Duration</li>
1278-
<li><strong>App Service Metrics</strong> &gt; Response Time</li>
1279-
<li><strong>Thread Pool</strong> section showing blocked threads</li>
1280-
</ul>
1281-
</section>
1282-
1283-
<!-- Recommended Monitoring Setup Section -->
1284-
<section id="setup" class="doc-section">
1285-
<h2>🛠️ Recommended Monitoring Setup</h2>
1286-
1287-
<h3>1. Enable Application Insights</h3>
1288-
<div class="code-block">
1289-
<span class="comment"># Via Azure CLI</span>
1290-
az monitor app-insights component create \
1291-
--app ai-perf-simulator \
1292-
--location eastus \
1293-
--resource-group rg-perf-simulator \
1294-
--application-type web
1295-
1296-
<span class="comment"># Get instrumentation key</span>
1297-
az monitor app-insights component show \
1298-
--app ai-perf-simulator \
1299-
--resource-group rg-perf-simulator \
1300-
--query instrumentationKey -o tsv
1301-
</div>
1302-
1303-
<h3>2. Configure Alerts</h3>
1304-
<p>Create alerts for:</p>
1305-
<table class="alert-table">
1306-
<thead>
1307-
<tr>
1308-
<th>Metric</th>
1309-
<th>Threshold</th>
1310-
<th>Action</th>
1311-
</tr>
1312-
</thead>
1313-
<tbody>
1314-
<tr>
1315-
<td>CPU Percentage</td>
1316-
<td>&gt; 80% for 5 min</td>
1317-
<td>Email</td>
1318-
</tr>
1319-
<tr>
1320-
<td>Memory Working Set</td>
1321-
<td>&gt; 1 GB</td>
1322-
<td>Email</td>
1323-
</tr>
1324-
<tr>
1325-
<td>Response Time</td>
1326-
<td>&gt; 5s average</td>
1327-
<td>Email</td>
1328-
</tr>
1329-
<tr>
1330-
<td>Failed Requests</td>
1331-
<td>&gt; 10/minute</td>
1332-
<td>Email + PagerDuty</td>
1333-
</tr>
1334-
</tbody>
1335-
</table>
1336-
1337-
<h3>3. Enable Diagnostic Logs</h3>
1338-
<div class="code-block">
1339-
az webapp log config \
1340-
--resource-group rg-perf-simulator \
1341-
--name your-app-name \
1342-
--application-logging filesystem \
1343-
--detailed-error-messages <span class="keyword">true</span> \
1344-
--failed-request-tracing <span class="keyword">true</span> \
1345-
--web-server-logging filesystem
1346-
</div>
1347-
</section>
1348-
1349-
<!-- Best Practices Section -->
1350-
<section id="best-practices" class="doc-section">
1351-
<h2>📈 Best Practices</h2>
1352-
1353-
<div class="best-practices">
1354-
<div class="do-list">
1355-
<h4>DO:</h4>
1356-
<ul>
1357-
<li>Use Application Insights for production apps</li>
1358-
<li>Set up alerts before issues occur</li>
1359-
<li>Enable diagnostic logging proactively</li>
1360-
<li>Monitor thread pool metrics</li>
1361-
<li>Use async/await properly throughout</li>
1362-
</ul>
1363-
</div>
1364-
<div class="dont-list">
1365-
<h4>DON'T:</h4>
1366-
<ul>
1367-
<li>Use <code>.Wait()</code> or <code>.Result</code> on async methods</li>
1368-
<li>Block thread pool threads</li>
1369-
<li>Allocate large pinned arrays without releasing</li>
1370-
<li>Use spin loops for delays</li>
1371-
<li>Ignore memory growth over time</li>
1372-
</ul>
1373-
</div>
1374-
</div>
1375-
</section>
1376-
13771213
<!-- Additional Resources Section -->
13781214
<section id="resources" class="doc-section">
13791215
<h2>🔗 Additional Resources</h2>
@@ -1437,18 +1273,7 @@ <h2>🔗 Additional Resources</h2>
14371273
<a href="#failedrequests"><span class="toc-icon"></span>Failed Requests</a>
14381274
</li>
14391275
<li class="doc-toc-divider-item" aria-hidden="true"></li>
1440-
<li class="doc-toc-section-item">Tools</li>
1441-
<li class="doc-toc-item">
1442-
<a href="#latency"><span class="toc-icon">⏱️</span>Latency Monitor</a>
1443-
</li>
1444-
<li class="doc-toc-divider-item" aria-hidden="true"></li>
14451276
<li class="doc-toc-section-item">Reference</li>
1446-
<li class="doc-toc-item">
1447-
<a href="#setup"><span class="toc-icon">⚙️</span>Setup</a>
1448-
</li>
1449-
<li class="doc-toc-item">
1450-
<a href="#best-practices"><span class="toc-icon"></span>Best Practices</a>
1451-
</li>
14521277
<li class="doc-toc-item">
14531278
<a href="#resources"><span class="toc-icon">📚</span>Resources</a>
14541279
</li>

src/PerfProblemSimulator/wwwroot/css/dashboard.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ body.page-secondary {
121121
}
122122

123123
.indicator.connected {
124-
background: var(--color-success);
125-
box-shadow: 0 0 8px var(--color-success);
124+
background: #2ecc40;
125+
box-shadow: 0 0 8px #2ecc40;
126126
}
127127

128128
.indicator.disconnected {
@@ -1139,6 +1139,7 @@ body.page-secondary {
11391139
color: white;
11401140
width: 32px;
11411141
height: 32px;
1142+
padding: 0.625rem 1.25rem;
11421143
border-radius: 50%;
11431144
cursor: pointer;
11441145
font-size: 1rem;

0 commit comments

Comments
 (0)