Core
Network Logging
Monitor and log network requests including model downloads
LocalMode provides network logging utilities to monitor downloads, track progress, and debug network issues. This is especially useful for tracking model downloads and displaying progress to users.
Overview
The network logging system tracks:
- Model downloads with progress
- API requests (if any external services are used)
- Upload/download byte counts
- Request timing and statistics
Network logging is opt-in and local-only. No data is sent anywhere—this is purely for local debugging and UI progress indicators.
Quick Start
import { onNetworkRequest, getNetworkStats } from '@localmode/core';
// Subscribe to network events
const unsubscribe = onNetworkRequest((entry) => {
if (entry.category === 'model' && entry.state === 'in-progress') {
console.log(`Downloading: ${entry.url} (${entry.progress}%)`);
}
});
// Later: get statistics
const stats = getNetworkStats();
console.log(`Downloaded: ${stats.totalDownloadBytes} bytes`);
// Clean up when done
unsubscribe();Creating a Network Logger
import { createNetworkLogger } from '@localmode/core';
const logger = createNetworkLogger({
maxEntries: 500, // Keep last 500 entries
logHeaders: false, // Don't log request headers
categories: ['model'], // Only log model downloads
});Configuration Options
Prop
Type
Subscribing to Events
Real-time Progress Updates
import { onNetworkRequest } from '@localmode/core';
const unsubscribe = onNetworkRequest((entry) => {
switch (entry.state) {
case 'pending':
console.log(`Starting: ${entry.url}`);
break;
case 'in-progress':
console.log(`Progress: ${entry.progress}%`);
updateProgressBar(entry.progress);
break;
case 'completed':
console.log(`Completed: ${entry.url} (${entry.duration}ms)`);
break;
case 'failed':
console.error(`Failed: ${entry.url} - ${entry.error}`);
break;
}
});Model Download Progress UI
import { onNetworkRequest } from '@localmode/core';
function ModelDownloadProgress() {
const [progress, setProgress] = useState<number | null>(null);
const [downloading, setDownloading] = useState(false);
useEffect(() => {
const unsubscribe = onNetworkRequest((entry) => {
if (entry.category === 'model') {
if (entry.state === 'in-progress') {
setDownloading(true);
setProgress(entry.progress ?? 0);
} else if (entry.state === 'completed' || entry.state === 'failed') {
setDownloading(false);
setProgress(null);
}
}
});
return unsubscribe;
}, []);
if (!downloading) return null;
return (
<div className="progress-bar">
<div style={{ width: `${progress}%` }} />
<span>{progress}%</span>
</div>
);
}Retrieving Logs
Get All Logs
import { getNetworkLogs } from '@localmode/core';
const logs = getNetworkLogs();
console.log(`Total requests: ${logs.length}`);Filter Logs
import { getNetworkLogs } from '@localmode/core';
// Get model downloads only
const modelLogs = getNetworkLogs({
category: 'model',
});
// Get failed requests
const failedLogs = getNetworkLogs({
state: 'failed',
});
// Get recent requests (last hour)
const recentLogs = getNetworkLogs({
since: new Date(Date.now() - 60 * 60 * 1000),
limit: 50,
order: 'desc',
});
// Filter by URL pattern
const huggingFaceLogs = getNetworkLogs({
urlPattern: /huggingface\.co/,
});Filter Options
Prop
Type
Network Statistics
import { getNetworkStats } from '@localmode/core';
const stats = getNetworkStats();
console.log(`Total requests: ${stats.totalRequests}`);
console.log(`Completed: ${stats.completedRequests}`);
console.log(`Failed: ${stats.failedRequests}`);
console.log(`Downloaded: ${(stats.totalDownloadBytes / 1024 / 1024).toFixed(2)} MB`);
console.log(`Average speed: ${(stats.averageSpeed / 1024).toFixed(2)} KB/s`);
console.log(`Requests/min: ${stats.requestsPerMinute}`);
// Stats by category
console.log('By category:', stats.byCategory);
// Stats by HTTP status
console.log('By status:', stats.byStatus);Stats Structure
Prop
Type
Clearing Logs
import { clearNetworkLogs } from '@localmode/core';
// Clear all logs
clearNetworkLogs();
// Clear logs older than 7 days
clearNetworkLogs({ olderThan: '7d' });
// Clear logs older than specific date
clearNetworkLogs({ olderThan: new Date('2024-01-01') });Duration formats: s (seconds), m (minutes), h (hours), d (days), w (weeks)
Log Entry Structure
Prop
Type
Wrapping Fetch
For full request logging, wrap the global fetch:
import { wrapFetchWithLogging, unwrapFetch, isFetchWrapped } from '@localmode/core';
// Wrap global fetch
wrapFetchWithLogging({
category: 'api',
logHeaders: true,
});
// Now all fetch calls are logged
await fetch('https://api.example.com/data');
// Check if fetch is wrapped
console.log(isFetchWrapped()); // true
// Restore original fetch
unwrapFetch();Wrapping fetch affects all requests in your application. Use with care in production environments.