From 327ef29d550a111ad2d60a93248ac90247c9f77e Mon Sep 17 00:00:00 2001 From: Michael Mainguy Date: Tue, 19 Aug 2025 07:18:39 -0500 Subject: [PATCH] Fix CSV export timing columns and add units to headers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrects CSV export to properly include timing data by accessing nested timing properties and calculating derived values like DNS time, connection time, and data rate. Headers now include units (μs, bytes, bytes/sec) for clarity. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .../httprequestviewer/lib/csvExport.ts | 82 ++++++++++++++++--- 1 file changed, 69 insertions(+), 13 deletions(-) diff --git a/src/components/httprequestviewer/lib/csvExport.ts b/src/components/httprequestviewer/lib/csvExport.ts index d5fd0dd..0e6134f 100644 --- a/src/components/httprequestviewer/lib/csvExport.ts +++ b/src/components/httprequestviewer/lib/csvExport.ts @@ -14,14 +14,14 @@ const DEFAULT_COLUMNS = [ 'priority', 'protocol', 'connectionNumber', - 'requestNumber', - 'startTime', - 'queueTime', + 'requestNumberOnConnection', + 'timing.start', + 'timing.queueTime', 'dnsTime', 'connectionTime', - 'serverLatency', - 'duration', - 'totalResponseTime', + 'timing.serverLatency', + 'timing.duration', + 'timing.totalResponseTime', 'dataRate', 'size', 'contentLength', @@ -55,6 +55,34 @@ const formatCSVValue = (value: any): string => { return stringValue } +// Calculate derived values for CSV export +const calculateDerivedValue = (request: HTTPRequest, path: string): any => { + switch (path) { + case 'dnsTime': + if (request.timing.dnsStart !== undefined && request.timing.dnsEnd !== undefined && + request.timing.dnsStart >= 0 && request.timing.dnsEnd >= 0) { + return request.timing.dnsEnd - request.timing.dnsStart + } + return null + case 'connectionTime': + if (request.timing.connectStart !== undefined && request.timing.connectEnd !== undefined && + request.timing.connectStart >= 0 && request.timing.connectEnd >= 0) { + return request.timing.connectEnd - request.timing.connectStart + } + return null + case 'dataRate': + if (!request.timing.duration || request.timing.duration <= 0) return null + const bytes = request.contentLength && request.contentLength > 0 ? request.contentLength : request.encodedDataLength + if (!bytes) return null + const durationSeconds = request.timing.duration / 1000000 + return bytes / durationSeconds // bytes per second + case 'size': + return request.encodedDataLength || request.contentLength || null + default: + return getNestedValue(request, path) + } +} + // Get nested property value from object const getNestedValue = (obj: any, path: string): any => { return path.split('.').reduce((current, key) => { @@ -81,12 +109,40 @@ export const exportRequestsToCSV = ( // Add headers if requested if (includeHeaders) { const headers = selectedColumns.map(col => { - // Clean up column names for headers - return col - .replace(/([A-Z])/g, ' $1') // Add space before capitals - .replace(/^\w/, c => c.toUpperCase()) // Capitalize first letter - .replace(/\./g, ' ') // Replace dots with spaces - .trim() + // Add units to timing-related headers + switch (col) { + case 'timing.start': + return 'Start Time (μs)' + case 'timing.queueTime': + return 'Queue Time (μs)' + case 'dnsTime': + return 'DNS Time (μs)' + case 'connectionTime': + return 'Connection Time (μs)' + case 'timing.serverLatency': + return 'Server Latency (μs)' + case 'timing.duration': + return 'Duration (μs)' + case 'timing.totalResponseTime': + return 'Total Response Time (μs)' + case 'timing.downloadTime': + return 'Download Time (μs)' + case 'dataRate': + return 'Data Rate (bytes/sec)' + case 'size': + return 'Size (bytes)' + case 'contentLength': + return 'Content Length (bytes)' + case 'encodedDataLength': + return 'Encoded Data Length (bytes)' + default: + // Clean up column names for other headers + return col + .replace(/([A-Z])/g, ' $1') // Add space before capitals + .replace(/^\w/, c => c.toUpperCase()) // Capitalize first letter + .replace(/\./g, ' ') // Replace dots with spaces + .trim() + } }) lines.push(headers.map(formatCSVValue).join(',')) } @@ -94,7 +150,7 @@ export const exportRequestsToCSV = ( // Add data rows for (const request of requests) { const values = selectedColumns.map(column => { - const value = getNestedValue(request, column) + const value = calculateDerivedValue(request, column) return formatCSVValue(value) }) lines.push(values.join(','))