Files
elmprodvpn/selective-vpn-api/app/trace_handlers_read.go

93 lines
2.5 KiB
Go

package app
import (
"io"
"net/http"
"strings"
)
func handleTraceTailPlain(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
lines := tailFile(traceLogPath, defaultTraceTailMax)
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
_, _ = io.WriteString(w, strings.Join(lines, "\n"))
}
// ---------------------------------------------------------------------
// trace-json
// ---------------------------------------------------------------------
// GET /api/v1/trace-json?mode=full|gui|events|smartdns
func handleTraceJSON(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
mode := strings.ToLower(strings.TrimSpace(r.URL.Query().Get("mode")))
if mode == "" {
mode = "full"
}
if mode == "events" {
mode = "gui"
}
var lines []string
switch mode {
case "smartdns":
// чисто SmartDNS-лог
lines = tailFile(smartdnsLogPath, defaultTraceTailMax)
case "gui":
// Events: только человеко-читабельные события/ошибки/команды.
full := tailFile(traceLogPath, defaultTraceTailMax)
allow := []string{
"[gui]", "[info]", "[login]", "[vpn]", "[event]", "[error]",
}
for _, l := range full {
ll := strings.ToLower(l)
// берём только наши "человеческие" префиксы
ok := false
for _, a := range allow {
if strings.Contains(ll, strings.ToLower(a)) {
ok = true
break
}
}
if !ok {
// если префикса нет, но это похоже на ошибку — тоже включаем
if strings.Contains(ll, "error") || strings.Contains(ll, "failed") || strings.Contains(ll, "timeout") {
ok = true
}
}
if !ok {
continue
}
// режем шум от резолвера/маршрутов/массовых вставок
if strings.Contains(ll, "smartdns") ||
strings.Contains(ll, "resolver") ||
strings.Contains(ll, "dnstt") ||
strings.Contains(ll, "routes") ||
strings.Contains(ll, "nft add element") ||
strings.Contains(ll, "cache hit:") {
continue
}
lines = append(lines, l)
}
default: // full
// полный хвост trace.log без фильтрации
lines = tailFile(traceLogPath, defaultTraceTailMax)
}
writeJSON(w, http.StatusOK, map[string]any{
"lines": lines,
})
}