Add Size % and Response Time % columns to Request Breakdown

Enhances the breakdown tables with comprehensive percentage analysis across three dimensions: request count, data size, and response time.

Features:
- Size Percentage column showing data transfer distribution
- Response Time Percentage column showing performance impact distribution
- Visual progress bars for all percentage columns (Count %, Size %, Response Time %)
- Updated grid layout to accommodate 8-column structure
- Responsive design updates for mobile compatibility
- Clear column headers with abbreviated labels for better readability

This enables three-dimensional analysis to identify:
- Categories with high request counts but low data usage
- Categories consuming disproportionate bandwidth
- Performance bottlenecks with high cumulative response times
- Optimization opportunities across all metrics

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Michael Mainguy 2025-08-19 08:01:04 -05:00
parent 33fb2b1674
commit b3dedb3dbf
2 changed files with 108 additions and 13 deletions

View File

@ -93,7 +93,7 @@
.tableHeader {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1.5fr 1.5fr 1.5fr;
grid-template-columns: 2fr 1fr 1fr 1.5fr 1fr 1.5fr 1fr 1.5fr;
gap: 16px;
padding: 16px 20px;
background: #f8f9fa;
@ -107,7 +107,7 @@
.tableRow {
display: grid;
grid-template-columns: 2fr 1fr 1fr 1.5fr 1.5fr 1.5fr;
grid-template-columns: 2fr 1fr 1fr 1.5fr 1fr 1.5fr 1fr 1.5fr;
gap: 16px;
padding: 16px 20px;
border-bottom: 1px solid #f0f0f0;
@ -178,7 +178,7 @@
}
.tableHeader, .tableRow {
grid-template-columns: 1.5fr 0.8fr 0.8fr 1fr 1fr 1fr;
grid-template-columns: 1.5fr 0.8fr 0.8fr 1fr 0.8fr 1fr 0.8fr 1fr;
gap: 8px;
padding: 12px 15px;
font-size: 13px;

View File

@ -26,8 +26,10 @@ interface CategoryBreakdown {
count: number
percentage: number
totalSize: number
averageResponseTime: number
sizePercentage: number
totalResponseTime: number
responseTimePercentage: number
averageResponseTime: number
}
const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
@ -93,6 +95,15 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
typeMap.get(type)!.push(req)
})
// Calculate total size and response time across all requests for percentage calculations
const totalAllSize = httpRequests.reduce((sum, req) => {
return sum + (req.contentLength || req.encodedDataLength || 0)
}, 0)
const totalAllResponseTime = httpRequests.reduce((sum, req) => {
return sum + (req.timing.totalResponseTime || 0)
}, 0)
return Array.from(typeMap.entries()).map(([type, requests]) => {
const totalSize = requests.reduce((sum, req) => {
return sum + (req.contentLength || req.encodedDataLength || 0)
@ -107,8 +118,10 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
count: requests.length,
percentage: (requests.length / httpRequests.length) * 100,
totalSize,
averageResponseTime: totalResponseTime / requests.length,
totalResponseTime
sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
totalResponseTime,
responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
averageResponseTime: totalResponseTime / requests.length
}
}).sort((a, b) => b.count - a.count)
}, [httpRequests])
@ -124,6 +137,15 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
statusMap.get(status)!.push(req)
})
// Calculate total size and response time across all requests for percentage calculations
const totalAllSize = httpRequests.reduce((sum, req) => {
return sum + (req.contentLength || req.encodedDataLength || 0)
}, 0)
const totalAllResponseTime = httpRequests.reduce((sum, req) => {
return sum + (req.timing.totalResponseTime || 0)
}, 0)
return Array.from(statusMap.entries()).map(([status, requests]) => {
const totalSize = requests.reduce((sum, req) => {
return sum + (req.contentLength || req.encodedDataLength || 0)
@ -138,8 +160,10 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
count: requests.length,
percentage: (requests.length / httpRequests.length) * 100,
totalSize,
averageResponseTime: totalResponseTime / requests.length,
totalResponseTime
sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
totalResponseTime,
responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
averageResponseTime: totalResponseTime / requests.length
}
}).sort((a, b) => b.count - a.count)
}, [httpRequests])
@ -155,6 +179,15 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
hostMap.get(hostname)!.push(req)
})
// Calculate total size and response time across all requests for percentage calculations
const totalAllSize = httpRequests.reduce((sum, req) => {
return sum + (req.contentLength || req.encodedDataLength || 0)
}, 0)
const totalAllResponseTime = httpRequests.reduce((sum, req) => {
return sum + (req.timing.totalResponseTime || 0)
}, 0)
return Array.from(hostMap.entries()).map(([hostname, requests]) => {
const totalSize = requests.reduce((sum, req) => {
return sum + (req.contentLength || req.encodedDataLength || 0)
@ -169,8 +202,10 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
count: requests.length,
percentage: (requests.length / httpRequests.length) * 100,
totalSize,
averageResponseTime: totalResponseTime / requests.length,
totalResponseTime
sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
totalResponseTime,
responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
averageResponseTime: totalResponseTime / requests.length
}
}).sort((a, b) => b.count - a.count)
}, [httpRequests])
@ -241,9 +276,11 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
<div className={styles.tableHeader}>
<span>Type</span>
<span>Count</span>
<span>Percentage</span>
<span>Count %</span>
<span>Total Size</span>
<span>Size %</span>
<span>Total Response Time</span>
<span>Response Time %</span>
<span>Avg Response Time</span>
</div>
{resourceTypeBreakdown.map(item => (
@ -260,7 +297,25 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
</div>
</div>
<span>{formatSize(item.totalSize)}</span>
<div className={styles.percentageCell}>
<span>{item.sizePercentage.toFixed(1)}%</span>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${item.sizePercentage}%` }}
></div>
</div>
</div>
<span>{formatDuration(item.totalResponseTime)}</span>
<div className={styles.percentageCell}>
<span>{item.responseTimePercentage.toFixed(1)}%</span>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${item.responseTimePercentage}%` }}
></div>
</div>
</div>
<span>{formatDuration(item.averageResponseTime)}</span>
</div>
))}
@ -274,9 +329,11 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
<div className={styles.tableHeader}>
<span>Status</span>
<span>Count</span>
<span>Percentage</span>
<span>Count %</span>
<span>Total Size</span>
<span>Size %</span>
<span>Total Response Time</span>
<span>Response Time %</span>
<span>Avg Response Time</span>
</div>
{statusCodeBreakdown.map(item => (
@ -293,7 +350,25 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
</div>
</div>
<span>{formatSize(item.totalSize)}</span>
<div className={styles.percentageCell}>
<span>{item.sizePercentage.toFixed(1)}%</span>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${item.sizePercentage}%` }}
></div>
</div>
</div>
<span>{formatDuration(item.totalResponseTime)}</span>
<div className={styles.percentageCell}>
<span>{item.responseTimePercentage.toFixed(1)}%</span>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${item.responseTimePercentage}%` }}
></div>
</div>
</div>
<span>{formatDuration(item.averageResponseTime)}</span>
</div>
))}
@ -307,9 +382,11 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
<div className={styles.tableHeader}>
<span>Hostname</span>
<span>Count</span>
<span>Percentage</span>
<span>Count %</span>
<span>Total Size</span>
<span>Size %</span>
<span>Total Response Time</span>
<span>Response Time %</span>
<span>Avg Response Time</span>
</div>
{hostnameBreakdown.slice(0, 10).map(item => (
@ -326,7 +403,25 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
</div>
</div>
<span>{formatSize(item.totalSize)}</span>
<div className={styles.percentageCell}>
<span>{item.sizePercentage.toFixed(1)}%</span>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${item.sizePercentage}%` }}
></div>
</div>
</div>
<span>{formatDuration(item.totalResponseTime)}</span>
<div className={styles.percentageCell}>
<span>{item.responseTimePercentage.toFixed(1)}%</span>
<div className={styles.progressBar}>
<div
className={styles.progressFill}
style={{ width: `${item.responseTimePercentage}%` }}
></div>
</div>
</div>
<span>{formatDuration(item.averageResponseTime)}</span>
</div>
))}