## Summary Closes #15 When `logging.json: true` (or `DLC_LOGGING_JSON=true`), the logger was unconditionally initialised to console/text format at the top of `LoadConfig()`, so early log lines — most visibly **"Config file loaded"** — were always written as human-readable text regardless of configuration. ## Root cause Classic chicken-and-egg: the format flag lives inside the config that is being loaded. The format-switch block only ran *after* `v.Unmarshal()`, too late for the config-file log. ## Changes ### `pkg/config/config.go` - Add `peekJSONLogging()`: resolves the JSON flag **before** any log is emitted by (1) checking `DLC_LOGGING_JSON` directly via `os.Getenv`, then (2) doing a minimal throwaway Viper pre-read of the config file for the `logging.json` key. This mirrors Viper's own priority order without parsing the full config twice. - Apply the resolved format immediately and emit **"Logging configured"** as the very first log line. - Remove the now-redundant format-switch block that ran after `Unmarshal()`. ### `scripts/start-server.sh`, `test-graceful-shutdown.sh`, `test-opentelemetry.sh` - Replace hardcoded `PROJECT_DIR` path with a dynamic `SCRIPTS_DIR=$(dirname $(realpath ${BASH_SOURCE[0]}))` derivation so scripts work from any worktree or clone location. ## Test plan - [x] `go test ./pkg/...` — all pass - [x] `scripts/test-graceful-shutdown.sh` — all JSON valid, all startup logs present - [x] Manual smoke test: first line is `{"level":"info",...,"message":"Logging configured"}`, every line is valid JSON Reviewed-on: #16 Co-authored-by: Gabriel Radureau <arcodange@gmail.com> Co-committed-by: Gabriel Radureau <arcodange@gmail.com>
64 lines
1.7 KiB
Go
64 lines
1.7 KiB
Go
// Package main provides the dance-lessons-coach server entry point
|
|
//
|
|
// @title dance-lessons-coach API
|
|
// @version 1.4.0
|
|
// @description API for dance-lessons-coach service providing greeting functionality
|
|
// @termsOfService http://swagger.io/terms/
|
|
|
|
// @contact.name API Support
|
|
// @contact.url http://www.arcodange.fr/support
|
|
// @contact.email support@arcodange.fr
|
|
|
|
// @license.name MIT
|
|
// @license.url https://opensource.org/licenses/MIT
|
|
|
|
// @host localhost:8080
|
|
// @BasePath /api
|
|
// @schemes http https
|
|
//
|
|
// @securityDefinitions.apikey BearerAuth
|
|
// @in header
|
|
// @name Authorization
|
|
// @description JWT authentication using Bearer token. Format: Bearer <token>
|
|
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
|
|
"dance-lessons-coach/pkg/config"
|
|
"dance-lessons-coach/pkg/server"
|
|
"dance-lessons-coach/pkg/version"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func main() {
|
|
// Check for version flag first (before config loading)
|
|
if len(os.Args) > 1 && (os.Args[1] == "--version" || os.Args[1] == "-version") {
|
|
fmt.Println(version.Full())
|
|
os.Exit(0)
|
|
}
|
|
|
|
// Load configuration (this will also setup logging)
|
|
cfg, err := config.LoadConfig()
|
|
if err != nil {
|
|
log.Fatal().Err(err).Msg("Failed to load configuration")
|
|
}
|
|
|
|
// Create readiness context to control readiness state.
|
|
// CancelableContext exposes Cancel() so that Server.Run() can cancel
|
|
// readiness at the start of graceful shutdown (before the propagation sleep).
|
|
readyCtx, readyCancel := server.NewCancelableContext(context.Background())
|
|
defer readyCancel()
|
|
|
|
// Create and run server
|
|
server := server.NewServer(cfg, readyCtx)
|
|
if err := server.Run(); err != nil {
|
|
log.Fatal().Err(err).Msg("Server failed")
|
|
}
|
|
log.Trace().Msg("Server exited")
|
|
}
|