summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Dockerfile2
-rw-r--r--go.mod4
-rw-r--r--go.sum4
-rw-r--r--main.go31
-rw-r--r--web/server.go20
5 files changed, 48 insertions, 13 deletions
diff --git a/Dockerfile b/Dockerfile
index 3405c1a..81ca291 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -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 .
diff --git a/go.mod b/go.mod
index bbd1050..bd439ae 100644
--- a/go.mod
+++ b/go.mod
@@ -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
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..1fd64e4
--- /dev/null
+++ b/go.sum
@@ -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=
diff --git a/main.go b/main.go
index 2f27aee..f658c71 100644
--- a/main.go
+++ b/main.go
@@ -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
}