Gothic Framework G symbol

Request Logging

Every Gothic project wires one HTTP logger, middlewares.Logger, and it picks its own shape from the environment: a readable coloured line while you develop, and structured JSON your cloud provider can index in production.

package main

import (
	"log"
	"net/http"
	"os"

	"github.com/go-chi/chi/v5"
	"github.com/gothicframework/middlewares"
	"github.com/joho/godotenv"
	"my-project/src/routes"
)

func main() {
	godotenv.Load()

	router := chi.NewMux()
	router.Use(middlewares.Logger())
	router.Use(middlewares.Middleware(Config.Runtime))
	routes.RegisterFileBasedRoutes(router)

	port := os.Getenv("HTTP_LISTEN_ADDR")
	log.Fatal(http.ListenAndServe(port, router))
}

gothic init writes this line for you. There is nothing to configure for the common case.

Quiet while you develop

Under gothic hot-reload the logger is silent, so a page load does not bury your build output under a dozen asset requests. Ask for it with the --verbose flag, or set GOTHIC_VERBOSE=true, and each request gets one line:

16:42:36.960 GET / 200 121.176us 127.0.0.1:48640
16:42:36.970 GET /public/styles.css 200 1.056162ms 127.0.0.1:48640
16:42:37.032 GET /_gothic/gothic-core.wasm 200 142.235us 127.0.0.1:48646

The verb is coloured by what it does to the resource, and the status by its class, so a failing call stands out without reading the number. Outside hot reload the logger is always on.

To keep it on without the flag, pin it in code. The config only ever adds to what the environment already says, so it can never switch logging off:

router.Use(middlewares.Logger(middlewares.LoggingConfig{Verbose: true}))

JSON in production

When GOTHIC_PROVIDER is AWS, the logger emits one JSON object per request, which is what CloudWatch Logs Insights needs to query your traffic by field:

{"time":"2026-07-29T16:19:49.928Z","level":"INFO","msg":"request","component":"gothic","method":"GET","path":"/","status":200,"duration":63738,"remote":"127.0.0.1:43350"}

Anywhere else, a redirected stream gets key=value text. Colour is only ever used for an interactive terminal, so no escape codes reach a stored log, and NO_COLOR is honoured.

Streaming still works

The logger wraps the response writer to capture the status code, and it forwards Flush, Hijack and Push to the writer underneath. Server-sent events, streaming responses and WebSocket upgrades behave exactly as they do without it.

Requests are logged, but responses are also cached. Let's look at how Gothic caches what it renders.