How to Access and Interpret Logs for Diagnostics in Clash Verge Rev
To access and interpret logs for diagnostics in Clash Verge Rev, open the Logs page to view live WebSocket streams from the Mihomo core, filter entries by severity level (debug, info, warn, or error), and use the search bar to query specific payloads or timestamps.
Clash Verge Rev provides a comprehensive logging interface that aggregates runtime diagnostics from the underlying Mihomo core. Whether you are troubleshooting connection issues or monitoring proxy performance, understanding how to access and interpret logs for diagnostics in Clash Verge Rev is essential for effective network management.
Understanding the Log Architecture
The logging pipeline in Clash Verge Rev consists of three distinct layers that work together to deliver real-time diagnostics.
Log Settings and Preferences
User preferences are persisted in localStorage via the useClashLog hook located in src/hooks/use-clash-log.ts.
const defaultClashLog: IClashLog = {
enable: true,
logLevel: "info",
logFilter: "all",
logOrder: "asc",
};
export const useClashLog = () =>
useLocalStorage<IClashLog>("clash-log", defaultClashLog, {
serializer: JSON.stringify,
deserializer: JSON.parse,
});
This hook stores the enable toggle, logLevel (debug/info/warn/error), logFilter, and logOrder settings under the localStorage key clash-log.
Live Log Streaming and Retrieval
The useLogData hook in src/hooks/use-log-data.ts manages the WebSocket connection to Mihomo and buffers incoming messages.
| Step | Implementation Detail |
|---|---|
| Subscription Key | Builds getClashLog-${date} topic based on logLevel and enable settings |
| WebSocket Connection | Calls MihomoWebSocket.connect_logs(logLevel) to establish the stream |
| Buffering | Incoming messages are buffered and flushed every 50 ms (FLUSH_DELAY_MS = 50) to prevent UI churn |
| Parsing | Raw JSON messages are parsed into ILogItem objects; entries not matching the selected logLevel are filtered out |
| Timestamping | Human-readable timestamps are added using dayjs in MM-DD HH:mm:ss format |
| Initial Load | On first WS connection, the hook calls getClashLogs() (Tauri command) to fetch historic logs from the core's filesystem |
| Reactivity | Whenever logLevel changes, the subscription refreshes automatically |
Historic Log Parsing
The getClashLogs function in [src/services/cmds.ts](https://github.com/clash-verge-rev/clash-verge-rev/blob/dev/src/services/cmds.ts#L223-L244) parses raw log files from the Mihomo core using two regex patterns:
export async function getClashLogs() {
const regex = /time="(.+?)"\s+level=(.+?)\s+msg="(.+?)"/;
const newRegex = /(.+?)\s+(.+?)\s+(.+)/;
const logs = await invoke<string[]>("get_clash_logs");
return logs.reduce<ILogItem[]>((acc, log) => {
const result = log.match(regex);
if (result) {
const [_, _time, type, payload] = result;
const time = dayjs(_time).format("MM-DD HH:mm:ss");
acc.push({ time, type, payload });
return acc;
}
const result2 = log.match(newRegex);
if (result2) {
const [_, time, type, payload] = result2;
acc.push({ time, type, payload });
}
return acc;
}, []);
}
This function handles both legacy and new log formats, normalizing them into structured objects with time, type, and payload properties.
Navigating the Logs Interface
The LogPage component in src/pages/logs.tsx provides the diagnostic interface with several interactive features.
Filtering and Searching
The UI applies client-side filtering on the array returned by useLogData:
const filteredLogs = useMemo(() => {
return logData.filter((data) => {
const searchText = `${data.time || ""} ${data.type} ${data.payload}`.toLowerCase();
const matchesSearch = match(searchText);
return (logState == "all" ? true : data.type.includes(logState)) && matchesSearch;
});
}, [logData, logState, match]);
- Level Filter: Select
all,debug,info,warn, orerrorto show only entries of that severity. - Search: The search box queries across timestamps, log types, and message payloads simultaneously.
Sorting and Display
- Order Toggle: Switch between ascending and descending chronological order using the
logOrdersetting fromuseClashLog. - Virtualized Rendering: The interface uses
react-virtuosoto render only visible log rows, maintaining performance even with thousands of entries. - Clear History: The clear button calls
refreshGetClashLog(true), which resets the SWR cache and empties the displayed list without affecting stored files.
Programmatic Log Access
For advanced diagnostics or integration with external tools, you can interact with the logging system programmatically.
Fetching Raw Logs via Tauri Command
import { getClashLogs } from '@/services/cmds';
// Example: fetch and print the last 20 error-level logs
async function printRecentErrors() {
const all = await getClashLogs();
const errors = all.filter(l => l.type === 'error').slice(-20);
errors.forEach(l => console.log(`[${l.time}] ${l.payload}`));
}
printRecentErrors();
Adjusting Log Verbosity at Runtime
import { useClashLog } from '@/hooks/use-clash-log';
// Switch to "debug" level to capture all diagnostics
const [, setClashLog] = useClashLog();
setClashLog(prev => ({ ...prev, logLevel: 'debug' }));
Subscribing to Real-Time Logs via WebSocket
import { MihomoWebSocket } from 'tauri-plugin-mihomo-api';
async function subscribeToLogs() {
const ws = await MihomoWebSocket.connect_logs('info');
ws.onMessage(msg => console.log('WS LOG →', msg));
}
subscribeToLogs();
Clearing the Log Buffer
import { useLogData } from '@/hooks/use-log-data';
const { refreshGetClashLog } = useLogData();
// Force reset of the SWR cache to wipe the UI list
refreshGetClashLog(true);
Key Files for Log Diagnostics
Understanding the source structure helps when extending or debugging the logging functionality:
| File | Purpose | Location |
|---|---|---|
use-clash-log.ts |
Manages localStorage preferences for log settings | src/hooks/use-clash-log.ts |
use-log-data.ts |
Handles WebSocket connections, buffering, and real-time data flow | src/hooks/use-log-data.ts |
cmds.ts |
Parses raw Mihomo log files into structured data | src/services/cmds.ts (lines 223-244) |
logs.tsx |
Main UI component with filtering, search, and virtualization | src/pages/logs.tsx |
log-item.tsx |
Renders individual log entry rows | src/components/log/log-item.tsx |
Summary
- Three-layer architecture: Settings (
use-clash-log.ts), data streaming (use-log-data.ts), and UI presentation (logs.tsx) work together to deliver diagnostics. - Real-time and historic data: WebSocket connections provide live logs with 50ms buffering, while
getClashLogs()fetches persisted entries from the filesystem. - Flexible filtering: Client-side filtering supports severity levels (debug/info/warn/error), text search across timestamps and payloads, and ascending/descending sort order.
- Programmatic access: Developers can invoke
getClashLogs(), subscribe to WebSocket streams viaMihomoWebSocket, or manipulate log settings through theuseClashLoghook.
Frequently Asked Questions
How do I change the log verbosity level in Clash Verge Rev?
Navigate to the Logs page and use the level selector to switch between debug, info, warn, and error. This updates the logLevel property in useClashLog, which triggers a WebSocket resubscription to the Mihomo core with the new verbosity filter. Lower levels like "debug" capture all diagnostics, while "error" shows only critical failures.
Where are the log files stored on my system?
Clash Verge Rev retrieves historic logs via the Tauri command get_clash_logs, which reads files generated by the Mihomo core from the application's data directory. The exact filesystem path depends on your operating system (typically within the OS-specific app data folder), but you do not need to access these files directly since the UI and getClashLogs() function parse and display them automatically.
Why are my logs not updating in real-time?
Real-time updates require the enable setting to be true in useClashLog and an active WebSocket connection to the Mihomo core. If logs appear stale, verify that live logging is enabled in the UI settings. The system uses a 50ms buffer (FLUSH_DELAY_MS) to batch updates, so there is a brief delay between core events and UI rendering. If the connection drops, the hook automatically attempts to reconnect and fetch historic logs via getClashLogs().
Can I export logs from Clash Verge Rev for external analysis?
While the application does not include a built-in export button in the standard UI, you can programmatically retrieve structured log data using the getClashLogs() function from src/services/cmds.ts. This returns an array of ILogItem objects with time, type, and payload properties that you can serialize to JSON or CSV. For real-time export, subscribe to the WebSocket stream via MihomoWebSocket.connect_logs() and write incoming messages to a file.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →