in mem logs & syslog

This commit is contained in:
Alireza Ahmadi
2023-07-30 16:29:49 +02:00
parent 49eedb7057
commit 59204cdb0c
4 changed files with 111 additions and 38 deletions

View File

@@ -1,25 +1,47 @@
package logger package logger
import ( import (
"github.com/op/go-logging" "fmt"
"os" "os"
"time"
"github.com/op/go-logging"
) )
var logger *logging.Logger var logger *logging.Logger
var logBuffer []struct {
time string
level logging.Level
log string
}
func init() { func init() {
InitLogger(logging.INFO) InitLogger(logging.INFO)
} }
func InitLogger(level logging.Level) { func InitLogger(level logging.Level) {
format := logging.MustStringFormatter(
`%{time:2006/01/02 15:04:05} %{level} - %{message}`,
)
newLogger := logging.MustGetLogger("x-ui") newLogger := logging.MustGetLogger("x-ui")
backend := logging.NewLogBackend(os.Stderr, "", 0) 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}`,
)
}
backendFormatter := logging.NewBackendFormatter(backend, format) backendFormatter := logging.NewBackendFormatter(backend, format)
backendLeveled := logging.AddModuleLevel(backendFormatter) backendLeveled := logging.AddModuleLevel(backendFormatter)
backendLeveled.SetLevel(level, "") backendLeveled.SetLevel(level, "x-ui")
newLogger.SetBackend(backendLeveled) newLogger.SetBackend(backendLeveled)
logger = newLogger logger = newLogger
@@ -27,32 +49,70 @@ func InitLogger(level logging.Level) {
func Debug(args ...interface{}) { func Debug(args ...interface{}) {
logger.Debug(args...) logger.Debug(args...)
addToBuffer("DEBUG", fmt.Sprint(args...))
} }
func Debugf(format string, args ...interface{}) { func Debugf(format string, args ...interface{}) {
logger.Debugf(format, args...) logger.Debugf(format, args...)
addToBuffer("DEBUG", fmt.Sprintf(format, args...))
} }
func Info(args ...interface{}) { func Info(args ...interface{}) {
logger.Info(args...) logger.Info(args...)
addToBuffer("INFO", fmt.Sprint(args...))
} }
func Infof(format string, args ...interface{}) { func Infof(format string, args ...interface{}) {
logger.Infof(format, args...) logger.Infof(format, args...)
addToBuffer("INFO", fmt.Sprintf(format, args...))
} }
func Warning(args ...interface{}) { func Warning(args ...interface{}) {
logger.Warning(args...) logger.Warning(args...)
addToBuffer("WARNING", fmt.Sprint(args...))
} }
func Warningf(format string, args ...interface{}) { func Warningf(format string, args ...interface{}) {
logger.Warningf(format, args...) logger.Warningf(format, args...)
addToBuffer("WARNING", fmt.Sprintf(format, args...))
} }
func Error(args ...interface{}) { func Error(args ...interface{}) {
logger.Error(args...) logger.Error(args...)
addToBuffer("ERROR", fmt.Sprint(args...))
} }
func Errorf(format string, args ...interface{}) { func Errorf(format string, args ...interface{}) {
logger.Errorf(format, args...) logger.Errorf(format, args...)
addToBuffer("ERROR", fmt.Sprintf(format, 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 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
} }

View File

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

View File

@@ -110,7 +110,7 @@
<a-col :sm="24" :md="12"> <a-col :sm="24" :md="12">
<a-card hoverable :class="themeSwitcher.darkCardClass"> <a-card hoverable :class="themeSwitcher.darkCardClass">
{{ i18n "menu.link" }}: {{ i18n "menu.link" }}:
<a-tag color="blue" style="cursor: pointer;" @click="openLogs(20)">{{ 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="openConfig">{{ i18n "pages.index.config" }}</a-tag>
<a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag> <a-tag color="blue" style="cursor: pointer;" @click="openBackup">{{ i18n "pages.index.backup" }}</a-tag>
</a-card> </a-card>
@@ -211,7 +211,7 @@
<a-form-item label="Count"> <a-form-item label="Count">
<a-select v-model="logModal.rows" <a-select v-model="logModal.rows"
style="width: 80px" style="width: 80px"
@change="openLogs(logModal.rows)" @change="openLogs()"
:dropdown-class-name="themeSwitcher.darkCardClass"> :dropdown-class-name="themeSwitcher.darkCardClass">
<a-select-option value="10">10</a-select-option> <a-select-option value="10">10</a-select-option>
<a-select-option value="20">20</a-select-option> <a-select-option value="20">20</a-select-option>
@@ -219,8 +219,22 @@
<a-select-option value="100">100</a-select-option> <a-select-option value="100">100</a-select-option>
</a-select> </a-select>
</a-form-item> </a-form-item>
<a-form-item label="Log Level">
<a-select v-model="logModal.level"
style="width: 120px"
@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>
<a-select-option value="warning">Warning</a-select-option>
<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> <a-form-item>
<button class="ant-btn ant-btn-primary" @click="openLogs(logModal.rows)"><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-form-item> <a-form-item>
<a-button type="primary" style="margin-bottom: 10px;" <a-button type="primary" style="margin-bottom: 10px;"
@@ -349,10 +363,11 @@
visible: false, visible: false,
logs: '', logs: '',
rows: 20, rows: 20,
show(logs, rows) { level: 'info',
syslog: false,
show(logs) {
this.visible = true; this.visible = true;
this.rows = rows; this.logs = logs? logs.join("\n"): "No Record...";
this.logs = logs.join("\n");
}, },
hide() { hide() {
this.visible = false; this.visible = false;
@@ -449,14 +464,14 @@
return; return;
} }
}, },
async openLogs(rows){ async openLogs(){
this.loading(true); this.loading(true);
const msg = await HttpUtil.post('server/logs/'+rows); const msg = await HttpUtil.post('server/logs/'+logModal.rows,{level: logModal.level, syslog: logModal.syslog});
this.loading(false); this.loading(false);
if (!msg.success) { if (!msg.success) {
return; return;
} }
logModal.show(msg.obj, rows); logModal.show(msg.obj);
}, },
async openConfig() { async openConfig() {
this.loading(true); this.loading(true);

View File

@@ -12,6 +12,7 @@ import (
"os" "os"
"os/exec" "os/exec"
"runtime" "runtime"
"strconv"
"strings" "strings"
"time" "time"
"x-ui/config" "x-ui/config"
@@ -334,27 +335,26 @@ func (s *ServerService) UpdateXray(version string) error {
} }
func (s *ServerService) GetLogs(count string) ([]string, error) { func (s *ServerService) GetLogs(count string, level string, syslog string) []string {
// Define the journalctl command and its arguments c, _ := strconv.Atoi(count)
var cmdArgs []string var lines []string
if runtime.GOOS == "linux" {
cmdArgs = []string{"journalctl", "-u", "x-ui", "--no-pager", "-n", count} 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 { } else {
return []string{"Unsupported operating system"}, nil lines = logger.GetLogs(c, level)
} }
// Run the command return lines
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
var out bytes.Buffer
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
return nil, err
}
lines := strings.Split(out.String(), "\n")
return lines, nil
} }
func (s *ServerService) GetConfigJson() (interface{}, error) { func (s *ServerService) GetConfigJson() (interface{}, error) {