Procházet zdrojové kódy

网络服务WebUI动态改变输出日志级别,完成

niujiuru před 2 týdny
rodič
revize
8394210021

+ 5 - 4
web-ui.service/web/pages/page2.html

@@ -68,18 +68,19 @@
           <div class="card-header">
             <h2>联网服务</h2>
             <div class="log-actions">
-              <select class="log-level-select" id="logLevel">
+              <select class="log-level-select" id="logLevel" onchange="setNetLogLevel()">
                 <option value="trace">trace</option>
                 <option value="debug">debug</option>
                 <option value="info" selected>info</option>
                 <option value="error">error</option>
                 <option value="fatal">fatal</option>
               </select>
-              <button class="btn" title="点击设置日志级别" onclick="setLogLevel()">📝</button>
               <span style="margin:0 1px;"></span>
-              <button class="btn" title="点击下载日志文件" onclick="downloadLogFile()">⬇️📄</button>
+              <button class="btn" title="点击清屏日志输出" onclick="clearLog('text4')">📋✕</button>
               <span style="margin:0 1px;"></span>
-              <button class="btn" title="点击重启联网服务" onclick="restartNSvc()">🔄🌐</button>
+              <button class="btn" title="点击下载日志文件" onclick="downloadNetLogFile()">📋⬇️</button>
+              <span style="margin:0 1px;"></span>
+              <button class="btn" title="点击重启联网服务" onclick="restartNetService()">🔄🌐</button>
             </div>
           </div>
           <pre class="output" id="text4">自动实时获取数据...</pre>

+ 2 - 2
web-ui.service/web/static/css/app.css

@@ -149,11 +149,11 @@ p{
 
 /* 日志色 */
 .log-trace {
-    color:#7f8c99;
+    color:#60a5fa;
 }
 
 .log-debug {
-    color:#61afef;
+    color:#3b82f6;
 }
 
 .log-info {

+ 2 - 1
web-ui.service/web/static/css/page2.css

@@ -155,7 +155,8 @@
     font-family: ui-monospace, Consolas, monospace;
     color: #cbd5e1;
     overflow: auto;
-    white-space: pre;
+    white-space: pre-wrap;
+    word-break: break-all;
     line-height: 1.6;
 }
 

+ 12 - 15
web-ui.service/web/static/js/log-stream.js

@@ -30,20 +30,6 @@ function colorLog(line) {
     return s;
 }
 
-const monthMap = {
-    Jan: '01', Feb: '02', Mar: '03', Apr: '04',
-    May: '05', Jun: '06', Jul: '07', Aug: '08',
-    Sep: '09', Oct: '10', Nov: '11', Dec: '12'
-};
-
-function formatLog(line) {
-    return line.replace(
-        /^(\w{3})\s+(\d{1,2})\s+(\d{2}:\d{2}:\d{2})\s+\S+\s+[^\s]+\[\d+\]:\s+\[([a-z]+)\]:\s+\[[^\]]+\](.*)/i,
-        (_, mon, day, time, level, msg) =>
-            `${monthMap[mon]}-${day.padStart(2, '0')} ${time} ${level.toUpperCase()}${msg}`
-    );
-}
-
 function connectLog(unit, target) {
     const el = typeof target === "string"
         ? document.getElementById(target)
@@ -86,7 +72,6 @@ function connectLog(unit, target) {
         }
 
         el.innerHTML = logLines
-            .map(formatLog)
             .map(colorLog)
             .join("<br>") + "<br><br><br>";
 
@@ -117,3 +102,15 @@ function disconnectLog() {
 function getCurrentUnit() {
     return currentUnit;
 }
+
+function clearLog(target) {
+    logLines = [];
+
+    const el = typeof target === "string"
+        ? document.getElementById(target)
+        : target;
+
+    if (el) {
+        el.textContent = "";
+    }
+}

+ 58 - 20
web-ui.service/web/static/js/page2.js

@@ -1,13 +1,11 @@
 async function apiGetRetry(url, retry = false) {
   try {
     const res = await fetch(url);
-
     if (!res.ok) {
       throw new Error("HTTP " + res.status);
     }
 
     const text = await res.text();
-
     if (!text || text.trim() === "") {
       throw new Error("empty response");
     }
@@ -26,41 +24,81 @@ async function apiGetRetry(url, retry = false) {
 
 function getNetInfo1() {
   document.getElementById("text1").innerText = "";
+
   apiGetRetry("/api/network/interfaces")
-    .then(data => {
-      document.getElementById("text1").innerText = data;
-    })
-    .catch(() => {
-      document.getElementById("text1").innerText = "获取失败";
-    });
+  .then(data => {
+    document.getElementById("text1").innerText = data;
+  })
+  .catch(() => {
+    document.getElementById("text1").innerText = "获取失败";
+  });
 }
 
 function getNetInfo2() {
   document.getElementById("text2").innerText = "";
+
   apiGetRetry("/api/network/routes")
-    .then(data => {
-      document.getElementById("text2").innerText = data;
-    })
-    .catch(() => {
-      document.getElementById("text2").innerText = "获取失败";
-    });
+  .then(data => {
+    document.getElementById("text2").innerText = data;
+  })
+  .catch(() => {
+    document.getElementById("text2").innerText = "获取失败";
+  });
 }
 
 function getNetInfo3() {
   document.getElementById("text3").innerText = "";
+ 
   apiGetRetry("/api/network/dns")
-    .then(data => {
-      document.getElementById("text3").innerText = data;
-    })
-    .catch(() => {
-      document.getElementById("text3").innerText = "获取失败";
-    });
+  .then(data => {
+    document.getElementById("text3").innerText = data;
+  })
+  .catch(() => {
+    document.getElementById("text3").innerText = "获取失败";
+  });
+}
+
+let netLogLevel = "";
+function setNetLogLevel() {
+  const level = logLevel.value;
+
+  fetch("/api/network/loglevel", {
+    method: "POST",
+    headers: {"Content-Type": "application/json"},
+    body: JSON.stringify({level})
+  })
+  .then(async r => {
+    if (!r.ok) throw new Error(await r.text());
+    netLogLevel = level;
+  })
+  .catch(e => {
+    logLevel.value = netLogLevel;
+    alert("设置失败: " + e.message);
+  });
+}
+
+function getNetLogLevel() {
+  fetch("/api/network/loglevel")
+  .then(async r => {
+    if (!r.ok) throw new Error(await r.text());
+    return r.json();
+  })
+  .then(d => {
+    netLogLevel = d.log_level;
+    logLevel.value = d.log_level;
+  })
+  .catch(e => {
+    netLogLevel = "";
+    logLevel.value = "";
+    alert("获取失败: " + e.message);
+  });
 }
 
 function initPage2() {
   getNetInfo1();
   getNetInfo2();
   getNetInfo3();
+  getNetLogLevel();
   connectLog("yfkj-networkd.service", "text4");
 }
 

+ 50 - 2
web-ui.service/web_handler.go

@@ -9,6 +9,8 @@ import (
 	"os"
 	"os/exec"
 	"strings"
+
+	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
 )
 
 type LoginReq struct {
@@ -144,10 +146,11 @@ func serviceLogHandler(w http.ResponseWriter, r *http.Request) {
 		"-u",
 		unit,
 		"-n",
-		"100",
+		"10",
 		"--no-pager",
+		"-q",
 		"-o",
-		"short",
+		"short-iso",
 	)
 
 	stdout, err := cmd.StdoutPipe()
@@ -205,3 +208,48 @@ func netRoutes(w http.ResponseWriter, r *http.Request) {
 func netDNS(w http.ResponseWriter, r *http.Request) {
 	runShellAndWrite(w, "cat /etc/resolv.conf")
 }
+
+func callLocalRPC(w http.ResponseWriter, r *http.Request, port int, method string, params any) {
+	client, err := jsonrpc2.NewRPCClient(fmt.Sprintf("http://127.0.0.1:%d/rpc", port))
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	resp, err := client.Call(r.Context(), method, params)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	w.Header().Set("Content-Type", "application/json; charset=utf-8")
+	json.NewEncoder(w).Encode(resp.Result)
+}
+
+func serviceLogLevel(w http.ResponseWriter, r *http.Request, port int) {
+	switch r.Method {
+	case http.MethodGet:
+		callLocalRPC(w, r, port, "basic.getLogLevel", nil)
+
+	case http.MethodPost:
+		var req struct {
+			Level string `json:"level"`
+		}
+
+		if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
+			http.Error(w, err.Error(), http.StatusBadRequest)
+			return
+		}
+
+		callLocalRPC(w, r, port, "basic.setLogLevel", map[string]string{"log_level": req.Level})
+
+	default:
+		http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
+	}
+}
+
+func serviceLogLevelHandler(port int) http.HandlerFunc {
+	return func(w http.ResponseWriter, r *http.Request) {
+		serviceLogLevel(w, r, port)
+	}
+}

+ 5 - 0
web-ui.service/web_route.go

@@ -42,6 +42,11 @@ var routes = []Route{
 		"/api/network/dns",
 		netDNS,
 	},
+
+	{
+		"/api/network/loglevel",
+		serviceLogLevelHandler(7000),
+	},
 }
 
 func registerRoutes(mux *http.ServeMux) {