Extend retry backoff; rework logging (LOGLEVEL, request lines, colors)

Backoff now covers all dial-phase errors (refused, timeout, DNS), TLS
handshake failures, and 5xx responses with replayable bodies; streamed
POSTs are never replayed to avoid duplicate work. First retry of an
episode logs at WARN, subsequent attempts at INFO.

LOGLEVEL (LOG_LEVEL kept as alias) now defaults to warn: startup logs
version plus every setting; INFO adds one line per incoming request and
per response with status/duration, ANSI-colored in text mode (bypasses
slog's escaping so colors render in docker compose logs); NO_COLOR or
LOG_FORMAT=json disables colors.
This commit is contained in:
mram
2026-09-20 20:00:57 +02:00
parent 20d5439b5f
commit 42e1386811
5 changed files with 312 additions and 42 deletions
+28 -5
View File
@@ -82,7 +82,7 @@ func loadConfig(getenv func(string) string) (config, error) {
backoffMax: time.Minute,
promptCaptureLimit: 64 * 1024,
logLevel: slog.LevelInfo,
logLevel: slog.LevelWarn,
}
for _, e := range []struct {
name string
@@ -125,10 +125,15 @@ func loadConfig(getenv func(string) string) (config, error) {
}
cfg.promptCaptureLimit = n
}
if v := getenv("LOG_LEVEL"); v != "" {
// LOGLEVEL is the canonical spelling; LOG_LEVEL is kept as an alias.
logLevelValue := getenv("LOGLEVEL")
if logLevelValue == "" {
logLevelValue = getenv("LOG_LEVEL")
}
if logLevelValue != "" {
var level slog.Level
if err := level.UnmarshalText([]byte(v)); err != nil {
return cfg, fmt.Errorf("LOG_LEVEL: %w", err)
if err := level.UnmarshalText([]byte(logLevelValue)); err != nil {
return cfg, fmt.Errorf("LOGLEVEL: %w", err)
}
cfg.logLevel = level
}
@@ -157,12 +162,29 @@ func main() {
log := slog.New(handler)
slog.SetDefault(log)
log.Info("starting gpu-turnstile",
// The startup line carries the version and every setting and is emitted
// at WARN so it is visible even with the default (quiet) log level.
log.Log(context.Background(), slog.LevelWarn, "starting gpu-turnstile",
"version", version,
"listen_ollama", cfg.listenOllama,
"listen_comfy", cfg.listenComfy,
"ollama_url", cfg.ollamaURL,
"comfy_url", cfg.comfyURL,
"unload_timeout", cfg.unloadTimeout,
"job_timeout", cfg.jobTimeout,
"llm_wait_timeout", cfg.llmWaitTimeout,
"unload_poll_interval", cfg.unloadPollInterval,
"history_poll_interval", cfg.historyPollInterval,
"probe_timeout", cfg.probeTimeout,
"free_timeout", cfg.freeTimeout,
"warm_timeout", cfg.warmTimeout,
"shutdown_timeout", cfg.shutdownTimeout,
"backoff_initial", cfg.backoffInitial,
"backoff_max", cfg.backoffMax,
"prompt_capture_limit", cfg.promptCaptureLimit,
"warm_model", cfg.warmModel,
"log_level", cfg.logLevel,
"log_format", map[bool]string{true: "json", false: "text"}[cfg.logJSON],
)
ollamaClient, err := ollama.New(cfg.ollamaURL, log)
@@ -184,6 +206,7 @@ func main() {
Comfy: comfyClient,
Metrics: metrics.New(),
Log: log,
LogColor: !cfg.logJSON && os.Getenv("NO_COLOR") == "",
LLMWaitTimeout: cfg.llmWaitTimeout,
UnloadTimeout: cfg.unloadTimeout,
JobTimeout: cfg.jobTimeout,