Pārlūkot izejas kodu

log level & syslog

Co-Authored-By: Alireza Ahmadi <[email protected]>
MHSanaei 1 gadu atpakaļ
vecāks
revīzija
bf971911d5
5 mainītis faili ar 104 papildinājumiem un 86 dzēšanām
  1. 67 47
      logger/logger.go
  2. 2 3
      web/assets/js/model/xray.js
  3. 3 6
      web/controller/server.go
  4. 15 12
      web/html/xui/index.html
  5. 17 18
      web/service/server.go

+ 67 - 47
logger/logger.go

@@ -1,98 +1,118 @@
 package logger
 
 import (
+	"fmt"
 	"os"
-	"sync"
+	"time"
 
 	"github.com/op/go-logging"
 )
 
-var (
-	logger *logging.Logger
-	mu     sync.Mutex
-)
+var logger *logging.Logger
+var logBuffer []struct {
+	time  string
+	level logging.Level
+	log   string
+}
 
 func init() {
 	InitLogger(logging.INFO)
 }
 
 func InitLogger(level logging.Level) {
-	mu.Lock()
-	defer mu.Unlock()
-
-	if logger != nil {
-		return
+	newLogger := logging.MustGetLogger("x-ui")
+	var err error
+	var backend logging.Backend
+	var format logging.Formatter
+	ppid := os.Getppid()
+
+	if ppid == 1 {
+		backend, err = logging.NewSyslogBackend("")
+		format = logging.MustStringFormatter(
+			`%{level} - %{message}`,
+		)
+	}
+	if err != nil || ppid != 1 {
+		backend = logging.NewLogBackend(os.Stderr, "", 0)
+		format = logging.MustStringFormatter(
+			`%{time:2006/01/02 15:04:05} %{level} - %{message}`,
+		)
 	}
 
-	format := logging.MustStringFormatter(
-		`%{time:2006/01/02 15:04:05} %{level} - %{message}`,
-	)
-	newLogger := logging.MustGetLogger("x-ui")
-	backend := logging.NewLogBackend(os.Stderr, "", 0)
 	backendFormatter := logging.NewBackendFormatter(backend, format)
 	backendLeveled := logging.AddModuleLevel(backendFormatter)
-	backendLeveled.SetLevel(level, "")
-	newLogger.SetBackend(logging.MultiLogger(backendLeveled))
+	backendLeveled.SetLevel(level, "x-ui")
+	newLogger.SetBackend(backendLeveled)
 
 	logger = newLogger
 }
 
 func Debug(args ...interface{}) {
-	if logger != nil {
-		logger.Debug(args...)
-	}
+	logger.Debug(args...)
+	addToBuffer("DEBUG", fmt.Sprint(args...))
 }
 
 func Debugf(format string, args ...interface{}) {
-	if logger != nil {
-		logger.Debugf(format, args...)
-	}
+	logger.Debugf(format, args...)
+	addToBuffer("DEBUG", fmt.Sprintf(format, args...))
 }
 
 func Info(args ...interface{}) {
-	if logger != nil {
-		logger.Info(args...)
-	}
+	logger.Info(args...)
+	addToBuffer("INFO", fmt.Sprint(args...))
 }
 
 func Infof(format string, args ...interface{}) {
-	if logger != nil {
-		logger.Infof(format, args...)
-	}
+	logger.Infof(format, args...)
+	addToBuffer("INFO", fmt.Sprintf(format, args...))
 }
 
 func Warning(args ...interface{}) {
-	if logger != nil {
-		logger.Warning(args...)
-	}
+	logger.Warning(args...)
+	addToBuffer("WARNING", fmt.Sprint(args...))
 }
 
 func Warningf(format string, args ...interface{}) {
-	if logger != nil {
-		logger.Warningf(format, args...)
-	}
+	logger.Warningf(format, args...)
+	addToBuffer("WARNING", fmt.Sprintf(format, args...))
 }
 
 func Error(args ...interface{}) {
-	if logger != nil {
-		logger.Error(args...)
-	}
+	logger.Error(args...)
+	addToBuffer("ERROR", fmt.Sprint(args...))
 }
 
 func Errorf(format string, args ...interface{}) {
-	if logger != nil {
-		logger.Errorf(format, args...)
-	}
+	logger.Errorf(format, args...)
+	addToBuffer("ERROR", fmt.Sprintf(format, args...))
 }
 
-func Notice(args ...interface{}) {
-	if logger != nil {
-		logger.Notice(args...)
+func addToBuffer(level string, newLog string) {
+	t := time.Now()
+	if len(logBuffer) >= 10240 {
+		logBuffer = logBuffer[1:]
 	}
+
+	logLevel, _ := logging.LogLevel(level)
+	logBuffer = append(logBuffer, struct {
+		time  string
+		level logging.Level
+		log   string
+	}{
+		time:  t.Format("2006/01/02 15:04:05"),
+		level: logLevel,
+		log:   newLog,
+	})
 }
 
-func Noticef(format string, args ...interface{}) {
-	if logger != nil {
-		logger.Noticef(format, args...)
+func GetLogs(c int, level string) []string {
+	var output []string
+	logLevel, _ := logging.LogLevel(level)
+
+	for i := len(logBuffer) - 1; i >= 0 && len(output) <= c; i-- {
+		if logBuffer[i].level <= logLevel {
+			output = append(output, fmt.Sprintf("%s %s - %s", logBuffer[i].time, logBuffer[i].level, logBuffer[i].log))
+		}
 	}
+	return output
 }

+ 2 - 3
web/assets/js/model/xray.js

@@ -402,7 +402,7 @@ class HttpStreamSettings extends XrayCommonClass {
     }
 
     static fromJson(json={}) {
-        return new HttpStreamSettings(json.path, json.host, json.sockopt);
+        return new HttpStreamSettings(json.path, json.host);
     }
 
     toJson() {
@@ -461,8 +461,7 @@ class GrpcStreamSettings extends XrayCommonClass {
     static fromJson(json={}) {
         return new GrpcStreamSettings(
             json.serviceName,
-            json.multiMode,
-            json.sockopt
+            json.multiMode
             );
     }
 

+ 3 - 6
web/controller/server.go

@@ -118,12 +118,9 @@ func (a *ServerController) restartXrayService(c *gin.Context) {
 
 func (a *ServerController) getLogs(c *gin.Context) {
 	count := c.Param("count")
-	logLevel := c.PostForm("logLevel")
-	logs, err := a.serverService.GetLogs(count, logLevel)
-	if err != nil {
-		jsonMsg(c, "getLogs", err)
-		return
-	}
+	level := c.PostForm("level")
+	syslog := c.PostForm("syslog")
+	logs := a.serverService.GetLogs(count, level, syslog)
 	jsonObj(c, logs, nil)
 }
 

+ 15 - 12
web/html/xui/index.html

@@ -86,7 +86,7 @@
                     <a-col :sm="24" :md="12">
                         <a-card hoverable :class="themeSwitcher.darkCardClass">
                             {{ i18n "menu.link" }}:
-                            <a-tag color="blue" style="cursor: pointer;" @click="openLogs(logModal.rows, logModal.logLevel)">{{ i18n "pages.index.logs" }}</a-tag>
+                            <a-tag color="blue" style="cursor: pointer;" @click="openLogs()">{{ i18n "pages.index.logs" }}</a-tag>
                             <a-tag color="blue" style="cursor: pointer;" @click="openConfig">{{ i18n "pages.index.config" }}</a-tag>
                             <a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag>
                         </a-card>
@@ -253,7 +253,7 @@
             <a-form-item label="Count">
                 <a-select v-model="logModal.rows"
                 style="width: 80px"
-                @change="openLogs(logModal.rows, logModal.logLevel)"
+                @change="openLogs()"
                 :dropdown-class-name="themeSwitcher.darkCardClass">
                     <a-select-option value="10">10</a-select-option>
                     <a-select-option value="20">20</a-select-option>
@@ -262,9 +262,9 @@
                 </a-select>
             </a-form-item>
             <a-form-item label="Log Level">
-                <a-select v-model="logModal.logLevel"
+                <a-select v-model="logModal.level"
                 style="width: 120px"
-                @change="openLogs(logModal.rows, logModal.logLevel)"
+                @change="openLogs()"
                 :dropdown-class-name="themeSwitcher.darkCardClass">
                     <a-select-option value="debug">Debug</a-select-option>
                     <a-select-option value="info">Info</a-select-option>
@@ -273,8 +273,11 @@
                     <a-select-option value="err">Error</a-select-option>
                 </a-select>
             </a-form-item>
+            <a-form-item label="SysLog">
+                <a-checkbox v-model="logModal.syslog" @change="openLogs()"></a-checkbox>
+            </a-form-item>
             <a-form-item>
-                <button class="ant-btn ant-btn-primary" @click="openLogs(logModal.rows, logModal.logLevel)"><a-icon type="sync"></a-icon> Reload</button>
+                <button class="ant-btn ant-btn-primary" @click="openLogs()"><a-icon type="sync"></a-icon> Reload</button>
             </a-form-item>
             <a-form-item>
                 <a-button type="primary" style="margin-bottom: 10px;"
@@ -409,11 +412,11 @@
         visible: false,
         logs: '',
         rows: 20,
-        logLevel: 'info',
-        show(logs, rows) {
+        level: 'info',
+        syslog: false,
+        show(logs) {
             this.visible = true;
-            this.rows = rows;
-            this.logs = logs.join("\n");
+            this.logs = logs? logs.join("\n"): "No Record...";
         },
         hide() {
             this.visible = false;
@@ -514,14 +517,14 @@
                     return;
                 }
             },
-            async openLogs(rows, logLevel) {
+            async openLogs(){
                 this.loading(true);
-                const msg = await HttpUtil.post('server/logs/' + rows, { logLevel: `${logLevel}` });
+                const msg = await HttpUtil.post('server/logs/'+logModal.rows,{level: logModal.level, syslog: logModal.syslog});
                 this.loading(false);
                 if (!msg.success) {
                     return;
                 }
-                logModal.show(msg.obj, rows);
+                logModal.show(msg.obj);
             },
             async openConfig() {
                 this.loading(true);

+ 17 - 18
web/service/server.go

@@ -12,6 +12,7 @@ import (
 	"os"
 	"os/exec"
 	"runtime"
+	"strconv"
 	"strings"
 	"time"
 
@@ -378,28 +379,26 @@ func (s *ServerService) UpdateXray(version string) error {
 	return nil
 }
 
-func (s *ServerService) GetLogs(count string, logLevel string) ([]string, error) {
-	var cmdArgs []string
-	if runtime.GOOS == "linux" {
-		cmdArgs = []string{"journalctl", "-u", "x-ui", "--no-pager", "-n", count}
-		if logLevel != "" {
-			cmdArgs = append(cmdArgs, "-p", logLevel)
+func (s *ServerService) GetLogs(count string, level string, syslog string) []string {
+	c, _ := strconv.Atoi(count)
+	var lines []string
+
+	if syslog == "true" {
+		cmdArgs := []string{"journalctl", "-u", "x-ui", "--no-pager", "-n", count, "-p", level}
+		// Run the command
+		cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
+		var out bytes.Buffer
+		cmd.Stdout = &out
+		err := cmd.Run()
+		if err != nil {
+			return []string{"Failed to run journalctl command!"}
 		}
+		lines = strings.Split(out.String(), "\n")
 	} else {
-		return []string{"Unsupported operating system"}, nil
-	}
-
-	cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
-	var out bytes.Buffer
-	cmd.Stdout = &out
-	err := cmd.Run()
-	if err != nil {
-		return nil, err
+		lines = logger.GetLogs(c, level)
 	}
 
-	lines := strings.Split(out.String(), "\n")
-
-	return lines, nil
+	return lines
 }
 
 func (s *ServerService) GetConfigJson() (interface{}, error) {