diff options
| author | Colin Wilk <colin@wilk.cx> | 2026-10-30 10:19:01 +0100 |
|---|---|---|
| committer | Colin Wilk <colin@wilk.cx> | 2026-10-30 10:19:01 +0100 |
| commit | 57c86f20f2112ce54f05d1de55c4afa16d28a9ab (patch) | |
| tree | 6b8e20ad72faa253292069cbf5d5d0f3b6651610 | |
| parent | b03b00869391cd70ef1e40561f72dffbd2f47b29 (diff) | |
| download | cr-web-57c86f20f2112ce54f05d1de55c4afa16d28a9ab.tar.gz cr-web-57c86f20f2112ce54f05d1de55c4afa16d28a9ab.zip | |
Add logging with httplog
| -rw-r--r-- | Dockerfile | 2 | ||||
| -rw-r--r-- | go.mod | 4 | ||||
| -rw-r--r-- | go.sum | 4 | ||||
| -rw-r--r-- | main.go | 31 | ||||
| -rw-r--r-- | web/server.go | 20 |
5 files changed, 48 insertions, 13 deletions
@@ -1,7 +1,7 @@ # --- Builder --- FROM golang:alpine AS builder WORKDIR /app -COPY go.mod main.go ./ +COPY go.mod go.sum main.go ./ COPY registry ./registry COPY web ./web RUN CGO_ENABLED=0 go build -o registry-browser . @@ -1,3 +1,7 @@ module git.wilk.cx/cr-browser go 1.26 + +require github.com/go-chi/httplog/v3 v3.5.0 + +require github.com/go-chi/chi/v5 v5.3.0 // indirect @@ -0,0 +1,4 @@ +github.com/go-chi/chi/v5 v5.3.0 h1:halUjDxhshgXHMrao5bB8eNBXo/rnzwr8m5m36glehM= +github.com/go-chi/chi/v5 v5.3.0/go.mod h1:R+tYY2hNuVUUjxoPtqUdgBqevM9s9njzkTLutVsOCto= +github.com/go-chi/httplog/v3 v3.5.0 h1:QTd0cRZGznBMC1J9hm4reEfgneV92hvSHOoPR97f/aE= +github.com/go-chi/httplog/v3 v3.5.0/go.mod h1:tDhJo9G+F4mioDgX4pKbyA0uVZwCtHejoSsDkvJkFkU= @@ -2,7 +2,8 @@ package main import ( "flag" - "log" + "fmt" + "log/slog" "net/http" "os" "strings" @@ -14,8 +15,26 @@ import ( func main() { httpAddr := flag.String("http", ":8080", "HTTP listen address") + defaultVerbosity := os.Getenv("VERBOSITY") + verbosity := flag.String("verbosity", defaultVerbosity, "Log verbosity: ERR, WARN, INFO (env VERBOSITY)") flag.Parse() + var level slog.Level + switch strings.ToUpper(strings.TrimSpace(*verbosity)) { + case "ERROR": + level = slog.LevelError + case "WARN": + level = slog.LevelWarn + case "INFO": + level = slog.LevelInfo + case "": + level = slog.LevelInfo + default: + fmt.Fprintf(os.Stderr, "invalid verbosity %q: expected ERROR, WARN, or INFO\n", *verbosity) + os.Exit(2) + } + slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: level}))) + registryURL := os.Getenv("REGISTRY_URL") if registryURL == "" { registryURL = "http://localhost:5000" @@ -35,7 +54,8 @@ func main() { server, err := web.NewServer(provider, registryHost) if err != nil { - log.Fatal(err) + slog.Error("initialize server", "error", err) + os.Exit(1) } httpServer := &http.Server{ @@ -44,6 +64,9 @@ func main() { ReadHeaderTimeout: 5 * time.Second, } - log.Printf("Listening on %s", *httpAddr) - log.Fatal(httpServer.ListenAndServe()) + slog.Info("listening", "address", *httpAddr) + if err := httpServer.ListenAndServe(); err != nil { + slog.Error("HTTP server stopped", "error", err) + os.Exit(1) + } } diff --git a/web/server.go b/web/server.go index 121b197..59b5c2b 100644 --- a/web/server.go +++ b/web/server.go @@ -5,11 +5,12 @@ import ( "context" "errors" "html/template" - "log" + "log/slog" "net/http" "strings" "git.wilk.cx/cr-browser/registry" + "github.com/go-chi/httplog/v3" ) type RepositoryLister interface { @@ -64,7 +65,10 @@ func (s *Server) Handler() http.Handler { mux.HandleFunc("/", s.repositories) mux.HandleFunc("/r/{name...}", s.repository) - return mux + return httplog.RequestLogger(slog.Default(), &httplog.Options{ + Level: slog.LevelInfo, + Schema: httplog.SchemaECS.Concise(true), + })(mux) } func (s *Server) repositories(w http.ResponseWriter, r *http.Request) { @@ -81,7 +85,7 @@ func (s *Server) repositories(w http.ResponseWriter, r *http.Request) { repos, err := s.provider.Repositories(r.Context()) if err != nil { - log.Printf("fetch repositories: %v", err) + slog.Error("fetch repositories", "error", err) http.Error(w, "failed to fetch repositories", http.StatusBadGateway) return } @@ -94,7 +98,7 @@ func (s *Server) repositories(w http.ResponseWriter, r *http.Request) { var buf bytes.Buffer if err := s.tmpl.ExecuteTemplate(&buf, "repositories", data); err != nil { - log.Printf("render repositories: %v", err) + slog.Error("render repositories", "error", err) http.Error(w, "failed to render page", http.StatusInternalServerError) return } @@ -127,7 +131,7 @@ func (s *Server) repository(w http.ResponseWriter, r *http.Request) { return } - log.Printf("fetch repository: %v", err) + slog.Error("fetch repository", "error", err) http.Error(w, "failed to fetch repository", http.StatusBadGateway) return } @@ -140,7 +144,7 @@ func (s *Server) repository(w http.ResponseWriter, r *http.Request) { var buf bytes.Buffer if err := s.tmpl.ExecuteTemplate(&buf, "repository", data); err != nil { - log.Printf("render repository: %v", err) + slog.Error("render repository", "error", err) http.Error(w, "failed to render page", http.StatusInternalServerError) return } @@ -156,7 +160,7 @@ func (s *Server) manifest(w http.ResponseWriter, r *http.Request, repository, di http.NotFound(w, r) return } - log.Printf("fetch manifest: %v", err) + slog.Error("fetch manifest", "error", err) http.Error(w, "failed to fetch manifest", http.StatusBadGateway) return } @@ -171,7 +175,7 @@ func (s *Server) manifest(w http.ResponseWriter, r *http.Request, repository, di var buf bytes.Buffer if err := s.tmpl.ExecuteTemplate(&buf, "manifest", data); err != nil { - log.Printf("render manifest: %v", err) + slog.Error("render manifest", "error", err) http.Error(w, "failed to render page", http.StatusInternalServerError) return } |