# How Clash Nyanpasu Implements Traffic Monitoring and Data Visualization

> Explore how Clash Nyanpasu implements traffic monitoring and data visualization. Learn about real-time data gathering, buffering, and interactive chart rendering.

- Repository: [Nyanpasu/clash-nyanpasu](https://github.com/libnyanpasu/clash-nyanpasu)
- Tags: deep-dive
- Published: 2026-03-06

---

**Clash Nyanpasu gathers real-time network traffic statistics through a WebSocket connection to the Clash core, buffers the data in a React context provider, and renders interactive line charts using a custom hook and utility formatting functions.**

The repository `libnyanpasu/clash-nyanpasu` implements a three-layer architecture for traffic monitoring and data visualization that bridges the Rust-based backend with a React frontend. This article examines the specific implementation details, file paths, and code patterns used to stream, store, and display network throughput metrics.

## Backend WebSocket API Layer

The data acquisition starts in [`frontend/interface/src/ipc/use-clash-traffic.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-traffic.ts), where a custom hook opens a persistent WebSocket connection to the Clash core's `/traffic` endpoint.

The hook resolves the URL using `resolveUrl('traffic')`, then listens for incoming JSON messages containing `ClashTraffic` objects. Each message includes `up` and `down` fields representing bytes per second. The hook maintains a rolling buffer of traffic history, automatically truncating the array to `MAX_TRAFFIC_HISTORY` (defined in [`src/ipc/consts.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/src/ipc/consts.ts)) to prevent memory bloat.

```typescript
// frontend/interface/src/ipc/use-clash-traffic.ts
export const useClashTraffic = () => {
  const { trafficWS } = useWebSocket(resolveUrl('traffic'));
  const [data, setData] = useState<ClashTraffic[]>([]);

  useEffect(() => {
    if (!trafficWS) return;
    trafficWS.onmessage = (msg) => {
      const traffic = JSON.parse(msg.data) as ClashTraffic;
      setData((prev) => {
        const next = [...prev, traffic];
        // limit history length (MAX_TRAFFIC_HISTORY)
        return next.length > MAX_TRAFFIC_HISTORY ? next.slice(-MAX_TRAFFIC_HISTORY) : next;
      });
    };
  }, [trafficWS]);

  return { data };
};

```

## State Management and Context Provider

To share traffic data across the component tree without prop drilling, the application uses `ClashWsProvider` located in [`frontend/interface/src/provider/clash-ws-provider.tsx`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/provider/clash-ws-provider.tsx).

This React context provider consumes the `useClashTraffic` hook and exposes the traffic array to child components. It implements the `recordTraffic` boolean flag that allows users to pause data collection without closing the WebSocket connection. The provider also enforces the `MAX_TRAFFIC_HISTORY` limit at the context level, ensuring all dashboard components receive a consistently sized dataset.

```tsx
// frontend/interface/src/provider/clash-ws-provider.tsx
// Consumes useClashTraffic and provides traffic data to the app
const ClashWsProvider = ({ children }) => {
  const { data: trafficData } = useClashTraffic();
  const [recordTraffic, setRecordTraffic] = useState(true);
  
  // Filter or limit data based on recordTraffic flag
  const activeTraffic = recordTraffic ? trafficData : [];
  
  return (
    <ClashWsContext.Provider value={{ traffic: activeTraffic, recordTraffic, setRecordTraffic }}>
      {children}
    </ClashWsContext.Provider>
  );
};

```

## Frontend Visualization Components

The dashboard UI renders traffic metrics using two primary components: `DataPanel` for the main charts and `DataLine` for compact tile views.

### Data Panel and Chart Rendering

[`frontend/nyanpasu/src/components/dashboard/data-panel.tsx`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/nyanpasu/src/components/dashboard/data-panel.tsx) imports the `useClashTraffic` hook (exposed through the provider) and maps the traffic history into separate arrays for download and upload rates. It passes these arrays to the charting library as `LineChart` data props.

```tsx
// frontend/nyanpasu/src/components/dashboard/data-panel.tsx
import { useClashTraffic } from '@/hooks/useClashTraffic';

export const DataPanel = () => {
  const { data: traffic } = useClashTraffic();

  return (
    <div className="grid gap-4">
      <LineChart 
        data={traffic.map(t => t.down)} 
        title={t('Download Traffic')} 
      />
      <LineChart 
        data={traffic.map(t => t.up)} 
        title={t('Upload Traffic')} 
      />
    </div>
  );
};

```

### Traffic Formatting Utility

Raw byte values are converted to human-readable strings (KB, MB, GB) by `parseTraffic` in [`frontend/nyanpasu/src/utils/parse-traffic.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/nyanpasu/src/utils/parse-traffic.ts). This utility is used throughout the UI for tooltips, table cells, and the dashboard tiles.

```typescript
// frontend/nyanpasu/src/utils/parse-traffic.ts
export default function parseTraffic(bytes: number): string[] {
  if (bytes < 1024) return [bytes + ' B'];
  const units = ['KB', 'MB', 'GB', 'TB'];
  let i = -1;
  do {
    bytes /= 1024;
    i++;
  } while (bytes >= 1024 && i < units.length - 1);
  return [bytes.toFixed(2), units[i]];
}

```

### Compact Dashboard Tiles

For smaller UI surfaces, [`frontend/nyanpasu/src/components/dashboard/dataline.tsx`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/nyanpasu/src/components/dashboard/dataline.tsx) displays the most recent traffic sample (`data.at(-1)`) or the full raw history depending on the `type` prop, using `parseTraffic` for formatting.

## Configuration and Feature Toggles

Users can disable the traffic visualization through the `traffic_graph` setting defined in [`backend/tauri/src/config/nyanpasu/mod.rs`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/backend/tauri/src/config/nyanpasu/mod.rs). When set to `false`, the UI components conditionally skip rendering the chart elements, though the underlying WebSocket connection may remain active for other telemetry purposes.

## Summary

- **WebSocket Data Stream**: [`use-clash-traffic.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/use-clash-traffic.ts) establishes a persistent connection to the Clash core's `/traffic` endpoint and buffers `ClashTraffic` objects up to `MAX_TRAFFIC_HISTORY`.
- **React Context Provider**: [`clash-ws-provider.tsx`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/clash-ws-provider.tsx) distributes traffic data throughout the application and supports pausing collection via the `recordTraffic` flag.
- **Chart Rendering**: [`data-panel.tsx`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/data-panel.tsx) consumes the traffic hook and renders separate line charts for download and upload rates using the mapped `up` and `down` fields.
- **Data Formatting**: [`parse-traffic.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/parse-traffic.ts) converts raw byte counts into human-readable units (KB, MB, GB) for UI display.
- **User Control**: The `traffic_graph` configuration option in the Rust backend allows users to toggle the visualization feature on or off.

## Frequently Asked Questions

### How does Clash Nyanpasu collect real-time traffic data?

Clash Nyanpasu opens a WebSocket connection to the Clash core's `/traffic` endpoint via the `useClashTraffic` hook in [`frontend/interface/src/ipc/use-clash-traffic.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/interface/src/ipc/use-clash-traffic.ts). This hook listens for JSON messages containing upload and download byte counts, parses them into typed `ClashTraffic` objects, and maintains a rolling history buffer limited by `MAX_TRAFFIC_HISTORY`.

### What component renders the traffic charts in the dashboard?

The `DataPanel` component located at [`frontend/nyanpasu/src/components/dashboard/data-panel.tsx`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/nyanpasu/src/components/dashboard/data-panel.tsx) is responsible for rendering the traffic visualization. It imports the `useClashTraffic` hook to access the buffered traffic history, then maps the `up` and `down` fields into separate arrays passed as data props to line chart components for upload and download rates respectively.

### How does the application format raw byte values for display?

Raw byte values are converted to human-readable strings using the `parseTraffic` utility in [`frontend/nyanpasu/src/utils/parse-traffic.ts`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/frontend/nyanpasu/src/utils/parse-traffic.ts). This function divides the byte count by 1024 iteratively through unit tiers (KB, MB, GB, TB) until the value falls below 1024, then returns a formatted string with two decimal places and the appropriate unit suffix.

### Can users disable the traffic graph without stopping data collection?

Yes, users can toggle the traffic visualization through the `traffic_graph` configuration setting defined in [`backend/tauri/src/config/nyanpasu/mod.rs`](https://github.com/libnyanpasu/clash-nyanpasu/blob/main/backend/tauri/src/config/nyanpasu/mod.rs). When disabled, the UI components conditionally skip rendering the chart elements, but the underlying WebSocket connection managed by `useClashTraffic` typically remains active to support other telemetry features or immediate re-enabling of the graph.