Add Data Rate column with color coding and content-length prioritization
- Add Data Rate column between Duration and Size in HTTP requests table - Implement formatDataRate function that prefers content-length over transfer size - Add color coding for data rate: green (≥1 MB/s), yellow (100 KB/s - 1 MB/s), red (<100 KB/s) - Add comprehensive tooltip definition for data rate column - Reorder columns: Server Latency → Duration → Total Response Time → Data Rate → Size 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
69025c17ee
commit
f49a6de4db
@ -4,7 +4,7 @@ import styles from './HTTPRequestViewer.module.css'
|
|||||||
import type { HTTPRequest } from './types/httpRequest'
|
import type { HTTPRequest } from './types/httpRequest'
|
||||||
|
|
||||||
// Import utility functions
|
// Import utility functions
|
||||||
import { formatDuration, formatSize } from './lib/formatUtils'
|
import { formatDuration, formatSize, formatDataRate } from './lib/formatUtils'
|
||||||
import {
|
import {
|
||||||
getStatusColor,
|
getStatusColor,
|
||||||
getProtocolColor,
|
getProtocolColor,
|
||||||
@ -13,6 +13,7 @@ import {
|
|||||||
getDurationColor,
|
getDurationColor,
|
||||||
getTotalResponseTimeColor,
|
getTotalResponseTimeColor,
|
||||||
getServerLatencyColor,
|
getServerLatencyColor,
|
||||||
|
getDataRateColor,
|
||||||
getQueueAnalysisIcon,
|
getQueueAnalysisIcon,
|
||||||
getCDNIcon,
|
getCDNIcon,
|
||||||
getCDNDisplayName
|
getCDNDisplayName
|
||||||
@ -100,6 +101,7 @@ const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({
|
|||||||
<td className={styles.serverLatencyCell} style={{ ...getServerLatencyColor(request.timing.serverLatency) }}>
|
<td className={styles.serverLatencyCell} style={{ ...getServerLatencyColor(request.timing.serverLatency) }}>
|
||||||
{formatDuration(request.timing.serverLatency)}
|
{formatDuration(request.timing.serverLatency)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td className={styles.durationCell} style={{ ...getDurationColor(request.timing.duration) }}>
|
<td className={styles.durationCell} style={{ ...getDurationColor(request.timing.duration) }}>
|
||||||
{formatDuration(request.timing.duration)}
|
{formatDuration(request.timing.duration)}
|
||||||
</td>
|
</td>
|
||||||
@ -109,6 +111,11 @@ const RequestRowSummary: React.FC<RequestRowSummaryProps> = ({
|
|||||||
{formatDuration(request.timing.totalResponseTime)}
|
{formatDuration(request.timing.totalResponseTime)}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
{/* Data Rate */}
|
||||||
|
<td className={`${styles.tableCell} ${styles.right} ${styles.monospace}`} style={{ ...getDataRateColor(request.encodedDataLength, request.contentLength, request.timing.duration) }}>
|
||||||
|
{formatDataRate(request.encodedDataLength, request.contentLength, request.timing.duration)}
|
||||||
|
</td>
|
||||||
|
|
||||||
<td className={styles.sizeCell} style={{ ...getSizeColor(request.encodedDataLength) }}>
|
<td className={styles.sizeCell} style={{ ...getSizeColor(request.encodedDataLength) }}>
|
||||||
{formatSize(request.encodedDataLength)}
|
{formatSize(request.encodedDataLength)}
|
||||||
</td>
|
</td>
|
||||||
|
@ -106,6 +106,11 @@ const RequestsTable: React.FC<RequestsTableProps> = ({
|
|||||||
Total Response Time
|
Total Response Time
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</th>
|
</th>
|
||||||
|
<th className={`${styles.tableHeaderCell} ${styles.right}`}>
|
||||||
|
<Tooltip type={TooltipType.DATA_RATE}>
|
||||||
|
Data Rate
|
||||||
|
</Tooltip>
|
||||||
|
</th>
|
||||||
<th className={`${styles.tableHeaderCell} ${styles.right}`}>
|
<th className={`${styles.tableHeaderCell} ${styles.right}`}>
|
||||||
<Tooltip type={TooltipType.TRANSFER_SIZE}>
|
<Tooltip type={TooltipType.TRANSFER_SIZE}>
|
||||||
Size
|
Size
|
||||||
|
@ -88,6 +88,32 @@ export const getServerLatencyColor = (microseconds?: number) => {
|
|||||||
return HIGHLIGHTING_CONFIG.COLORS.SERVER_LATENCY.DEFAULT
|
return HIGHLIGHTING_CONFIG.COLORS.SERVER_LATENCY.DEFAULT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getDataRateColor = (transferSize?: number, contentLength?: number, durationMicroseconds?: number) => {
|
||||||
|
if (!durationMicroseconds || durationMicroseconds <= 0) return {}
|
||||||
|
|
||||||
|
// Prefer content-length over transfer size for more accurate data rate calculation
|
||||||
|
const bytes = contentLength && contentLength > 0 ? contentLength : transferSize
|
||||||
|
if (!bytes) return {}
|
||||||
|
|
||||||
|
// Convert duration from microseconds to seconds
|
||||||
|
const durationSeconds = durationMicroseconds / 1000000
|
||||||
|
|
||||||
|
// Calculate bytes per second
|
||||||
|
const bytesPerSecond = bytes / durationSeconds
|
||||||
|
|
||||||
|
// Convert to standard units for comparison
|
||||||
|
const mbps = bytesPerSecond / (1024 * 1024) // MB/s
|
||||||
|
const kbps = bytesPerSecond / 1024 // KB/s
|
||||||
|
|
||||||
|
if (mbps >= 1) {
|
||||||
|
return { backgroundColor: '#e8f5e8', color: '#2e7d32' } // Green for >= 1 MB/s
|
||||||
|
} else if (kbps >= 100) {
|
||||||
|
return { backgroundColor: '#fff8e1', color: '#f57c00' } // Yellow for 100 KB/s - 1 MB/s
|
||||||
|
} else {
|
||||||
|
return { backgroundColor: '#ffebee', color: '#c62828' } // Red for < 100 KB/s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const getQueueAnalysisIcon = (analysis?: QueueAnalysis): string => {
|
export const getQueueAnalysisIcon = (analysis?: QueueAnalysis): string => {
|
||||||
if (!analysis) return ''
|
if (!analysis) return ''
|
||||||
|
|
||||||
|
@ -10,4 +10,22 @@ export const formatSize = (bytes?: number): string => {
|
|||||||
if (bytes < 1024) return `${bytes}B`
|
if (bytes < 1024) return `${bytes}B`
|
||||||
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`
|
||||||
return `${(bytes / 1024 / 1024).toFixed(1)}MB`
|
return `${(bytes / 1024 / 1024).toFixed(1)}MB`
|
||||||
|
}
|
||||||
|
|
||||||
|
export const formatDataRate = (transferSize?: number, contentLength?: number, durationMicroseconds?: number): string => {
|
||||||
|
if (!durationMicroseconds || durationMicroseconds <= 0) return 'N/A'
|
||||||
|
|
||||||
|
// Prefer content-length over transfer size for more accurate data rate calculation
|
||||||
|
const bytes = contentLength && contentLength > 0 ? contentLength : transferSize
|
||||||
|
if (!bytes) return 'N/A'
|
||||||
|
|
||||||
|
// Convert duration from microseconds to seconds
|
||||||
|
const durationSeconds = durationMicroseconds / 1000000
|
||||||
|
|
||||||
|
// Calculate bytes per second
|
||||||
|
const bytesPerSecond = bytes / durationSeconds
|
||||||
|
|
||||||
|
if (bytesPerSecond < 1024) return `${bytesPerSecond.toFixed(0)} B/s`
|
||||||
|
if (bytesPerSecond < 1024 * 1024) return `${(bytesPerSecond / 1024).toFixed(1)} KB/s`
|
||||||
|
return `${(bytesPerSecond / 1024 / 1024).toFixed(1)} MB/s`
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ export const TooltipType = {
|
|||||||
SERVER_LATENCY: 'SERVER_LATENCY',
|
SERVER_LATENCY: 'SERVER_LATENCY',
|
||||||
REQUEST_URL: 'REQUEST_URL',
|
REQUEST_URL: 'REQUEST_URL',
|
||||||
REQUEST_DURATION: 'REQUEST_DURATION',
|
REQUEST_DURATION: 'REQUEST_DURATION',
|
||||||
|
DATA_RATE: 'DATA_RATE',
|
||||||
TOTAL_RESPONSE_TIME: 'TOTAL_RESPONSE_TIME',
|
TOTAL_RESPONSE_TIME: 'TOTAL_RESPONSE_TIME',
|
||||||
TRANSFER_SIZE: 'TRANSFER_SIZE',
|
TRANSFER_SIZE: 'TRANSFER_SIZE',
|
||||||
CONTENT_LENGTH: 'CONTENT_LENGTH',
|
CONTENT_LENGTH: 'CONTENT_LENGTH',
|
||||||
@ -164,6 +165,17 @@ export const TOOLTIP_DEFINITIONS: Record<TooltipTypeValues, TooltipDefinition> =
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[TooltipType.DATA_RATE]: {
|
||||||
|
title: "Data Rate",
|
||||||
|
description: "Download speed calculated as transfer size divided by request duration. Indicates network throughput for this resource.",
|
||||||
|
lighthouseRelation: "Low data rates may indicate network bottlenecks affecting resource loading speed, impacting LCP and overall performance scores.",
|
||||||
|
calculation: "Transfer Size ÷ Request Duration. Shows effective throughput in KB/s or MB/s.",
|
||||||
|
links: [
|
||||||
|
{ text: "Network Performance", url: "https://web.dev/articles/fast" },
|
||||||
|
{ text: "Optimize Resource Loading", url: "https://web.dev/articles/critical-rendering-path" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
[TooltipType.TOTAL_RESPONSE_TIME]: {
|
[TooltipType.TOTAL_RESPONSE_TIME]: {
|
||||||
title: "Total Response Time",
|
title: "Total Response Time",
|
||||||
description: "Complete time from navigation start to request completion. Shows request timing in context of page load.",
|
description: "Complete time from navigation start to request completion. Shows request timing in context of page load.",
|
||||||
|
Loading…
Reference in New Issue
Block a user