Files
dance-lessons-coach/scripts/start-server.sh
Gabriel Radureau c17fb4f9b4
Some checks failed
CI/CD Pipeline / Build Docker Cache (push) Successful in 10s
CI/CD Pipeline / CI Pipeline (push) Failing after 4m14s
CI/CD Pipeline / Trigger Docker Push (push) Has been skipped
🐛 fix: emit all config-loading logs in correct JSON format from the start (#16)
## 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>
2026-04-12 23:28:35 +02:00

164 lines
4.2 KiB
Bash
Executable File

#!/bin/bash
# dance-lessons-coach Server Start Script
# This script starts the server in the background and provides control functions
# Configuration
SCRIPTS_DIR=$(dirname "$(realpath "${BASH_SOURCE[0]}")")
PROJECT_DIR=$(dirname "$SCRIPTS_DIR")
SERVER_CMD="go run ./cmd/server"
LOG_FILE="server.log"
PID_FILE="server.pid"
# Change to project directory
cd "$PROJECT_DIR" || { echo "Failed to change to project directory"; exit 1; }
# Function to start the server
start_server() {
echo "Starting dance-lessons-coach server..."
# Check if server is already running
if [ -f "$PID_FILE" ]; then
if ps -p $(cat $PID_FILE) > /dev/null; then
echo "Server is already running (PID: $(cat $PID_FILE))"
return 0
else
echo "Found stale PID file, cleaning up..."
rm -f "$PID_FILE"
fi
fi
# Start server in background with colors disabled for log file
export DLC_NO_COLOR=1
echo '' > "$LOG_FILE"
nohup $SERVER_CMD > "$LOG_FILE" 2>&1 &
# Wait a moment for server to start and get the actual server PID
sleep 2
# Get the PID of the process actually listening on port 8080
ACTUAL_PID=$(lsof -ti :8080 2>/dev/null || echo "")
if [ -z "$ACTUAL_PID" ]; then
echo "Failed to start server - no process listening on port 8080"
echo "Check log file for errors: $LOG_FILE"
rm -f "$PID_FILE"
unset DLC_NO_COLOR
return 1
fi
echo $ACTUAL_PID > "$PID_FILE"
unset DLC_NO_COLOR
echo "Server started with PID: $(cat $PID_FILE)"
echo "Log file: $LOG_FILE"
echo "Server address: http://localhost:8080"
echo "Server is running successfully"
}
# Function to stop the server
stop_server() {
if [ -f "$PID_FILE" ]; then
echo "Stopping server..."
kill -TERM $(cat "$PID_FILE") 2>/dev/null
# Wait for graceful shutdown
for i in {1..10}; do
if ! ps -p $(cat "$PID_FILE") > /dev/null; then
echo "Server stopped successfully"
rm -f "$PID_FILE"
return 0
fi
sleep 1
done
# Force kill if not stopped
echo "Server did not stop gracefully, forcing kill..."
kill -9 $(cat "$PID_FILE") 2>/dev/null
rm -f "$PID_FILE"
return 1
else
echo "No server is running (PID file not found)"
return 1
fi
}
# Function to check server status
status_server() {
if [ -f "$PID_FILE" ]; then
if ps -p $(cat "$PID_FILE") > /dev/null; then
echo "Server is running (PID: $(cat $PID_FILE))"
echo "Started: $(ps -p $(cat $PID_FILE) -o lstart=)"
return 0
else
echo "Server PID file exists but process is not running"
return 1
fi
else
echo "Server is not running"
return 1
fi
}
# Function to show server logs
tail_logs() {
if [ -f "$LOG_FILE" ]; then
echo "=== Server Logs ==="
tail -n 50 "$LOG_FILE"
else
echo "No log file found: $LOG_FILE"
fi
}
# Function to test API endpoints
test_api() {
echo "Testing API endpoints..."
# Test health endpoint
echo "Testing /api/health:"
curl -s http://localhost:8080/api/health
echo ""
# Test greet endpoint
echo "Testing /api/v1/greet/:"
curl -s http://localhost:8080/api/v1/greet/
echo ""
# Test greet with name
echo "Testing /api/v1/greet/John:"
curl -s http://localhost:8080/api/v1/greet/John
echo ""
}
# Main script logic
case "$1" in
start)
start_server
;;
stop)
stop_server
;;
restart)
stop_server
start_server
;;
status)
status_server
;;
logs)
tail_logs
;;
test)
test_api
;;
*)
echo "Usage: $0 {start|stop|restart|status|logs|test}"
echo " start - Start the server"
echo " stop - Stop the server"
echo " restart - Restart the server"
echo " status - Check server status"
echo " logs - Show server logs"
echo " test - Test API endpoints"
exit 1
;;
esac