mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-05-12 11:18:27 +00:00
log level & syslog
Co-Authored-By: Alireza Ahmadi <alireza7@gmail.com>
This commit is contained in:
parent
c46ced0c4c
commit
bf971911d5
5 changed files with 103 additions and 85 deletions
|
@ -1,98 +1,118 @@
|
||||||
package logger
|
package logger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"time"
|
||||||
|
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var logger *logging.Logger
|
||||||
logger *logging.Logger
|
var logBuffer []struct {
|
||||||
mu sync.Mutex
|
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) {
|
||||||
mu.Lock()
|
newLogger := logging.MustGetLogger("x-ui")
|
||||||
defer mu.Unlock()
|
var err error
|
||||||
|
var backend logging.Backend
|
||||||
|
var format logging.Formatter
|
||||||
|
ppid := os.Getppid()
|
||||||
|
|
||||||
if logger != nil {
|
if ppid == 1 {
|
||||||
return
|
backend, err = logging.NewSyslogBackend("")
|
||||||
|
format = logging.MustStringFormatter(
|
||||||
|
`%{level} - %{message}`,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
if err != nil || ppid != 1 {
|
||||||
format := logging.MustStringFormatter(
|
backend = logging.NewLogBackend(os.Stderr, "", 0)
|
||||||
|
format = logging.MustStringFormatter(
|
||||||
`%{time:2006/01/02 15:04:05} %{level} - %{message}`,
|
`%{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)
|
backendFormatter := logging.NewBackendFormatter(backend, format)
|
||||||
backendLeveled := logging.AddModuleLevel(backendFormatter)
|
backendLeveled := logging.AddModuleLevel(backendFormatter)
|
||||||
backendLeveled.SetLevel(level, "")
|
backendLeveled.SetLevel(level, "x-ui")
|
||||||
newLogger.SetBackend(logging.MultiLogger(backendLeveled))
|
newLogger.SetBackend(backendLeveled)
|
||||||
|
|
||||||
logger = newLogger
|
logger = newLogger
|
||||||
}
|
}
|
||||||
|
|
||||||
func Debug(args ...interface{}) {
|
func Debug(args ...interface{}) {
|
||||||
if logger != nil {
|
|
||||||
logger.Debug(args...)
|
logger.Debug(args...)
|
||||||
}
|
addToBuffer("DEBUG", fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Debugf(format string, args ...interface{}) {
|
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{}) {
|
func Info(args ...interface{}) {
|
||||||
if logger != nil {
|
|
||||||
logger.Info(args...)
|
logger.Info(args...)
|
||||||
}
|
addToBuffer("INFO", fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Infof(format string, args ...interface{}) {
|
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{}) {
|
func Warning(args ...interface{}) {
|
||||||
if logger != nil {
|
|
||||||
logger.Warning(args...)
|
logger.Warning(args...)
|
||||||
}
|
addToBuffer("WARNING", fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Warningf(format string, args ...interface{}) {
|
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{}) {
|
func Error(args ...interface{}) {
|
||||||
if logger != nil {
|
|
||||||
logger.Error(args...)
|
logger.Error(args...)
|
||||||
}
|
addToBuffer("ERROR", fmt.Sprint(args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func Errorf(format string, args ...interface{}) {
|
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{}) {
|
func addToBuffer(level string, newLog string) {
|
||||||
if logger != nil {
|
t := time.Now()
|
||||||
logger.Notice(args...)
|
if len(logBuffer) >= 10240 {
|
||||||
}
|
logBuffer = logBuffer[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func Noticef(format string, args ...interface{}) {
|
logLevel, _ := logging.LogLevel(level)
|
||||||
if logger != nil {
|
logBuffer = append(logBuffer, struct {
|
||||||
logger.Noticef(format, args...)
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -402,7 +402,7 @@ class HttpStreamSettings extends XrayCommonClass {
|
||||||
}
|
}
|
||||||
|
|
||||||
static fromJson(json={}) {
|
static fromJson(json={}) {
|
||||||
return new HttpStreamSettings(json.path, json.host, json.sockopt);
|
return new HttpStreamSettings(json.path, json.host);
|
||||||
}
|
}
|
||||||
|
|
||||||
toJson() {
|
toJson() {
|
||||||
|
@ -461,8 +461,7 @@ class GrpcStreamSettings extends XrayCommonClass {
|
||||||
static fromJson(json={}) {
|
static fromJson(json={}) {
|
||||||
return new GrpcStreamSettings(
|
return new GrpcStreamSettings(
|
||||||
json.serviceName,
|
json.serviceName,
|
||||||
json.multiMode,
|
json.multiMode
|
||||||
json.sockopt
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,12 +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")
|
||||||
logLevel := c.PostForm("logLevel")
|
level := c.PostForm("level")
|
||||||
logs, err := a.serverService.GetLogs(count, logLevel)
|
syslog := c.PostForm("syslog")
|
||||||
if err != nil {
|
logs := a.serverService.GetLogs(count, level, syslog)
|
||||||
jsonMsg(c, "getLogs", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
jsonObj(c, logs, nil)
|
jsonObj(c, logs, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -86,7 +86,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(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="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>
|
||||||
|
@ -253,7 +253,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, logModal.logLevel)"
|
@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>
|
||||||
|
@ -262,9 +262,9 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
<a-form-item label="Log Level">
|
<a-form-item label="Log Level">
|
||||||
<a-select v-model="logModal.logLevel"
|
<a-select v-model="logModal.level"
|
||||||
style="width: 120px"
|
style="width: 120px"
|
||||||
@change="openLogs(logModal.rows, logModal.logLevel)"
|
@change="openLogs()"
|
||||||
:dropdown-class-name="themeSwitcher.darkCardClass">
|
:dropdown-class-name="themeSwitcher.darkCardClass">
|
||||||
<a-select-option value="debug">Debug</a-select-option>
|
<a-select-option value="debug">Debug</a-select-option>
|
||||||
<a-select-option value="info">Info</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-option value="err">Error</a-select-option>
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-form-item>
|
</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, 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-form-item>
|
<a-form-item>
|
||||||
<a-button type="primary" style="margin-bottom: 10px;"
|
<a-button type="primary" style="margin-bottom: 10px;"
|
||||||
|
@ -409,11 +412,11 @@
|
||||||
visible: false,
|
visible: false,
|
||||||
logs: '',
|
logs: '',
|
||||||
rows: 20,
|
rows: 20,
|
||||||
logLevel: 'info',
|
level: 'info',
|
||||||
show(logs, rows) {
|
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;
|
||||||
|
@ -514,14 +517,14 @@
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async openLogs(rows, logLevel) {
|
async openLogs(){
|
||||||
this.loading(true);
|
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);
|
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);
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -378,28 +379,26 @@ func (s *ServerService) UpdateXray(version string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetLogs(count string, logLevel string) ([]string, error) {
|
func (s *ServerService) GetLogs(count string, level string, syslog string) []string {
|
||||||
var cmdArgs []string
|
c, _ := strconv.Atoi(count)
|
||||||
if runtime.GOOS == "linux" {
|
var lines []string
|
||||||
cmdArgs = []string{"journalctl", "-u", "x-ui", "--no-pager", "-n", count}
|
|
||||||
if logLevel != "" {
|
|
||||||
cmdArgs = append(cmdArgs, "-p", logLevel)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return []string{"Unsupported operating system"}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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:]...)
|
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||||
var out bytes.Buffer
|
var out bytes.Buffer
|
||||||
cmd.Stdout = &out
|
cmd.Stdout = &out
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return []string{"Failed to run journalctl command!"}
|
||||||
|
}
|
||||||
|
lines = strings.Split(out.String(), "\n")
|
||||||
|
} else {
|
||||||
|
lines = logger.GetLogs(c, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
lines := strings.Split(out.String(), "\n")
|
return lines
|
||||||
|
|
||||||
return lines, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetConfigJson() (interface{}, error) {
|
func (s *ServerService) GetConfigJson() (interface{}, error) {
|
||||||
|
|
Loading…
Reference in a new issue