diff --git a/src/components/layout/layout-traffic.tsx b/src/components/layout/layout-traffic.tsx
index 9659eea539769a14c7f384107f25d67ed4633837..19db259729766e502570986d118215ed17d86025 100644
--- a/src/components/layout/layout-traffic.tsx
+++ b/src/components/layout/layout-traffic.tsx
@@ -7,9 +7,10 @@ import { listen } from "@tauri-apps/api/event";
 import { ApiType } from "../../services/types";
 import { getInfomation } from "../../services/api";
 import { getVergeConfig } from "../../services/cmds";
-import { atomClashPort } from "../../states/setting";
-import parseTraffic from "../../utils/parse-traffic";
+import { atomClashPort } from "../../services/states";
+import useLogSetup from "./use-log-setup";
 import useTrafficGraph from "./use-traffic-graph";
+import parseTraffic from "../../utils/parse-traffic";
 
 const LayoutTraffic = () => {
   const portValue = useRecoilValue(atomClashPort);
@@ -21,6 +22,9 @@ const LayoutTraffic = () => {
   const { data } = useSWR("getVergeConfig", getVergeConfig);
   const trafficGraph = data?.traffic_graph ?? true;
 
+  // setup log ws during layout
+  useLogSetup();
+
   useEffect(() => {
     let unlisten: () => void = null!;
 
diff --git a/src/components/layout/use-log-setup.ts b/src/components/layout/use-log-setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6d343045b0312488280fc3b5a2fe4953fc12dbc0
--- /dev/null
+++ b/src/components/layout/use-log-setup.ts
@@ -0,0 +1,49 @@
+import dayjs from "dayjs";
+import { useEffect } from "react";
+import { useSetRecoilState } from "recoil";
+import { listen } from "@tauri-apps/api/event";
+import { ApiType } from "../../services/types";
+import { getInfomation } from "../../services/api";
+import { atomLogData } from "../../services/states";
+
+const MAX_LOG_NUM = 1000;
+
+// setup the log websocket
+export default function useLogSetup() {
+  const setLogData = useSetRecoilState(atomLogData);
+
+  useEffect(() => {
+    let ws: WebSocket = null!;
+    let unlisten: () => void = null!;
+
+    const handler = (event: MessageEvent<any>) => {
+      const data = JSON.parse(event.data) as ApiType.LogItem;
+      const time = dayjs().format("MM-DD HH:mm:ss");
+      setLogData((l) => {
+        if (l.length >= MAX_LOG_NUM) l.shift();
+        return [...l, { ...data, time }];
+      });
+    };
+
+    (async () => {
+      const { server = "", secret = "" } = await getInfomation();
+
+      ws = new WebSocket(`ws://${server}/logs?token=${secret}`);
+      ws.addEventListener("message", handler);
+
+      // reconnect the websocket
+      unlisten = await listen("restart_clash", async () => {
+        const { server = "", secret = "" } = await getInfomation();
+
+        ws?.close();
+        ws = new WebSocket(`ws://${server}/logs?token=${secret}`);
+        ws.addEventListener("message", handler);
+      });
+    })();
+
+    return () => {
+      ws?.close();
+      unlisten?.();
+    };
+  }, []);
+}
diff --git a/src/components/setting/setting-clash.tsx b/src/components/setting/setting-clash.tsx
index 395eab4975bd9af18d5655c3f41f8cc33e25a5dd..610a23f5ca24b49cd0b95bf81aeee5c6f8d77955 100644
--- a/src/components/setting/setting-clash.tsx
+++ b/src/components/setting/setting-clash.tsx
@@ -11,7 +11,7 @@ import {
   Typography,
 } from "@mui/material";
 import { ApiType } from "../../services/types";
-import { atomClashPort } from "../../states/setting";
+import { atomClashPort } from "../../services/states";
 import { patchClashConfig } from "../../services/cmds";
 import { SettingList, SettingItem } from "./setting";
 import { getClashConfig, getVersion, updateConfigs } from "../../services/api";
diff --git a/src/pages/logs.tsx b/src/pages/logs.tsx
index 882248e2a7c13479edbbc6c5efcd607ac2576b29..78b1f826a78ef408ff3838ec028768228bf422a8 100644
--- a/src/pages/logs.tsx
+++ b/src/pages/logs.tsx
@@ -1,38 +1,12 @@
-import dayjs from "dayjs";
-import { useEffect, useState } from "react";
+import { useRecoilState } from "recoil";
 import { Button, Paper } from "@mui/material";
 import { Virtuoso } from "react-virtuoso";
-import { ApiType } from "../services/types";
-import { getInfomation } from "../services/api";
+import { atomLogData } from "../services/states";
 import BasePage from "../components/base/base-page";
 import LogItem from "../components/log/log-item";
 
-let logCache: ApiType.LogItem[] = [];
-
 const LogPage = () => {
-  const [logData, setLogData] = useState(logCache);
-
-  useEffect(() => {
-    let ws: WebSocket | null = null;
-
-    getInfomation().then((result) => {
-      const { server = "", secret = "" } = result;
-      ws = new WebSocket(`ws://${server}/logs?token=${secret}`);
-
-      ws.addEventListener("message", (event) => {
-        const data = JSON.parse(event.data) as ApiType.LogItem;
-        const time = dayjs().format("MM-DD HH:mm:ss");
-        setLogData((l) => (logCache = [...l, { ...data, time }]));
-      });
-    });
-
-    return () => ws?.close();
-  }, []);
-
-  const onClear = () => {
-    setLogData([]);
-    logCache = [];
-  };
+  const [logData, setLogData] = useRecoilState(atomLogData);
 
   return (
     <BasePage
@@ -43,7 +17,7 @@ const LogPage = () => {
           size="small"
           sx={{ mt: 1 }}
           variant="contained"
-          onClick={onClear}
+          onClick={() => setLogData([])}
         >
           Clear
         </Button>
diff --git a/src/services/states.ts b/src/services/states.ts
new file mode 100644
index 0000000000000000000000000000000000000000..210c42735f2812972a9eb2648da6286260dce16a
--- /dev/null
+++ b/src/services/states.ts
@@ -0,0 +1,12 @@
+import { atom } from "recoil";
+import { ApiType } from "./types";
+
+export const atomClashPort = atom<number>({
+  key: "atomClashPort",
+  default: 0,
+});
+
+export const atomLogData = atom<ApiType.LogItem[]>({
+  key: "atomLogData",
+  default: [],
+});
diff --git a/src/states/setting.ts b/src/states/setting.ts
deleted file mode 100644
index a135de0c7af57322c508c41ce304a0ab875c5ecd..0000000000000000000000000000000000000000
--- a/src/states/setting.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { atom } from "recoil";
-
-export const atomClashPort = atom<number>({
-  key: "atomClashPort",
-  default: 0,
-});