mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-04-19 21:42:24 +00:00
chore: pretty logs
modal
This commit is contained in:
parent
c35179d924
commit
903332e1c9
5 changed files with 117 additions and 81 deletions
|
@ -34,9 +34,9 @@ func InitLogger(level logging.Level) {
|
|||
backend = logging.NewLogBackend(os.Stderr, "", 0)
|
||||
}
|
||||
if ppid > 0 && err != nil {
|
||||
format = logging.MustStringFormatter(`%{time:2006/01/02 15:04:05} %{level} - %{message}`)
|
||||
format = logging.MustStringFormatter(`%{time:2006/01/02 15:04:05} %{level} —— %{message}`)
|
||||
} else {
|
||||
format = logging.MustStringFormatter(`%{level} - %{message}`)
|
||||
format = logging.MustStringFormatter(`%{level} —— %{message}`)
|
||||
}
|
||||
|
||||
backendFormatter := logging.NewBackendFormatter(backend, format)
|
||||
|
@ -115,14 +115,12 @@ func addToBuffer(level string, newLog string) {
|
|||
})
|
||||
}
|
||||
|
||||
func GetLogs(c int, level string) []string {
|
||||
func GetLogs() []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))
|
||||
}
|
||||
for _, entry := range logBuffer {
|
||||
output = append(output, fmt.Sprintf("%s %s —— %s", entry.time, entry.level, entry.log))
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
|
|
@ -81,11 +81,20 @@ class PromiseUtil {
|
|||
}
|
||||
|
||||
class RandomUtil {
|
||||
static getSeq({ hasNumbers = true, hasLowercase = true, hasUppercase = true } = {}) {
|
||||
static getSeq({ type = "default", hasNumbers = true, hasLowercase = true, hasUppercase = true } = {}) {
|
||||
let seq = '';
|
||||
|
||||
switch (type) {
|
||||
case "hex":
|
||||
seq += "0123456789abcdef";
|
||||
break;
|
||||
default:
|
||||
if (hasNumbers) seq += "0123456789";
|
||||
if (hasLowercase) seq += "abcdefghijklmnopqrstuvwxyz";
|
||||
if (hasUppercase) seq += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
break;
|
||||
}
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
|
@ -107,7 +116,7 @@ class RandomUtil {
|
|||
static randomShortIds() {
|
||||
const lengths = [2, 4, 6, 8, 10, 12, 14, 16].sort(() => Math.random() - 0.5);
|
||||
|
||||
return lengths.map(len => this.randomSeq(len)).join(',');
|
||||
return lengths.map(len => this.randomSeq(len, { type: "hex" })).join(',');
|
||||
}
|
||||
|
||||
static randomLowerAndNum(len) {
|
||||
|
|
|
@ -118,10 +118,8 @@ func (a *ServerController) restartXrayService(c *gin.Context) {
|
|||
}
|
||||
|
||||
func (a *ServerController) getLogs(c *gin.Context) {
|
||||
count := c.Param("count")
|
||||
level := c.PostForm("level")
|
||||
syslog := c.PostForm("syslog")
|
||||
logs := a.serverService.GetLogs(count, level, syslog)
|
||||
logs := a.serverService.GetLogs(syslog)
|
||||
jsonObj(c, logs, nil)
|
||||
}
|
||||
|
||||
|
|
|
@ -296,22 +296,20 @@
|
|||
@click="openLogs()">
|
||||
</a-icon>
|
||||
</template>
|
||||
<a-space direction="vertical" size="small">
|
||||
<a-form layout="inline">
|
||||
<a-form-item style="margin-right: 0.5rem;">
|
||||
<a-input-group compact>
|
||||
<a-select size="small" v-model="logModal.rows" style="width:70px;"
|
||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select size="small" v-model="logModal.rows" style="width:70px;" dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option value="10">10</a-select-option>
|
||||
<a-select-option value="20">20</a-select-option>
|
||||
<a-select-option value="50">50</a-select-option>
|
||||
<a-select-option value="100">100</a-select-option>
|
||||
<a-select-option value="500">500</a-select-option>
|
||||
</a-select>
|
||||
<a-select size="small" v-model="logModal.level" style="width:95px;"
|
||||
@change="openLogs()" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select size="small" v-model="logModal.level" style="width:95px;" :dropdown-class-name="themeSwitcher.currentTheme">
|
||||
<a-select-option value="debug">Debug</a-select-option>
|
||||
<a-select-option value="info">Info</a-select-option>
|
||||
<a-select-option value="notice">Notice</a-select-option>
|
||||
<a-select-option value="warning">Warning</a-select-option>
|
||||
<a-select-option value="err">Error</a-select-option>
|
||||
</a-select>
|
||||
|
@ -326,7 +324,23 @@
|
|||
</a-button>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
<div class="ant-input" style="height: auto; max-height: 500px; overflow: auto; margin-top: 0.5rem;" v-html="logModal.formattedLogs"></div>
|
||||
<a-list bordered size="small">
|
||||
<a-list-item v-for="log in logModal.logs.filter((log) => log.level === logModal.level).slice(0, logModal.rows)">
|
||||
<a-list-item-meta>
|
||||
<template #title>
|
||||
<a-space direction="horizontal" size="small" style="padding: 0;">
|
||||
<b>[[ log.sender ]]</b>
|
||||
<a-tag>[[ log.date ]]</a-tag>
|
||||
<a-tag :color="logModal.tagsColors[log.level]">[[ log.level ]]</a-tag>
|
||||
</a-space>
|
||||
</template>
|
||||
<template #description>
|
||||
[[ log.message ]]
|
||||
</template>
|
||||
</a-list-item-meta>
|
||||
</a-list-item>
|
||||
</a-list>
|
||||
</a-space>
|
||||
</a-modal>
|
||||
<a-modal id="backup-modal"
|
||||
v-model="backupModal.visible"
|
||||
|
@ -467,46 +481,64 @@
|
|||
level: 'info',
|
||||
syslog: false,
|
||||
loading: false,
|
||||
tagsColors: {
|
||||
"err": "red",
|
||||
"warning": "orange",
|
||||
"info": "blue",
|
||||
"debug": ""
|
||||
},
|
||||
show(logs) {
|
||||
this.visible = true;
|
||||
this.logs = logs;
|
||||
this.formattedLogs = this.logs?.length > 0 ? this.formatLogs(this.logs) : "No Record...";
|
||||
this.logs = this.getLogs(logs);
|
||||
},
|
||||
formatLogs(logs) {
|
||||
let formattedLogs = '';
|
||||
const levels = ["DEBUG","INFO","NOTICE","WARNING","ERROR"];
|
||||
const levelColors = ["#3c89e8","#008771","#008771","#f37b24","#e04141","#bcbcbc"];
|
||||
getLogs(logs) {
|
||||
if (logs === null) return []
|
||||
|
||||
logs.forEach((log, index) => {
|
||||
let [data, message] = log.split(" - ",2);
|
||||
const parts = data.split(" ")
|
||||
if(index>0) formattedLogs += '<br>';
|
||||
return logs.map((log) => {
|
||||
let message;
|
||||
let level;
|
||||
let date;
|
||||
let sender;
|
||||
|
||||
if (parts.length === 3) {
|
||||
const d = parts[0];
|
||||
const t = parts[1];
|
||||
const level = parts[2];
|
||||
const levelIndex = levels.indexOf(level,levels) || 5;
|
||||
|
||||
//formattedLogs += `<span style="color: gray;">${index + 1}.</span>`;
|
||||
formattedLogs += `<span style="color: ${levelColors[0]};">${d} ${t}</span> `;
|
||||
formattedLogs += `<span style="color: ${levelColors[levelIndex]}">${level}</span>`;
|
||||
if (log.includes("XRAY:")) {
|
||||
sender = "xray"
|
||||
} else {
|
||||
const levelIndex = levels.indexOf(data,levels) || 5;
|
||||
formattedLogs += `<span style="color: ${levelColors[levelIndex]}">${data}</span>`;
|
||||
sender = "3x-ui"
|
||||
}
|
||||
|
||||
if(message){
|
||||
if(message.startsWith("XRAY:"))
|
||||
message = "<b>XRAY: </b>" + message.substring(5);
|
||||
else
|
||||
message = "<b>X-UI: </b>" + message;
|
||||
if (sender === "xray") {
|
||||
if (log.toLowerCase().includes("failed")) {
|
||||
level = "err"
|
||||
} else if (log.includes("[Warning]")) {
|
||||
level = "warning"
|
||||
} else if (log.includes("[Info]")) {
|
||||
level = "info"
|
||||
} else {
|
||||
level = "debug"
|
||||
}
|
||||
} else {
|
||||
if (log.includes("ERROR") || log.toLowerCase().includes("failed")) {
|
||||
level = "err"
|
||||
} else if (log.includes("DEBUG")) {
|
||||
level = "debug"
|
||||
} else if (log.includes("INFO")) {
|
||||
level = "info"
|
||||
}
|
||||
}
|
||||
|
||||
formattedLogs += message ? ' - ' + message : '';
|
||||
});
|
||||
// date = ``
|
||||
// message = `${logs.split("—")[1]}`
|
||||
|
||||
return formattedLogs;
|
||||
date = `${log.split(" ")[0]} ${log.split(" ")[1]}`
|
||||
message = `${log.split("——")[1]}`
|
||||
|
||||
return {
|
||||
message: message,
|
||||
level: level,
|
||||
date: date,
|
||||
sender: sender
|
||||
}
|
||||
}).reverse()
|
||||
},
|
||||
hide() {
|
||||
this.visible = false;
|
||||
|
@ -597,7 +629,7 @@
|
|||
},
|
||||
async openLogs(){
|
||||
logModal.loading = true;
|
||||
const msg = await HttpUtil.post('server/logs/'+logModal.rows,{level: logModal.level, syslog: logModal.syslog});
|
||||
const msg = await HttpUtil.post('server/logs/'+logModal.rows,{syslog: logModal.syslog});
|
||||
if (!msg.success) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -418,12 +418,11 @@ func (s *ServerService) UpdateXray(version string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *ServerService) GetLogs(count string, level string, syslog string) []string {
|
||||
c, _ := strconv.Atoi(count)
|
||||
func (s *ServerService) GetLogs(syslog string) []string {
|
||||
var lines []string
|
||||
|
||||
if syslog == "true" {
|
||||
cmdArgs := []string{"journalctl", "-u", "x-ui", "--no-pager", "-n", count, "-p", level}
|
||||
cmdArgs := []string{"journalctl", "-u", "x-ui", "--no-pager"}
|
||||
// Run the command
|
||||
cmd := exec.Command(cmdArgs[0], cmdArgs[1:]...)
|
||||
var out bytes.Buffer
|
||||
|
@ -434,7 +433,7 @@ func (s *ServerService) GetLogs(count string, level string, syslog string) []str
|
|||
}
|
||||
lines = strings.Split(out.String(), "\n")
|
||||
} else {
|
||||
lines = logger.GetLogs(c, level)
|
||||
lines = logger.GetLogs()
|
||||
}
|
||||
|
||||
return lines
|
||||
|
|
Loading…
Reference in a new issue