diff options
| author | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-07-31 19:41:47 +0300 |
|---|---|---|
| committer | MHSanaei <ho3ein.sanaei@gmail.com> | 2023-07-31 19:41:47 +0300 |
| commit | bf971911d50b26492fc27b4f904026ee73c0c918 (patch) | |
| tree | 3bb247ea7cc44b22bdcd4c3fef7a72a1e4d07daf | |
| parent | c46ced0c4c57bd9e243bca1b068017aa8a97f4b0 (diff) | |
log level & syslog
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
| -rw-r--r-- | logger/logger.go | 114 | ||||
| -rw-r--r-- | web/assets/js/model/xray.js | 5 | ||||
| -rw-r--r-- | web/controller/server.go | 9 | ||||
| -rw-r--r-- | web/html/xui/index.html | 27 | ||||
| -rw-r--r-- | web/service/server.go | 35 |
5 files changed, 104 insertions, 86 deletions
diff --git a/logger/logger.go b/logger/logger.go index 6e49c850..6e824c78 100644 --- a/logger/logger.go +++ b/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 } diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index 94dc4eaa..bf766cf0 100644 --- a/web/assets/js/model/xray.js +++ b/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 ); } diff --git a/web/controller/server.go b/web/controller/server.go index 086d9ec9..10baacb9 100644 --- a/web/controller/server.go +++ b/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) } diff --git a/web/html/xui/index.html b/web/html/xui/index.html index 236ab010..0942b0ad 100644 --- a/web/html/xui/index.html +++ b/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); diff --git a/web/service/server.go b/web/service/server.go index 3de5f3ff..376126df 100644 --- a/web/service/server.go +++ b/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) { |
