mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-08-23 11:26:52 +00:00
Added filters to the xray logs viewer (#3314)
Some checks are pending
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
Some checks are pending
Release 3X-UI / build (386) (push) Waiting to run
Release 3X-UI / build (amd64) (push) Waiting to run
Release 3X-UI / build (arm64) (push) Waiting to run
Release 3X-UI / build (armv5) (push) Waiting to run
Release 3X-UI / build (armv6) (push) Waiting to run
Release 3X-UI / build (armv7) (push) Waiting to run
Release 3X-UI / build (s390x) (push) Waiting to run
* added filters to xray logs viewer * better freedom/blackhole tags handling * better freedom/blackhole tags handling 2 * fix comments * fix comments 2
This commit is contained in:
parent
6a17285935
commit
419ea63dd0
3 changed files with 110 additions and 16 deletions
|
@ -18,6 +18,7 @@ type ServerController struct {
|
||||||
BaseController
|
BaseController
|
||||||
|
|
||||||
serverService service.ServerService
|
serverService service.ServerService
|
||||||
|
settingService service.SettingService
|
||||||
|
|
||||||
lastStatus *service.Status
|
lastStatus *service.Status
|
||||||
lastGetStatusTime time.Time
|
lastGetStatusTime time.Time
|
||||||
|
@ -137,7 +138,45 @@ func (a *ServerController) getLogs(c *gin.Context) {
|
||||||
|
|
||||||
func (a *ServerController) getXrayLogs(c *gin.Context) {
|
func (a *ServerController) getXrayLogs(c *gin.Context) {
|
||||||
count := c.Param("count")
|
count := c.Param("count")
|
||||||
logs := a.serverService.GetXrayLogs(count)
|
filter := c.PostForm("filter")
|
||||||
|
showDirect := c.PostForm("showDirect")
|
||||||
|
showBlocked := c.PostForm("showBlocked")
|
||||||
|
showProxy := c.PostForm("showProxy")
|
||||||
|
|
||||||
|
var freedoms []string
|
||||||
|
var blackholes []string
|
||||||
|
|
||||||
|
//getting tags for freedom and blackhole outbounds
|
||||||
|
config, err := a.settingService.GetDefaultXrayConfig()
|
||||||
|
if err == nil && config != nil {
|
||||||
|
if cfgMap, ok := config.(map[string]interface{}); ok {
|
||||||
|
if outbounds, ok := cfgMap["outbounds"].([]interface{}); ok {
|
||||||
|
for _, outbound := range outbounds {
|
||||||
|
if obMap, ok := outbound.(map[string]interface{}); ok {
|
||||||
|
switch obMap["protocol"] {
|
||||||
|
case "freedom":
|
||||||
|
if tag, ok := obMap["tag"].(string); ok {
|
||||||
|
freedoms = append(freedoms, tag)
|
||||||
|
}
|
||||||
|
case "blackhole":
|
||||||
|
if tag, ok := obMap["tag"].(string); ok {
|
||||||
|
blackholes = append(blackholes, tag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(freedoms) == 0 {
|
||||||
|
freedoms = []string{"direct"}
|
||||||
|
}
|
||||||
|
if len(blackholes) == 0 {
|
||||||
|
blackholes = []string{"blocked"}
|
||||||
|
}
|
||||||
|
|
||||||
|
logs := a.serverService.GetXrayLogs(count, filter, showDirect, showBlocked, showProxy, freedoms, blackholes)
|
||||||
jsonObj(c, logs, nil)
|
jsonObj(c, logs, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -457,6 +457,14 @@
|
||||||
</a-select>
|
</a-select>
|
||||||
</a-input-group>
|
</a-input-group>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item label="Filter:">
|
||||||
|
<a-input size="small" v-model="xraylogModal.filter" @keyup.enter="openXrayLogs()"></a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-checkbox v-model="xraylogModal.showDirect" @change="openXrayLogs()">Direct</a-checkbox>
|
||||||
|
<a-checkbox v-model="xraylogModal.showBlocked" @change="openXrayLogs()">Blocked</a-checkbox>
|
||||||
|
<a-checkbox v-model="xraylogModal.showProxy" @change="openXrayLogs()">Proxy</a-checkbox>
|
||||||
|
</a-form-item>
|
||||||
<a-form-item :style="{ float: 'right' }">
|
<a-form-item :style="{ float: 'right' }">
|
||||||
<a-button type="primary" icon="download" @click="FileManager.downloadTextFile(xraylogModal.logs?.join('\n'), 'x-ui.log')"></a-button>
|
<a-button type="primary" icon="download" @click="FileManager.downloadTextFile(xraylogModal.logs?.join('\n'), 'x-ui.log')"></a-button>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
@ -651,6 +659,9 @@
|
||||||
visible: false,
|
visible: false,
|
||||||
logs: [],
|
logs: [],
|
||||||
rows: 20,
|
rows: 20,
|
||||||
|
showDirect: true,
|
||||||
|
showBlocked: true,
|
||||||
|
showProxy: true,
|
||||||
loading: false,
|
loading: false,
|
||||||
show(logs) {
|
show(logs) {
|
||||||
this.visible = true;
|
this.visible = true;
|
||||||
|
@ -665,17 +676,17 @@
|
||||||
|
|
||||||
const parts = log.split(' ');
|
const parts = log.split(' ');
|
||||||
|
|
||||||
if(parts.length === 9) {
|
if(parts.length === 10) {
|
||||||
const dateTime = `<b>${parts[0]} ${parts[1]}</b>`;
|
const dateTime = `<b>${parts[0]} ${parts[1]}</b>`;
|
||||||
const from = `<b>${parts[3]}</b>`;
|
const from = `<b>${parts[3]}</b>`;
|
||||||
const to = `<b>${parts[5].replace(/^\/+/, "")}</b>`;
|
const to = `<b>${parts[5].replace(/^\/+/, "")}</b>`;
|
||||||
|
|
||||||
let outboundColor = '';
|
let outboundColor = '';
|
||||||
if (parts[8].startsWith('blocked')) {
|
if (parts[9] === "b") {
|
||||||
outboundColor = ' style="color: #e04141;"';
|
outboundColor = ' style="color: #e04141;"'; //red for blocked
|
||||||
}
|
}
|
||||||
else if (!parts[8].startsWith('direct')) {
|
else if (parts[9] === "p") {
|
||||||
outboundColor = ' style="color: #3c89e8;"';
|
outboundColor = ' style="color: #3c89e8;"'; //blue for proxies
|
||||||
}
|
}
|
||||||
|
|
||||||
formattedLogs += `<span${outboundColor}>
|
formattedLogs += `<span${outboundColor}>
|
||||||
|
@ -684,10 +695,10 @@ ${dateTime}
|
||||||
${from}
|
${from}
|
||||||
${parts[4]}
|
${parts[4]}
|
||||||
${to}
|
${to}
|
||||||
${parts.slice(6).join(' ')}
|
${parts.slice(6, 9).join(' ')}
|
||||||
</span>`;
|
</span>`;
|
||||||
} else {
|
} else {
|
||||||
formattedLogs += `<span>${parts.join(' ')}</span>`;
|
formattedLogs += `<span>${log}</span>`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -817,7 +828,7 @@ ${dateTime}
|
||||||
},
|
},
|
||||||
async openXrayLogs(){
|
async openXrayLogs(){
|
||||||
xraylogModal.loading = true;
|
xraylogModal.loading = true;
|
||||||
const msg = await HttpUtil.post('server/xraylogs/'+xraylogModal.rows);
|
const msg = await HttpUtil.post('server/xraylogs/'+xraylogModal.rows,{filter: xraylogModal.filter, showDirect: xraylogModal.showDirect, showBlocked: xraylogModal.showBlocked, showProxy: xraylogModal.showProxy});
|
||||||
if (!msg.success) {
|
if (!msg.success) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -482,8 +482,16 @@ func (s *ServerService) GetLogs(count string, level string, syslog string) []str
|
||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetXrayLogs(count string) []string {
|
func (s *ServerService) GetXrayLogs(
|
||||||
c, _ := strconv.Atoi(count)
|
count string,
|
||||||
|
filter string,
|
||||||
|
showDirect string,
|
||||||
|
showBlocked string,
|
||||||
|
showProxy string,
|
||||||
|
freedoms []string,
|
||||||
|
blackholes []string) []string {
|
||||||
|
|
||||||
|
countInt, _ := strconv.Atoi(count)
|
||||||
var lines []string
|
var lines []string
|
||||||
|
|
||||||
pathToAccessLog, err := xray.GetAccessLogPath()
|
pathToAccessLog, err := xray.GetAccessLogPath()
|
||||||
|
@ -498,21 +506,57 @@ func (s *ServerService) GetXrayLogs(count string) []string {
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
scanner := bufio.NewScanner(file)
|
scanner := bufio.NewScanner(file)
|
||||||
|
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := strings.TrimSpace(scanner.Text())
|
||||||
if strings.TrimSpace(line) == "" || strings.Contains(line, "api -> api") {
|
|
||||||
|
if line == "" || strings.Contains(line, "api -> api") {
|
||||||
|
//skipping empty lines and api calls
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if filter != "" && !strings.Contains(line, filter) {
|
||||||
|
//applying filter if it's not empty
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
//adding suffixes to further distinguish entries by outbound
|
||||||
|
if hasSuffix(line, freedoms) {
|
||||||
|
if showDirect == "false" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
line = line + " f"
|
||||||
|
} else if hasSuffix(line, blackholes) {
|
||||||
|
if showBlocked == "false" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
line = line + " b"
|
||||||
|
} else {
|
||||||
|
if showProxy == "false" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
line = line + " p"
|
||||||
|
}
|
||||||
|
|
||||||
lines = append(lines, line)
|
lines = append(lines, line)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(lines) > c {
|
if len(lines) > countInt {
|
||||||
lines = lines[len(lines)-c:]
|
lines = lines[len(lines)-countInt:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hasSuffix(line string, suffixes []string) bool {
|
||||||
|
for _, sfx := range suffixes {
|
||||||
|
if strings.HasSuffix(line, sfx+"]") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetConfigJson() (any, error) {
|
func (s *ServerService) GetConfigJson() (any, error) {
|
||||||
config, err := s.xrayService.GetXrayConfig()
|
config, err := s.xrayService.GetXrayConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue