From 25ff094bdf0cca7fd757f66dbdfd67ec17c5cc3b Mon Sep 17 00:00:00 2001 From: Jan Eitzinger Date: Mon, 16 Feb 2026 09:10:08 +0100 Subject: [PATCH] Fix log endpoint --- internal/api/log.go | 20 +++++++++----------- internal/api/rest.go | 1 + 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/internal/api/log.go b/internal/api/log.go index 4ad07589..90add9bb 100644 --- a/internal/api/log.go +++ b/internal/api/log.go @@ -12,12 +12,12 @@ import ( "os/exec" "regexp" "strconv" + "strings" "github.com/ClusterCockpit/cc-backend/internal/config" "github.com/ClusterCockpit/cc-backend/internal/repository" cclog "github.com/ClusterCockpit/cc-lib/v2/ccLogger" "github.com/ClusterCockpit/cc-lib/v2/schema" - "github.com/gorilla/mux" ) type LogEntry struct { @@ -60,15 +60,15 @@ func (api *RestAPI) getJournalLog(rw http.ResponseWriter, r *http.Request) { unit := config.Keys.SystemdUnit if unit == "" { - unit = "clustercockpit" + unit = "clustercockpit.service" } args := []string{ "--output=json", "--no-pager", - fmt.Sprintf("-n %d", lines), - fmt.Sprintf("--since=%s", since), - fmt.Sprintf("-u %s", unit), + "-n", fmt.Sprintf("%d", lines), + "--since", since, + "-u", unit, } if level := r.URL.Query().Get("level"); level != "" { @@ -77,7 +77,7 @@ func (api *RestAPI) getJournalLog(rw http.ResponseWriter, r *http.Request) { handleError(fmt.Errorf("invalid 'level' parameter (must be 0-7)"), http.StatusBadRequest, rw) return } - args = append(args, fmt.Sprintf("--priority=%d", n)) + args = append(args, "--priority", fmt.Sprintf("%d", n)) } if search := r.URL.Query().Get("search"); search != "" { @@ -85,9 +85,10 @@ func (api *RestAPI) getJournalLog(rw http.ResponseWriter, r *http.Request) { handleError(fmt.Errorf("invalid 'search' parameter"), http.StatusBadRequest, rw) return } - args = append(args, fmt.Sprintf("--grep=%s", search)) + args = append(args, "--grep", search) } + cclog.Debugf("calling journalctl with %s", strings.Join(args, " ")) cmd := exec.CommandContext(r.Context(), "journalctl", args...) stdout, err := cmd.StdoutPipe() if err != nil { @@ -105,6 +106,7 @@ func (api *RestAPI) getJournalLog(rw http.ResponseWriter, r *http.Request) { for scanner.Scan() { var raw map[string]any if err := json.Unmarshal(scanner.Bytes(), &raw); err != nil { + cclog.Debugf("error unmarshal log output: %v", err) continue } @@ -161,7 +163,3 @@ func (api *RestAPI) getJournalLog(rw http.ResponseWriter, r *http.Request) { cclog.Errorf("Failed to encode log entries: %v", err) } } - -func (api *RestAPI) MountLogAPIRoutes(r *mux.Router) { - r.HandleFunc("/logs/", api.getJournalLog).Methods(http.MethodGet) -} diff --git a/internal/api/rest.go b/internal/api/rest.go index 575b1809..fe722511 100644 --- a/internal/api/rest.go +++ b/internal/api/rest.go @@ -158,6 +158,7 @@ func (api *RestAPI) MountConfigAPIRoutes(r chi.Router) { // MountFrontendAPIRoutes registers frontend-specific API endpoints. // These routes support JWT generation and user configuration updates with session authentication. func (api *RestAPI) MountFrontendAPIRoutes(r chi.Router) { + r.Get("/logs/", api.getJournalLog) // Settings Frontend Uses SessionAuth if api.Authentication != nil { r.Get("/jwt/", api.getJWT)