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:
parent
33fb2b1674
commit
b3dedb3dbf
@ -93,7 +93,7 @@
|
|||||||
|
|
||||||
.tableHeader {
|
.tableHeader {
|
||||||
display: grid;
|
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;
|
gap: 16px;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
background: #f8f9fa;
|
background: #f8f9fa;
|
||||||
@ -107,7 +107,7 @@
|
|||||||
|
|
||||||
.tableRow {
|
.tableRow {
|
||||||
display: grid;
|
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;
|
gap: 16px;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
border-bottom: 1px solid #f0f0f0;
|
border-bottom: 1px solid #f0f0f0;
|
||||||
@ -178,7 +178,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.tableHeader, .tableRow {
|
.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;
|
gap: 8px;
|
||||||
padding: 12px 15px;
|
padding: 12px 15px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
@ -26,8 +26,10 @@ interface CategoryBreakdown {
|
|||||||
count: number
|
count: number
|
||||||
percentage: number
|
percentage: number
|
||||||
totalSize: number
|
totalSize: number
|
||||||
averageResponseTime: number
|
sizePercentage: number
|
||||||
totalResponseTime: number
|
totalResponseTime: number
|
||||||
|
responseTimePercentage: number
|
||||||
|
averageResponseTime: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
||||||
@ -93,6 +95,15 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
typeMap.get(type)!.push(req)
|
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]) => {
|
return Array.from(typeMap.entries()).map(([type, requests]) => {
|
||||||
const totalSize = requests.reduce((sum, req) => {
|
const totalSize = requests.reduce((sum, req) => {
|
||||||
return sum + (req.contentLength || req.encodedDataLength || 0)
|
return sum + (req.contentLength || req.encodedDataLength || 0)
|
||||||
@ -107,8 +118,10 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
count: requests.length,
|
count: requests.length,
|
||||||
percentage: (requests.length / httpRequests.length) * 100,
|
percentage: (requests.length / httpRequests.length) * 100,
|
||||||
totalSize,
|
totalSize,
|
||||||
averageResponseTime: totalResponseTime / requests.length,
|
sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
|
||||||
totalResponseTime
|
totalResponseTime,
|
||||||
|
responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
|
||||||
|
averageResponseTime: totalResponseTime / requests.length
|
||||||
}
|
}
|
||||||
}).sort((a, b) => b.count - a.count)
|
}).sort((a, b) => b.count - a.count)
|
||||||
}, [httpRequests])
|
}, [httpRequests])
|
||||||
@ -124,6 +137,15 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
statusMap.get(status)!.push(req)
|
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]) => {
|
return Array.from(statusMap.entries()).map(([status, requests]) => {
|
||||||
const totalSize = requests.reduce((sum, req) => {
|
const totalSize = requests.reduce((sum, req) => {
|
||||||
return sum + (req.contentLength || req.encodedDataLength || 0)
|
return sum + (req.contentLength || req.encodedDataLength || 0)
|
||||||
@ -138,8 +160,10 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
count: requests.length,
|
count: requests.length,
|
||||||
percentage: (requests.length / httpRequests.length) * 100,
|
percentage: (requests.length / httpRequests.length) * 100,
|
||||||
totalSize,
|
totalSize,
|
||||||
averageResponseTime: totalResponseTime / requests.length,
|
sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
|
||||||
totalResponseTime
|
totalResponseTime,
|
||||||
|
responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
|
||||||
|
averageResponseTime: totalResponseTime / requests.length
|
||||||
}
|
}
|
||||||
}).sort((a, b) => b.count - a.count)
|
}).sort((a, b) => b.count - a.count)
|
||||||
}, [httpRequests])
|
}, [httpRequests])
|
||||||
@ -155,6 +179,15 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
hostMap.get(hostname)!.push(req)
|
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]) => {
|
return Array.from(hostMap.entries()).map(([hostname, requests]) => {
|
||||||
const totalSize = requests.reduce((sum, req) => {
|
const totalSize = requests.reduce((sum, req) => {
|
||||||
return sum + (req.contentLength || req.encodedDataLength || 0)
|
return sum + (req.contentLength || req.encodedDataLength || 0)
|
||||||
@ -169,8 +202,10 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
count: requests.length,
|
count: requests.length,
|
||||||
percentage: (requests.length / httpRequests.length) * 100,
|
percentage: (requests.length / httpRequests.length) * 100,
|
||||||
totalSize,
|
totalSize,
|
||||||
averageResponseTime: totalResponseTime / requests.length,
|
sizePercentage: totalAllSize > 0 ? (totalSize / totalAllSize) * 100 : 0,
|
||||||
totalResponseTime
|
totalResponseTime,
|
||||||
|
responseTimePercentage: totalAllResponseTime > 0 ? (totalResponseTime / totalAllResponseTime) * 100 : 0,
|
||||||
|
averageResponseTime: totalResponseTime / requests.length
|
||||||
}
|
}
|
||||||
}).sort((a, b) => b.count - a.count)
|
}).sort((a, b) => b.count - a.count)
|
||||||
}, [httpRequests])
|
}, [httpRequests])
|
||||||
@ -241,9 +276,11 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
<div className={styles.tableHeader}>
|
<div className={styles.tableHeader}>
|
||||||
<span>Type</span>
|
<span>Type</span>
|
||||||
<span>Count</span>
|
<span>Count</span>
|
||||||
<span>Percentage</span>
|
<span>Count %</span>
|
||||||
<span>Total Size</span>
|
<span>Total Size</span>
|
||||||
|
<span>Size %</span>
|
||||||
<span>Total Response Time</span>
|
<span>Total Response Time</span>
|
||||||
|
<span>Response Time %</span>
|
||||||
<span>Avg Response Time</span>
|
<span>Avg Response Time</span>
|
||||||
</div>
|
</div>
|
||||||
{resourceTypeBreakdown.map(item => (
|
{resourceTypeBreakdown.map(item => (
|
||||||
@ -260,7 +297,25 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>{formatSize(item.totalSize)}</span>
|
<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>
|
<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>
|
<span>{formatDuration(item.averageResponseTime)}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -274,9 +329,11 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
<div className={styles.tableHeader}>
|
<div className={styles.tableHeader}>
|
||||||
<span>Status</span>
|
<span>Status</span>
|
||||||
<span>Count</span>
|
<span>Count</span>
|
||||||
<span>Percentage</span>
|
<span>Count %</span>
|
||||||
<span>Total Size</span>
|
<span>Total Size</span>
|
||||||
|
<span>Size %</span>
|
||||||
<span>Total Response Time</span>
|
<span>Total Response Time</span>
|
||||||
|
<span>Response Time %</span>
|
||||||
<span>Avg Response Time</span>
|
<span>Avg Response Time</span>
|
||||||
</div>
|
</div>
|
||||||
{statusCodeBreakdown.map(item => (
|
{statusCodeBreakdown.map(item => (
|
||||||
@ -293,7 +350,25 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>{formatSize(item.totalSize)}</span>
|
<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>
|
<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>
|
<span>{formatDuration(item.averageResponseTime)}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -307,9 +382,11 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
<div className={styles.tableHeader}>
|
<div className={styles.tableHeader}>
|
||||||
<span>Hostname</span>
|
<span>Hostname</span>
|
||||||
<span>Count</span>
|
<span>Count</span>
|
||||||
<span>Percentage</span>
|
<span>Count %</span>
|
||||||
<span>Total Size</span>
|
<span>Total Size</span>
|
||||||
|
<span>Size %</span>
|
||||||
<span>Total Response Time</span>
|
<span>Total Response Time</span>
|
||||||
|
<span>Response Time %</span>
|
||||||
<span>Avg Response Time</span>
|
<span>Avg Response Time</span>
|
||||||
</div>
|
</div>
|
||||||
{hostnameBreakdown.slice(0, 10).map(item => (
|
{hostnameBreakdown.slice(0, 10).map(item => (
|
||||||
@ -326,7 +403,25 @@ const RequestBreakdown: React.FC<RequestBreakdownProps> = ({ traceId }) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span>{formatSize(item.totalSize)}</span>
|
<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>
|
<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>
|
<span>{formatDuration(item.averageResponseTime)}</span>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
Loading…
Reference in New Issue
Block a user