v0.116.0: observability pass — always-on debug ring + leveled sweep + agent tab + self-log pull — MinAgent: 0.81.0
Capture layer: LogBuffer always exists; logger = MultiWriter(LevelFilterWriter (stdout, logging.level), ring) so DEBUG detail exists remotely without a config flip while docker logs keep respecting the level. New internal/logx leveled helpers. Report ACK gains controller_log_requested (additive); next report ships controller_log_tail (128KB, consume-once, app-tail wire byte-compatible). Debug page: Vezérlő|Ügynök tabs; agent tab proxies agent /debug/logs with the pre-0.83 notice on typed 404. Sweep: netstorage_job phases, netprobe, handler validation refusals + orphan WARN, SupportsWithSource gate line, agentapi per-call DEBUG, migrate phase lines, tier2/offbox unswallowed persists. Red-proofs: filter-disabled, drain-removed, dropped-phase-line all FAIL. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/agentapi"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/appexport"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/monitor"
|
||||
"gitea.dooplex.hu/admin/felhom-controller/internal/report"
|
||||
@@ -79,6 +81,8 @@ func (s *Server) handleDebugAPI(w http.ResponseWriter, r *http.Request) {
|
||||
// Section 8: Log viewer
|
||||
case subpath == "logs" && r.Method == http.MethodGet:
|
||||
s.debugLogBuffer(w, r)
|
||||
case subpath == "agent-logs" && r.Method == http.MethodGet:
|
||||
s.debugAgentLogs(w, r)
|
||||
|
||||
// Section 9: App Export/Import
|
||||
case subpath == "appexport/status" && r.Method == http.MethodGet:
|
||||
@@ -528,6 +532,41 @@ func (s *Server) debugLogBuffer(w http.ResponseWriter, r *http.Request) {
|
||||
})
|
||||
}
|
||||
|
||||
// debugAgentLogs proxies the host agent's always-DEBUG capture ring (agent ≥ 0.83.0)
|
||||
// for the Debug page's "Ügynök" tab. A pre-0.83 agent has no such route — the typed
|
||||
// 404 (StatusError, the features.go precedent) renders the "available after the
|
||||
// agent's next update" notice instead of an error; nothing else is gated on it.
|
||||
func (s *Server) debugAgentLogs(w http.ResponseWriter, r *http.Request) {
|
||||
fetch := s.agentLogsFn
|
||||
if fetch == nil {
|
||||
client, err := s.agentClient()
|
||||
if err != nil {
|
||||
writeDebugJSON(w, http.StatusOK, false, "Az ügynök nincs konfigurálva ezen a rendszeren.", nil)
|
||||
return
|
||||
}
|
||||
fetch = client.DebugLogs
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
resp, err := fetch(ctx)
|
||||
if err != nil {
|
||||
var se *agentapi.StatusError
|
||||
if errors.As(err, &se) && se.Code == http.StatusNotFound {
|
||||
writeDebugJSON(w, http.StatusOK, true, "", map[string]interface{}{
|
||||
"unsupported": true,
|
||||
"notice": "Az ügynök naplónézete az ügynök következő frissítése után érhető el.",
|
||||
})
|
||||
return
|
||||
}
|
||||
writeDebugJSON(w, http.StatusOK, false, err.Error(), nil)
|
||||
return
|
||||
}
|
||||
writeDebugJSON(w, http.StatusOK, true, "", map[string]interface{}{
|
||||
"entries": resp.Entries,
|
||||
"total": resp.Total,
|
||||
})
|
||||
}
|
||||
|
||||
// ── Section 9: App Export/Import ─────────────────────────────────────
|
||||
|
||||
func (s *Server) debugAppExportStatus(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
Reference in New Issue
Block a user