Technical Track Record
Case 01: iperf Analyzer - DevOps Performance Engine
Briefing
Manual processing of iperf logs across global infrastructures introduced inconsistencies and critical delays in SLA validation. I built a high-performance Single Page Application that centralizes all data processing entirely client-side. The solution converts raw logs into actionable intelligence, automating executive and technical report generation in five languages and reducing analysis time from hours to seconds.
Technical Deep Dive
I implemented a sophisticated parsing engine using a State Machine to process multi-stream iperf3 data flows. The application uses advanced Regex to normalize units (SI vs. Binary) and compute link efficiency statistics with an 80% threshold for automatic PASS/FAIL determination. To guarantee data sovereignty, the architecture is 100% stateless; all processing, complex chart rendering with Chart.js, and PDF generation via jsPDF occur in the browser, eliminating infrastructure costs and privacy risks.
iperf Report Generator
Documentation
Production-Ready Network Performance Analysis Tool Comprehensive documentation for DevOps teams supporting the iperf Analyzer application.
ποΈ System Architecture
Application Overview
The iperf Analyzer is a client-side Single Page Application (SPA) built with Next.js that processes network performance test data from iperf tools. It provides multilingual support, interactive visualizations, and generates professional PDF reports.
Core Components
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β CLIENT BROWSER β
β βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ β
β β UI Layer β β Data Processing β β PDF Generatorβ β
β β - Forms β β - iperf Parser β β - jsPDF β β
β β - Charts β β - Calculations β β - Reports β β
β β - Results β β - Validation β β β β
β βββββββββββββββββββ βββββββββββββββββββ ββββββββββββββββ β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β Internationalization (i18n) β β
β β 5 Languages: PT-BR, EN, ES, FR, DE β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββTechnology Stack
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Framework | Next.js | 15.3.3 | React framework with App Router |
| Runtime | React | 19.0 | UI library |
| Language | TypeScript | 5.0 | Type safety and development |
| Styling | Tailwind CSS | 4.0 | Utility-first CSS framework |
| Charts | Chart.js + react-chartjs-2 | 4.4.9 + 5.3.0 | Interactive data visualization |
| jsPDF + html2canvas | 3.0.1 + 1.4.1 | Client-side PDF generation | |
| Icons | Lucide React | 0.513.0 | Icon library |
| Date Handling | date-fns | 4.1.0 | Date manipulation and formatting |
π Deployment Guide
Prerequisites
- Node.js 18.x or higher
- npm 8.x or higher
- Modern web server (Nginx, Apache, or CDN)
Build Process
# Install dependencies
npm ci --production=false
# Run type checking
npm run build
# Output location: .next/ directory
# Static assets: .next/static/
# Server files: .next/server/Environment Configuration
The application requires no environment variables for basic functionality. All processing occurs client-side.
Optional Environment Variables:
# Analytics (if implemented)
NEXT_PUBLIC_GA_ID=G-XXXXXXXXXX
NEXT_PUBLIC_SENTRY_DSN=https://xxx@sentry.io/xxx
# Build optimization
NODE_ENV=production
NEXT_TELEMETRY_DISABLED=1Deployment Options
1. Static Export (Recommended)
# Build static version
npm run build
# Deploy .next/static/* to CDN
# Deploy _next/* to web server2. Next.js Server
# Production server
npm run start
# Default port: 3000
# Configure reverse proxy for port 80/4433. Docker Deployment
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]Web Server Configuration
Nginx Configuration
server {
listen 80;
server_name your-domain.com;
# Gzip compression
gzip on;
gzip_types text/css application/javascript application/json image/svg+xml;
# Static assets caching
location /_next/static/ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Application routes
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}π Monitoring & Observability
Key Metrics to Monitor
Application Performance
- Page Load Time: Target < 2 seconds
- Bundle Size: Monitor for increases > 10%
- Memory Usage: Client-side memory consumption
- Parse Time: iperf data processing duration
User Experience
- Error Rate: JavaScript errors and parsing failures
- Success Rate: Successful analysis completions
- PDF Generation: Success rate and timing
- Language Distribution: Usage by locale
Health Check Endpoints
# Application availability
curl -f http://localhost:3000/ || exit 1
# API health (if implemented)
curl -f http://localhost:3000/api/health || exit 1Logging Strategy
Client-Side Logging
// Error tracking
window.addEventListener('error', (event) => {
console.error('Global error:', event.error);
// Send to monitoring service
});
// Performance monitoring
window.addEventListener('load', () => {
const perfData = performance.getEntriesByType('navigation')[0];
console.log('Page load time:', perfData.loadEventEnd - perfData.loadEventStart);
});Server-Side Logging (if using Next.js server)
// Custom logging middleware
export function middleware(request) {
console.log(`${new Date().toISOString()} ${request.method} ${request.url}`);
}π§ Configuration Management
Application Configuration
Language Configuration (src/lib/i18n.ts)
// Supported languages
export type Language = 'pt-BR' | 'en' | 'es' | 'fr' | 'de';
// Add new language
const translations: Record<Language, Translations> = {
'pt-BR': { /* Portuguese translations */ },
'en': { /* English translations */ },
// Add new language here
};Chart Configuration (src/components/Charts/)
// Chart.js global settings
Chart.defaults.font.family = 'Inter, sans-serif';
Chart.defaults.color = '#374151';
Chart.defaults.plugins.legend.display = true;PDF Configuration (src/lib/pdfGenerator.ts)
// PDF settings
const PDF_CONFIG = {
format: 'a4',
margin: 20,
fontSize: {
title: 18,
subtitle: 14,
body: 10
}
};Build Configuration
Next.js Configuration (next.config.js)
const nextConfig = {
// Strict mode for development
eslint: { ignoreDuringBuilds: false },
typescript: { ignoreBuildErrors: false },
// Performance optimizations
compress: true,
poweredByHeader: false,
// Static export for CDN deployment
output: 'export',
trailingSlash: true,
// Image optimization
images: { unoptimized: true }
};π Troubleshooting Guide
Common Issues
1. Build Failures
# Clear Next.js cache
rm -rf .next
# Clear node_modules
rm -rf node_modules package-lock.json
npm install
# Check TypeScript errors
npx tsc --noEmit2. Memory Issues
# Increase Node.js memory limit
export NODE_OPTIONS="--max-old-space-size=4096"
npm run build3. Chart Rendering Issues
// Check Chart.js version compatibility
npm ls chart.js react-chartjs-2
// Verify canvas support
if (!document.createElement('canvas').getContext) {
console.error('Canvas not supported');
}4. PDF Generation Failures
// Check jsPDF compatibility
try {
const pdf = new jsPDF();
pdf.text('Test', 10, 10);
} catch (error) {
console.error('PDF generation not supported:', error);
}Error Codes & Solutions
| Error Code | Description | Solution |
|---|---|---|
PARSE_001 | Invalid iperf data format | Validate input contains [SUM] markers |
CALC_002 | Calculation overflow | Check for extremely large bandwidth values |
PDF_003 | PDF generation timeout | Reduce chart complexity or data size |
I18N_004 | Missing translation key | Add key to all language files |
CHART_005 | Chart rendering failure | Verify Chart.js canvas context |
Debug Mode
# Enable debug logging
export DEBUG=iperf-analyzer:*
npm run dev
# Enable React strict mode
export NODE_ENV=developmentπ Security Considerations
Client-Side Security
- Input Validation: All user inputs are validated and sanitized
- XSS Prevention: React's built-in XSS protection
- Content Security Policy: Implement CSP headers
- Data Processing: All processing occurs client-side (no data transmission)
Recommended Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;π Performance Optimization
Bundle Analysis
# Analyze bundle size
npm install -g @next/bundle-analyzer
ANALYZE=true npm run buildOptimization Strategies
- Code Splitting: Charts and PDF generation are lazy-loaded
- Tree Shaking: Unused code is eliminated during build
- Image Optimization: Use WebP format for better compression
- Caching: Implement aggressive caching for static assets
Performance Targets
- First Contentful Paint: < 1.5s
- Largest Contentful Paint: < 2.5s
- Cumulative Layout Shift: < 0.1
- First Input Delay: < 100ms
π Backup & Recovery
Data Backup
Since the application is stateless and processes data client-side:
- No database backup required
- Source code backup: Ensure Git repository is backed up
- Configuration backup: Store environment variables securely
Disaster Recovery
- Application Recovery: Redeploy from Git repository
- CDN Recovery: Re-upload static assets
- DNS Recovery: Update DNS records if needed
π Maintenance Procedures
Regular Maintenance
Weekly Tasks
- Monitor application performance metrics
- Check for security vulnerabilities:
npm audit - Review error logs and user feedback
Monthly Tasks
- Update dependencies:
npm update - Performance audit:
npm run build && npm run analyze - Security scan:
npm audit --audit-level moderate
Quarterly Tasks
- Major dependency updates
- Performance optimization review
- Security penetration testing
Dependency Management
# Check for outdated packages
npm outdated
# Update all dependencies
npm update
# Update specific package
npm install package-name@latest
# Security audit
npm audit
npm audit fixπ Additional Resources
Documentation Links
- [Next.js Documentation](https://nextjs.org/docs)
- [Chart.js Documentation](https://www.chartjs.org/docs/)
- [jsPDF Documentation](https://raw.githack.com/MrRio/jsPDF/master/docs/)
- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
Development Tools
# Code quality
npm run lint
npm run type-check
# Testing (if implemented)
npm run test
npm run test:e2e
# Performance testing
npm run lighthouse---
π iperf Log Parsing Engine
Overview
The iperf Analyzer implements a sophisticated parsing engine that processes raw iperf output logs and extracts meaningful performance data. The parser handles multiple iperf formats, connection types, and test scenarios with robust error handling and validation.
Parsing Architecture
Core Parser Class (src/lib/iperfParser.ts)
export class IperfParser {
// Unit conversion methods
private static convertToBytes(value: string): number
private static convertToBitsPerSec(value: string): number
private static parseTimeInterval(interval: string): { start: number; end: number }
// Main parsing method
public static parse(rawData: string): ParsedIperfData
}Parsing Process Flow
1. Input Preprocessing
// Split raw data into lines and filter empty lines
const lines = rawData.split('\n')
.map(line => line.trim())
.filter(line => line.length > 0);2. State Machine Processing
The parser operates as a state machine with two primary states:
- Test Execution State: Captures real-time interval data
- Summary State: Processes final test results
let isInSummarySection = false;
let currentBlockSummaries: { sender?: ConnectionSummary; receiver?: ConnectionSummary } = {};3. Pattern Recognition
Connection Information Extraction
/^\[\s*(\d+)\] local ([\d.]+) port (\d+) connected to ([\d.]+) port (\d+)/Example Match:
[ 5] local 192.168.1.100 port 5201 connected to 192.168.1.200 port 47384Real-time Interval Data
/^\[SUM\]\s+([\d.-]+)\s+sec\s+([\d.]+\s*[KMGT]?Bytes)\s+([\d.]+\s*[KMGT]?bits\/sec)/Example Match:
[SUM] 0.00-1.00 sec 125 MBytes 1.05 Gbits/secSummary Section Data
/^\[SUM\]\s+[\d.-]+\s*sec\s+([\d.]+\s*[KMGT]?Bytes)\s+([\d.]+\s*[KMGT]?bits\/sec)\s+(sender|receiver)/Example Match:
[SUM] 0.00-30.00 sec 3.66 GBytes 1.05 Gbits/sec sender
[SUM] 0.00-30.00 sec 3.66 GBytes 1.05 Gbits/sec receiverUnit Conversion System
Bandwidth Conversion (Decimal SI Units)
private static convertToBitsPerSec(value: string): number {
const match = value.match(/^([\d.]+)\s*([KMGT]?)bits\/sec$/);
// K = 1,000 | M = 1,000,000 | G = 1,000,000,000 | T = 1,000,000,000,000
}Transfer Conversion (Binary Units)
private static convertToBytes(value: string): number {
const match = value.match(/^([\d.]+)\s*([KMGT]?)Bytes$/);
// K = 1,024 | M = 1,048,576 | G = 1,073,741,824 | T = 1,099,511,627,776
}Data Structure Output
Parsed Data Structure
interface ParsedIperfData {
testStart: string; // Test initiation timestamp
connections: Connection[]; // Network connection details
intervals: IperfInterval[]; // Real-time performance intervals
summary: {
upload: ConnectionSummary[]; // Upload test summaries
download: ConnectionSummary[]; // Download test summaries
};
errors: string[]; // Captured error messages
thirtySecondBlocks: ThirtySecondBlock[]; // 30-second aggregated blocks
}Interval Data Structure
interface IperfInterval {
startTime: number; // Interval start time (seconds)
endTime: number; // Interval end time (seconds)
transfer: number; // Data transferred (bytes)
bandwidth: number; // Measured bandwidth (bits/sec)
duration: number; // Interval duration (seconds)
isFailed: boolean; // Failure detection flag
}Success Criteria and Validation
1. Connection Validation
- Success: Valid IP addresses and port numbers extracted
- Failure: Malformed connection strings or missing connection info
2. Interval Data Validation
// Bandwidth validation
const isFailed = bandwidth === 0;
// Time interval validation
const duration = timeInterval.end - timeInterval.start;
if (duration <= 0) {
// Invalid interval detected
}3. Unit Conversion Validation
// Bandwidth pattern matching
const match = value.match(/^([\d.]+)\s*([KMGT]?)bits\/sec$/);
if (!match) return 0; // Invalid format
// Transfer pattern matching
const match = value.match(/^([\d.]+)\s*([KMGT]?)Bytes$/);
if (!match) return 0; // Invalid formatError Detection and Handling
1. Parse Errors
// Capture explicit error messages
if (line.includes('error') || line.includes('Connection reset')) {
result.errors.push(line);
}2. Data Validation Errors
- Zero bandwidth detection:
bandwidth === 0 - Invalid time ranges:
startTime >= endTime - Missing summary data: No sender/receiver pairs found
3. Format Validation
- Regex pattern failures: Unrecognized line formats
- Unit conversion failures: Invalid unit specifications
- Incomplete data blocks: Missing sender or receiver data
Advanced Features
1. Multi-Block Support
Handles multiple 30-second test blocks for extended test scenarios:
// Detect block boundaries
if (line.includes('iperf Done.') || (line.startsWith('Test started on') && isInSummarySection)) {
// Save current block and start new one
if (currentBlockSummaries.sender && currentBlockSummaries.receiver) {
result.thirtySecondBlocks.push({
sender: currentBlockSummaries.sender,
receiver: currentBlockSummaries.receiver
});
}
}2. Bidirectional Test Support
Automatically detects and separates upload/download data:
if (connectionSummary.type === 'sender') {
result.summary.upload.push(connectionSummary);
} else {
result.summary.download.push(connectionSummary);
}Test Pass/Fail Criteria
Primary Success Metric: Link Efficiency β₯ 80%
The application determines test success based on link efficiency, calculated as the ratio between measured bandwidth and contracted bandwidth.
// Core Pass/Fail determination
const efficiency = IperfCalculator.calculateEfficiency(measuredBandwidth, contractedBandwidth);
const testPassed = efficiency >= 80;Efficiency Calculation Methods
1. Standard Efficiency Calculation
public static calculateEfficiency(measuredBandwidth: number, contractedBandwidth: number): number {
if (contractedBandwidth === 0) return 0;
return Math.min((measuredBandwidth / contractedBandwidth) * 100, 100);
}2. Advanced Minimum Bandwidth Analysis
For comprehensive testing, the system uses the minimum bandwidth approach:
// Calculate efficiency using minimum bandwidth (most conservative approach)
const uploadMinEfficiency = IperfCalculator.calculateEfficiency(uploadStats.min, contractedBandwidth);
const downloadMinEfficiency = IperfCalculator.calculateEfficiency(downloadStats.min, contractedBandwidth);
// Use the lower efficiency between upload and download
const minEfficiency = Math.min(uploadMinEfficiency, downloadMinEfficiency);
// Apply Pass/Fail criteria
if (minEfficiency >= 80) {
status = 'PASS';
} else {
status = 'FAIL';
}Pass/Fail Logic Implementation
ResultsDisplay Component (src/components/ResultsDisplay.tsx)
// Determine test result based on upload efficiency β₯ 80%
const contractedBandwidth = IperfCalculator.parseContractedBandwidth(analysis.metadata.contractedLinkSize);
const efficiency = IperfCalculator.calculateEfficiency(analysis.uploadStats.average, contractedBandwidth);
const testPassed = efficiency >= 80;PerformanceChart Component (src/components/Charts/PerformanceChart.tsx)
if (contractedBandwidth && uploadStats && downloadStats) {
// Use minimum bandwidth for conservative assessment
const uploadMinEfficiency = IperfCalculator.calculateEfficiency(uploadStats.min, contractedBandwidth);
const downloadMinEfficiency = IperfCalculator.calculateEfficiency(downloadStats.min, contractedBandwidth);
const minEfficiency = Math.min(uploadMinEfficiency, downloadMinEfficiency);
if (minEfficiency >= 80) {
status = { color: 'text-green-700', bg: 'bg-green-50', label: 'PASS' };
} else {
status = { color: 'text-red-700', bg: 'bg-red-50', label: 'FAIL' };
}
}Success Criteria Hierarchy
1. Primary Criteria (80% Threshold)
- PASS: Link efficiency β₯ 80% of contracted bandwidth
- FAIL: Link efficiency < 80% of contracted bandwidth
2. Assessment Methods (in order of preference)
- Conservative Method: Uses minimum bandwidth from both upload and download
- Standard Method: Uses average bandwidth for efficiency calculation
- Fallback Method: Uses available data when complete stats are unavailable
3. Bandwidth Parsing
public static parseContractedBandwidth(contractedSize: string): number {
const match = contractedSize.match(/^([\d.]+)\s*([KMGT]?)(?:bps|bits?\/s|Mbps|Gbps)?$/i);
if (!match) return 0;
const num = parseFloat(match[1]);
const unit = match[2].toUpperCase();
switch (unit) {
case 'K': return num * 1000;
case 'M': return num * 1000000;
case 'G': return num * 1000000000;
case 'T': return num * 1000000000000;
default: return num * 1000000; // Assume Mbps if no unit
}
}Visual Indicators
Pass Status Display
// Green indicator for successful tests
<div className="flex items-center justify-center w-8 h-8 bg-green-600 rounded-full">
<Check className="w-5 h-5 text-white" />
</div>
<div className="bg-green-50 border-l-green-500">
<p className="font-bold text-2xl text-green-600">PASS</p>
</div>Fail Status Display
// Red indicator for failed tests
<div className="flex items-center justify-center w-8 h-8 bg-red-600 rounded-full">
<X className="w-5 h-5 text-white" />
</div>
<div className="bg-red-50 border-l-red-500">
<p className="font-bold text-2xl text-red-600">FAIL</p>
</div>Validation Rules for Test Success
1. Data Completeness Requirements
- Minimum 1 valid interval required
- Valid contracted bandwidth specification
- Successful parsing of iperf summary data
2. Quality Thresholds
// Interval validation
const isFailed = bandwidth === 0;
const validIntervals = intervals.filter(interval => !interval.isFailed);
// Success rate calculation
const successRate = totalIntervals > 0
? ((validIntervals.length / totalIntervals) * 100)
: 0;3. Error Handling for Pass/Fail
- No contracted bandwidth: Test marked as indeterminate
- Zero measured bandwidth: Automatic FAIL
- Parsing errors: FAIL with error reporting
- Incomplete data: FAIL with diagnostic information
Industry Standards Compliance
80% Efficiency Threshold Rationale
- Industry Standard: Commonly accepted minimum for network performance validation
- SLA Compliance: Aligns with typical Service Level Agreement requirements
- Quality Assurance: Provides reasonable margin for network variability
- Conservative Assessment: Using minimum bandwidth ensures worst-case scenario validation
Reporting Integration
The Pass/Fail status is integrated across all system outputs:
- Executive Reports: High-level Pass/Fail summary
- Engineering Reports: Detailed efficiency analysis
- Interactive Dashboard: Real-time status indicators
- PDF Exports: Formatted Pass/Fail documentation
Performance Analysis Engine
Statistical Calculations (src/lib/calculations.ts)
export class IperfCalculator {
// Primary analysis method
public static analyze(parsedData: ParsedIperfData, metadata: TestMetadata): IperfAnalysis
// Statistical computation methods
private static calculateStats(intervals: IperfInterval[])
private static calculateStatsFromSummary(parsedData: ParsedIperfData, type: 'sender' | 'receiver')
// Utility methods
public static formatBandwidth(bitsPerSec: number): string
public static formatTransfer(bytes: number): string
public static calculateEfficiency(measured: number, contracted: number): number
}Success Metrics Calculation
// Failure rate calculation
const totalIntervals = parsedData.intervals.length;
const failedIntervals = parsedData.intervals.filter(interval => interval.isFailed).length;
const failureRate = totalIntervals > 0 ? (failedIntervals / totalIntervals) * 100 : 0;
// Performance statistics
const uploadStats = {
min: Math.min(...validBandwidths),
max: Math.max(...validBandwidths),
average: bandwidths.reduce((sum, bw) => sum + bw, 0) / bandwidths.length,
total: transfers.reduce((sum, transfer) => sum + transfer, 0)
};Supported iperf Formats
1. iperf3 Standard Output
[ 5] 0.00-1.00 sec 113 MBytes 948 Mbits/sec 0 sender
[ 5] 0.00-1.00 sec 113 MBytes 948 Mbits/sec receiver2. Multiple Connection Tests
[SUM] 0.00-1.00 sec 451 MBytes 3.78 Gbits/sec 0 sender
[SUM] 0.00-1.00 sec 451 MBytes 3.78 Gbits/sec receiver3. Bidirectional Tests
[ 5] 0.00-30.00 sec 1.09 GBytes 312 Mbits/sec sender
[ 5] 0.00-30.00 sec 1.09 GBytes 312 Mbits/sec receiver
[ 7] 0.00-30.00 sec 1.09 GBytes 312 Mbits/sec sender
[ 7] 0.00-30.00 sec 1.09 GBytes 312 Mbits/sec receiverQuality Assurance
1. Validation Rules
- Minimum 1 valid interval required for successful analysis
- Bandwidth values must be > 0 for non-failed intervals
- Time intervals must be sequential and non-overlapping
- Summary data must match interval count expectations
2. Error Recovery
- Graceful handling of malformed lines
- Fallback to interval data when summary is missing
- Partial data processing for incomplete tests
- Comprehensive error reporting for debugging
3. Performance Optimization
- Single-pass parsing algorithm: O(n) complexity
- Efficient regex patterns for pattern matching
- Minimal memory allocation during processing
- Lazy evaluation for expensive calculations
---
π± User Interface Documentation
Application Screen Flow
The iperf Analyzer follows a simple two-screen workflow: Data Input β Results Analysis β Report Generation.
1. Test Information Form (src/components/AnalysisForm.tsx)
Purpose
Primary data entry interface where users input test metadata and raw iperf log data for analysis.
Required Fields (All mandatory for form submission)
Site Information
- Site Code (
siteCode): Unique identifier for the test location - Example:
"SP-001","RJ-DATACENTER-01" - Validation: Non-empty string
- Icon: Building
- Operator Name (
operatorName): Network service provider - Example:
"Vivo","Claro","TIM" - Validation: Non-empty string
- Icon: Globe
Test Timing
- Start Date/Time (
startDateTime): Test initiation timestamp - Format:
datetime-localHTML input - Example:
"2024-01-15T09:30" - Validation: Valid datetime, must be before end time
- Icon: Calendar
- End Date/Time (
endDateTime): Test completion timestamp - Format:
datetime-localHTML input - Example:
"2024-01-15T10:00" - Validation: Valid datetime, must be after start time
- Icon: Calendar
- Total Test Time (
totalTestTime): AUTO-CALCULATED field - Read-only: Automatically computed from start/end times
- Calculation Logic:
const diffInMs = endDate.getTime() - startDate.getTime();
const diffInHours = diffInMs / (1000 * 60 * 60);
// Format: "2h 30min", "45min", "30s"
if (diffInHours >= 1) {
const hours = Math.floor(diffInHours);
const minutes = Math.round((diffInHours - hours) * 60);
timeString = minutes > 0 ? `${hours}h ${minutes}min` : `${hours}h`;
} else {
const minutes = Math.round(diffInHours * 60);
timeString = minutes >= 1 ? `${minutes}min` : `${seconds}s`;
}- Real-time Updates: Recalculates whenever start/end times change
- Icon: Clock
Network Configuration
- Contracted Link Size (
contractedLinkSize): Expected bandwidth capacity - Example:
"1000 Mbps","1 Gbps","500M" - Validation: Non-empty string
- Parsing Logic: Supports K/M/G/T units with flexible formatting
- Icon: Upload
Personnel Information
- Operations Engineer (
opsEngineer): Engineer conducting the test - Example:
"JoΓ£o Silva","Maria Santos" - Validation: Non-empty string
- Icon: User
- Local IT Contact (
localIT): On-site technical contact - Example:
"Pedro Costa","Ana Oliveira" - Validation: Non-empty string
- Icon: User
Test Data
- iperf Raw Data (
rawData): Complete iperf command output - Format: Multi-line text area (64 rows)
- Content Validation: Must contain
[SUM]markers - Font: Monospace for better readability
- Example content:
[ 5] local 192.168.1.100 port 5201 connected to 192.168.1.200 port 47384
[SUM] 0.00-1.00 sec 113 MBytes 948 Mbits/sec
[SUM] 0.00-30.00 sec 3.66 GBytes 1.05 Gbits/sec sender- Icon: FileText
Form Validation
Client-Side Validation Rules
const validateForm = (): boolean => {
const newErrors: string[] = [];
// Required field validation
if (!metadata.siteCode.trim()) newErrors.push(t.siteCodeRequired);
if (!metadata.startDateTime) newErrors.push(t.startDateRequired);
if (!metadata.endDateTime) newErrors.push(t.endDateRequired);
if (!metadata.contractedLinkSize.trim()) newErrors.push(t.linkSizeRequired);
if (!metadata.operatorName.trim()) newErrors.push(t.operatorRequired);
if (!metadata.opsEngineer.trim()) newErrors.push(t.engineerRequired);
if (!metadata.localIT.trim()) newErrors.push(t.localITRequired);
if (!rawData.trim()) newErrors.push(t.iperfDataRequired);
// Date range validation
if (metadata.startDateTime && metadata.endDateTime) {
const startDate = new Date(metadata.startDateTime);
const endDate = new Date(metadata.endDateTime);
if (endDate <= startDate) {
newErrors.push(t.invalidDateRange);
}
}
// iperf data format validation
if (rawData.trim() && !rawData.includes('[SUM]')) {
newErrors.push(t.invalidIperfData);
}
return newErrors.length === 0;
};Error Display
- Visual Treatment: Red-bordered container with error list
- Error Categories: Missing fields, invalid dates, malformed iperf data
- Real-time Feedback: Validation occurs on form submission
Form Submission
- Submit Button: Blue primary button with loading state
- Loading Indicator: Animated spinner with "Analyzing..." text
- Disabled State: Button disabled during processing
- Success Action: Triggers
onAnalyze(metadata, rawData)callback
---
2. Test Results Screen (src/components/ResultsDisplay.tsx)
Purpose
Comprehensive analysis dashboard displaying parsed iperf data, performance metrics, visualizations, and actionable insights.
Screen Layout Structure
Header Section
- Title: "Test Results Analysis"
- Subtitle: Site code and operator information
- Action Buttons:
- Back to Form: Gray button (β Back to Form)
- Executive Report: Blue button with download icon
- Engineering Report: Red button with download icon
Executive Summary Cards (4-card grid)
1. Peak Speed Card (Purple background)
// Data source: analysis.uploadStats.max / analysis.downloadStats.max
<div className="bg-purple-100 border-purple-300">
<h3>Peak Speed</h3>
<p>Upload: {IperfCalculator.formatBandwidth(analysis.uploadStats.max)}</p>
<p>Download: {IperfCalculator.formatBandwidth(analysis.downloadStats.max)}</p>
<p className="text-xs">Maximum recorded</p>
</div>- Meaning: Highest bandwidth achieved during test
- Calculation:
Math.max(...validBandwidths) - Significance: Indicates optimal network capacity under ideal conditions
2. Minimum Bandwidth Card (Red background)
// Data source: analysis.uploadStats.min / analysis.downloadStats.min
<div className="bg-red-100 border-red-300">
<h3>Minimum Bandwidth</h3>
<p>Upload: {IperfCalculator.formatBandwidth(analysis.uploadStats.min)}</p>
<p>Download: {IperfCalculator.formatBandwidth(analysis.downloadStats.min)}</p>
<p className="text-xs">Minimum recorded</p>
</div>- Meaning: Lowest bandwidth during test (excluding failed intervals)
- Calculation:
Math.min(...validBandwidths) - Significance: Indicates worst-case performance, critical for SLA validation
3. Average Bandwidth Card (Blue background)
// Data source: analysis.uploadStats.average / analysis.downloadStats.average
<div className="bg-blue-100 border-blue-300">
<h3>Average Bandwidth</h3>
<p>Upload: {IperfCalculator.formatBandwidth(analysis.uploadStats.average)}</p>
<p>Download: {IperfCalculator.formatBandwidth(analysis.downloadStats.average)}</p>
<p className="text-xs">General speed</p>
</div>- Meaning: Statistical mean of all valid measurements
- Calculation:
bandwidths.reduce((sum, bw) => sum + bw, 0) / bandwidths.length - Significance: Representative performance under normal conditions
4. Link Efficiency Card (Green background)
// Data source: Calculated efficiency vs contracted bandwidth
<div className="bg-green-100 border-green-300">
<h3>Link Efficiency</h3>
<p>Upload: {efficiency.toFixed(1)}%</p>
<p>Download: {downloadEfficiency.toFixed(1)}%</p>
<p className="text-xs">vs {analysis.metadata.contractedLinkSize}</p>
</div>- Meaning: Performance as percentage of contracted capacity
- Calculation:
(measuredBandwidth / contractedBandwidth) * 100 - Significance: Primary success metric for network validation
Pass/Fail Status Indicator
// Visual status based on 80% efficiency threshold
{testPassed ? (
<div className="bg-green-50 border-l-green-500">
<Check className="w-5 h-5 text-white bg-green-600" />
<p className="font-bold text-2xl text-green-600">PASS</p>
</div>
) : (
<div className="bg-red-50 border-l-red-500">
<X className="w-5 h-5 text-white bg-red-600" />
<p className="font-bold text-2xl text-red-600">FAIL</p>
</div>
)}- Criteria:
efficiency >= 80 - Visual Treatment: Large, prominent status with color coding
- Business Impact: Immediate pass/fail determination for network acceptance
Visualization Section (2-chart grid)
1. Bandwidth Evolution Chart (BandwidthChart.tsx)
- Type: Line chart showing bandwidth over time
- Data Source:
analysis.uploadIntervalsoranalysis.thirtySecondIntervals - X-Axis: Time progression (seconds or 30-second blocks)
- Y-Axis: Bandwidth (Mbps/Gbps)
- Features:
- Contracted bandwidth reference line
- Upload/Download separation (if bidirectional data available)
- Interactive tooltips with precise values
- Adaptive scaling based on data range
2. Performance Distribution Chart (PerformanceChart.tsx)
- Type: Histogram/bar chart showing bandwidth distribution
- Data Source: Bandwidth values grouped into ranges
- X-Axis: Bandwidth ranges (bins)
- Y-Axis: Frequency count
- Features:
- Pass/Fail status indicator
- Efficiency percentage display
- Statistical summary (min/max/average)
- Success rate calculation
Detailed Data Table
30-Second Block Table (when available)
// Comprehensive table for extended test data
<table>
<thead>
<tr>
<th>Block</th>
<th>Interval</th>
<th>Upload Bandwidth</th>
<th>Download Bandwidth</th>
<th>Upload Transfer</th>
<th>Download Transfer</th>
<th>Status</th>
<th>Upload Efficiency</th>
<th>Download Efficiency</th>
</tr>
</thead>
<tbody>
{analysis.thirtySecondIntervals.slice(0, 20).map((interval, index) => (
<tr key={index}>
<td>#{interval.blockIndex + 1}</td>
<td>{startTime}min - {endTime}min</td>
<td>{IperfCalculator.formatBandwidth(interval.senderBandwidth)}</td>
<td>{IperfCalculator.formatBandwidth(interval.receiverBandwidth)}</td>
<td>{IperfCalculator.formatTransfer(interval.senderTransfer)}</td>
<td>{IperfCalculator.formatTransfer(interval.receiverTransfer)}</td>
<td>{interval.isFailed ? 'Failed' : 'OK'}</td>
<td>{uploadEfficiency.toFixed(1)}%</td>
<td>{downloadEfficiency.toFixed(1)}%</td>
</tr>
))}
</tbody>
</table>Standard Interval Table (fallback)
// Simplified table for basic interval data
<table>
<thead>
<tr>
<th>Interval</th>
<th>Transfer</th>
<th>Bandwidth</th>
<th>Status</th>
<th>Efficiency</th>
</tr>
</thead>
<tbody>
{analysis.uploadIntervals.slice(0, 15).map((interval, index) => (
<tr key={index}>
<td>{interval.startTime}s - {interval.endTime}s</td>
<td>{IperfCalculator.formatTransfer(interval.transfer)}</td>
<td>{IperfCalculator.formatBandwidth(interval.bandwidth)}</td>
<td>{interval.isFailed ? 'Failed' : 'OK'}</td>
<td>{intervalEfficiency.toFixed(1)}%</td>
</tr>
))}
</tbody>
</table>---
3. Report Generation System (src/lib/pdfGenerator.ts)
Report Types and Differences
Executive Report (generateReport())
Target Audience: Management, stakeholders, non-technical decision makers
Content Structure:
- Executive Summary
- High-level performance metrics
- Simple pass/fail determination
- Key performance indicators in visual cards
- Test Information
- Basic metadata (site, operator, duration)
- Test parameters and configuration
- Visual Charts
- Simplified bandwidth evolution chart
- Performance distribution histogram
- Conclusions
- Clear pass/fail status
- Efficiency percentage
- Recommendations (if applicable)
Format Characteristics:
- Page Count: Typically 1-2 pages
- Visual Focus: Large charts, minimal technical detail
- Language: Business-oriented terminology
- File Name:
"compass-it-report-[SiteCode]-[Date].pdf"
Engineering Report (generateEngineeringReport())
Target Audience: Network engineers, technical teams, troubleshooting specialists
Content Structure:
- Technical Summary
- Detailed performance statistics
- Comprehensive efficiency analysis
- Statistical breakdown (min/max/average/std deviation)
- Complete Test Metadata
- Full test configuration
- Engineer and contact information
- Precise timing information
- Detailed Charts and Graphs
- High-resolution bandwidth evolution
- Performance distribution with statistical overlays
- Interval-by-interval analysis
- Technical Analysis
- Failure rate analysis
- Performance consistency metrics
- Detailed recommendations for optimization
- Raw Data Tables
- Complete interval listing
- Transfer statistics
- Error analysis (if applicable)
Format Characteristics:
- Page Count: Typically 3-5 pages
- Technical Focus: Detailed data tables, comprehensive statistics
- Language: Technical terminology, precise measurements
- File Name:
"compass-it-network-report-[SiteCode]-[Date].pdf"
PDF Generation Process
Common Features
// Shared header generation
private static async addHeader(pdf: jsPDF, pageWidth: number): Promise<number> {
// Company branding (IT Networks + COMPASS)
// Banner image loading with fallback
// Standardized styling and positioning
}
// Image processing for charts
private static async generateChartImage(
intervals: IperfInterval[],
contractedBandwidth: number,
t: Translations,
chartType: 'bandwidth' | 'performance'
): Promise<string> {
// Canvas-based chart rendering
// High-resolution image generation
// Base64 encoding for PDF embedding
}Report Generation Workflow
- PDF Initialization: Create jsPDF instance with A4 format
- Header Addition: Company branding and styling
- Content Rendering: Type-specific content generation
- Chart Integration: Convert interactive charts to static images
- Data Table Generation: Formatted tabular data
- File Download: Automatic browser download with descriptive filename
Internationalization Support
- Multi-language: All reports support 5 languages (PT-BR, EN, ES, FR, DE)
- Dynamic Text: All labels and descriptions use translation system
- Date Formatting: Locale-appropriate date/time formatting
- Number Formatting: Regional number and unit formatting
Report Button Functionality
Executive Report Button (Blue)
const handleGenerateExecutiveReport = async () => {
setIsGeneratingExecutiveReport(true);
try {
await PDFGenerator.generateReport(analysis, t);
} catch (error) {
console.error('Error generating executive report:', error);
} finally {
setIsGeneratingExecutiveReport(false);
}
};- Visual Style: Blue background (
bg-blue-600) - Icon: Download icon
- Loading State: Button disabled with spinner during generation
- Output: Business-focused PDF report
Engineering Report Button (Red)
const handleGenerateEngineeringReport = async () => {
setIsGeneratingEngineeringReport(true);
try {
await PDFGenerator.generateEngineeringReport(analysis, t);
} catch (error) {
console.error('Error generating engineering report:', error);
} finally {
setIsGeneratingEngineeringReport(false);
}
};- Visual Style: Red background (
bg-red-600) - Icon: Download icon
- Loading State: Independent loading state from executive report
- Output: Technical-focused PDF report
Error Handling
- Network Errors: Graceful fallback with user notification
- Chart Generation Failures: Placeholder charts with error indication
- Image Loading Issues: Text-based fallbacks for branding elements
- Memory Limitations: Optimized image processing for large datasets
---
π§ Recent Fixes and Improvements
PDF Report Synchronization (Latest Update)
Issue Fixed: PDF reports were not reflecting the same data displayed on the results screen.
Root Cause: The PDF generator was always using uploadIntervals data, even when 30-second aggregated data (thirtySecondIntervals) was available and being displayed on the results screen.
Solution Implemented:
- Executive Report: Now checks
analysis.hasThirtySecondDataand usesthirtySecondIntervalswhen available - Engineering Report: Updated both chart generation and detailed tables to use 30-second data when present
- Data Consistency: Both reports now match exactly what users see on the results screen
Technical Changes:
- Modified
generateReport()andgenerateEngineeringReport()methods - Added conditional logic to use appropriate data source
- Updated table headers and formatting for 30-second block data
- Fixed chart data mapping to include required
durationproperty
Impact: PDF reports now provide accurate representation of the analysis shown on screen, eliminating discrepancies between UI and exported data.
PDF Report Visual Alignment (Additional Fixes)
Issues Fixed: Multiple visual and content alignment issues between PDF reports and results screen.
Specific Corrections:
1. Executive Summary Cards Alignment
- Before: Cards showed different metrics (avg bandwidth, link efficiency, peak speed, failure rate)
- After: β Cards now match results screen exactly (Peak Speed, Minimum Bandwidth, Average Bandwidth, Link Efficiency)
- Format: Each card shows both upload and download values on separate lines
2. Pass/Fail Status Display
- Before: Verbose status messages ("Link funcionando adequadamente" / "AtenΓ§Γ£o necessΓ‘ria")
- After: β Clear PASS/FAIL indicators matching the results screen exactly
- Format: Large, prominent "β PASS" or "β FAIL" text with appropriate colors
3. Table Column Width Optimization
- Before: Column overlapping and poor text distribution across page width
- After: β Optimized column widths for both 30-second blocks and normal intervals
- 30-second blocks:
[18, 28, 30, 30, 18, 26](Block, Interval, Upload BW, Download BW, Status, Upload Efficiency) - Normal intervals:
[35, 30, 40, 20, 25](Interval, Transfer, Bandwidth, Status, Efficiency)
Technical Implementation:
// Executive Summary Cards - Now matches results screen
const metrics = [
{ label: t.peakSpeed, value: `Upload: ${max}\nDownload: ${max}`, color: purple },
{ label: t.minBandwidth, value: `Upload: ${min}\nDownload: ${min}`, color: red },
{ label: t.avgBandwidth, value: `Upload: ${avg}\nDownload: ${avg}`, color: blue },
{ label: t.linkEfficiency, value: `Upload: ${eff}%\nDownload: ${eff}%`, color: green }
];
// Pass/Fail Status - Clear and prominent
if (efficiency >= 80) {
pdf.text('β PASS', margin, currentY);
} else {
pdf.text('β FAIL', margin, currentY);
}Impact: PDF reports now provide pixel-perfect visual consistency with the results screen interface.
---
Last Updated: 06/25/2025 Document Version: 2.2
Made with β€οΈ for Syngenta IT Networks staff by Eric Barros