Enhance build system and logging configuration
- Add scripts/build.sh to compile binaries into bin/ directory - Move all zerolog setup logic from cmd/server/main.go to pkg/config - Add log level configuration support (trace, debug, info, warn, error, fatal, panic) - Simplify cmd/server/main.go from 57 to 27 lines (53% reduction) - Update .gitignore to use bin/ directory instead of individual files - Document build process and bin directory in AGENTS.md - Maintain backward compatibility with all existing functionality
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -2,8 +2,7 @@
|
||||
*.exe
|
||||
*.test
|
||||
*.out
|
||||
server
|
||||
greet
|
||||
bin/
|
||||
|
||||
# Dependency directories
|
||||
vendor/
|
||||
|
||||
29
AGENTS.md
29
AGENTS.md
@@ -355,12 +355,37 @@ go test ./...
|
||||
go test ./pkg/greet/
|
||||
```
|
||||
|
||||
### 5. Make Changes
|
||||
### 5. Build Binaries
|
||||
|
||||
The project uses a build script to compile binaries into the `bin/` directory:
|
||||
|
||||
```bash
|
||||
# Build both server and greet binaries
|
||||
./scripts/build.sh
|
||||
|
||||
# This creates:
|
||||
# - ./bin/server - The web server binary
|
||||
# - ./bin/greet - The CLI greeting tool
|
||||
```
|
||||
|
||||
**Binary Usage:**
|
||||
```bash
|
||||
# Run the server
|
||||
./bin/server
|
||||
|
||||
# Use the greet CLI
|
||||
./bin/greet # Output: Hello world!
|
||||
./bin/greet John # Output: Hello John!
|
||||
```
|
||||
|
||||
**The `bin/` directory is gitignored** to prevent binary files from being committed to the repository.
|
||||
|
||||
### 6. Make Changes
|
||||
- Edit source files in `pkg/` or `cmd/`
|
||||
- Follow existing patterns and interfaces
|
||||
- Add tests for new functionality
|
||||
|
||||
### 6. Stop and Restart
|
||||
### 7. Stop and Restart
|
||||
```bash
|
||||
./scripts/start-server.sh restart
|
||||
```
|
||||
|
||||
@@ -2,49 +2,19 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
|
||||
"DanceLessonsCoach/pkg/config"
|
||||
"DanceLessonsCoach/pkg/server"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Initialize Zerolog with default console format first
|
||||
zerolog.SetGlobalLevel(zerolog.TraceLevel)
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
consoleWriter := zerolog.ConsoleWriter{Out: os.Stderr}
|
||||
|
||||
// Check if JSON logging is requested via environment variable
|
||||
// This allows JSON logging even during config loading
|
||||
jsonLogging := os.Getenv("DLC_LOGGING_JSON") == "true"
|
||||
|
||||
if jsonLogging {
|
||||
// JSON output for structured logging
|
||||
log.Logger = log.Output(os.Stderr)
|
||||
} else {
|
||||
// Console output for initial logging
|
||||
log.Logger = log.Output(consoleWriter)
|
||||
}
|
||||
|
||||
// Load configuration
|
||||
// Load configuration (this will also setup logging)
|
||||
cfg, err := config.LoadConfig()
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Failed to load configuration")
|
||||
}
|
||||
|
||||
// Reconfigure logging based on loaded configuration (overrides env var)
|
||||
if cfg.Logging.JSON {
|
||||
// JSON output for structured logging
|
||||
log.Logger = log.Output(os.Stderr)
|
||||
} else {
|
||||
// Keep console output
|
||||
log.Logger = log.Output(consoleWriter)
|
||||
}
|
||||
|
||||
log.Info().Bool("json_logging", cfg.Logging.JSON).Msg("Logging configured")
|
||||
|
||||
// Create readiness context to control readiness state
|
||||
readyCtx, readyCancel := context.WithCancel(context.Background())
|
||||
defer readyCancel()
|
||||
|
||||
@@ -21,6 +21,10 @@ logging:
|
||||
# Enable JSON output for structured logging (default: false)
|
||||
# When true, logs are output in JSON format instead of console format
|
||||
json: false
|
||||
|
||||
# Log level (default: "trace")
|
||||
# Options: "trace", "debug", "info", "warn", "error", "fatal", "panic"
|
||||
level: trace
|
||||
|
||||
# Telemetry configuration (OpenTelemetry)
|
||||
telemetry:
|
||||
@@ -53,6 +57,7 @@ telemetry:
|
||||
# DLC_SERVER_PORT=8080
|
||||
# DLC_SHUTDOWN_TIMEOUT=30s
|
||||
# DLC_LOGGING_JSON=false
|
||||
# DLC_LOGGING_LEVEL=trace
|
||||
# DLC_TELEMETRY_ENABLED=true
|
||||
# DLC_TELEMETRY_OTLP_ENDPOINT="jaeger:4317"
|
||||
# DLC_TELEMETRY_SERVICE_NAME="DanceLessonsCoach"
|
||||
|
||||
@@ -3,8 +3,10 @@ package config
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -30,7 +32,8 @@ type ShutdownConfig struct {
|
||||
|
||||
// LoggingConfig holds logging-related configuration
|
||||
type LoggingConfig struct {
|
||||
JSON bool `mapstructure:"json"`
|
||||
JSON bool `mapstructure:"json"`
|
||||
Level string `mapstructure:"level"`
|
||||
}
|
||||
|
||||
// TelemetryConfig holds OpenTelemetry-related configuration
|
||||
@@ -53,12 +56,17 @@ type SamplerConfig struct {
|
||||
// To specify a custom config file path, set DLC_CONFIG_FILE environment variable
|
||||
func LoadConfig() (*Config, error) {
|
||||
v := viper.New()
|
||||
|
||||
// Set up initial console logging for config loading messages
|
||||
consoleWriter := zerolog.ConsoleWriter{Out: os.Stderr}
|
||||
log.Logger = log.Output(consoleWriter)
|
||||
|
||||
// Set default values
|
||||
v.SetDefault("server.host", "0.0.0.0")
|
||||
v.SetDefault("server.port", 8080)
|
||||
v.SetDefault("shutdown.timeout", 30*time.Second)
|
||||
v.SetDefault("logging.json", false)
|
||||
v.SetDefault("logging.level", "trace")
|
||||
|
||||
// Telemetry defaults
|
||||
v.SetDefault("telemetry.enabled", false)
|
||||
@@ -97,6 +105,7 @@ func LoadConfig() (*Config, error) {
|
||||
v.BindEnv("server.port", "DLC_SERVER_PORT")
|
||||
v.BindEnv("shutdown.timeout", "DLC_SHUTDOWN_TIMEOUT")
|
||||
v.BindEnv("logging.json", "DLC_LOGGING_JSON")
|
||||
v.BindEnv("logging.level", "DLC_LOGGING_LEVEL")
|
||||
|
||||
// Telemetry environment variables
|
||||
v.BindEnv("telemetry.enabled", "DLC_TELEMETRY_ENABLED")
|
||||
@@ -113,11 +122,23 @@ func LoadConfig() (*Config, error) {
|
||||
return nil, fmt.Errorf("config unmarshal error: %w", err)
|
||||
}
|
||||
|
||||
// Configure log output format (JSON or console) first
|
||||
if config.Logging.JSON {
|
||||
log.Logger = log.Output(os.Stderr)
|
||||
} else {
|
||||
consoleWriter := zerolog.ConsoleWriter{Out: os.Stderr}
|
||||
log.Logger = log.Output(consoleWriter)
|
||||
}
|
||||
|
||||
// Setup logging based on configuration
|
||||
config.SetupLogging()
|
||||
|
||||
log.Info().
|
||||
Str("host", config.Server.Host).
|
||||
Int("port", config.Server.Port).
|
||||
Dur("shutdown_timeout", config.Shutdown.Timeout).
|
||||
Bool("logging_json", config.Logging.JSON).
|
||||
Str("logging_level", config.Logging.Level).
|
||||
Bool("telemetry_enabled", config.Telemetry.Enabled).
|
||||
Str("telemetry_service", config.Telemetry.ServiceName).
|
||||
Msg("Configuration loaded")
|
||||
@@ -159,3 +180,40 @@ func (c *Config) GetSamplerType() string {
|
||||
func (c *Config) GetSamplerRatio() float64 {
|
||||
return c.Telemetry.Sampler.Ratio
|
||||
}
|
||||
|
||||
// GetLogLevel returns the logging level
|
||||
func (c *Config) GetLogLevel() string {
|
||||
return c.Logging.Level
|
||||
}
|
||||
|
||||
// SetupLogging configures zerolog based on the configuration
|
||||
func (c *Config) SetupLogging() {
|
||||
// Parse log level
|
||||
level := parseLogLevel(c.GetLogLevel())
|
||||
zerolog.SetGlobalLevel(level)
|
||||
|
||||
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
||||
}
|
||||
|
||||
// parseLogLevel converts a string log level to zerolog.Level
|
||||
func parseLogLevel(level string) zerolog.Level {
|
||||
switch strings.ToLower(level) {
|
||||
case "trace":
|
||||
return zerolog.TraceLevel
|
||||
case "debug":
|
||||
return zerolog.DebugLevel
|
||||
case "info":
|
||||
return zerolog.InfoLevel
|
||||
case "warn", "warning":
|
||||
return zerolog.WarnLevel
|
||||
case "error":
|
||||
return zerolog.ErrorLevel
|
||||
case "fatal":
|
||||
return zerolog.FatalLevel
|
||||
case "panic":
|
||||
return zerolog.PanicLevel
|
||||
default:
|
||||
log.Warn().Str("level", level).Msg("Unknown log level, defaulting to trace")
|
||||
return zerolog.TraceLevel
|
||||
}
|
||||
}
|
||||
|
||||
26
scripts/build.sh
Executable file
26
scripts/build.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
# DanceLessonsCoach Build Script
|
||||
# Builds binaries into the bin/ directory
|
||||
|
||||
set -e
|
||||
|
||||
echo "🔨 Building DanceLessonsCoach binaries..."
|
||||
|
||||
# Create bin directory if it doesn't exist
|
||||
mkdir -p bin
|
||||
|
||||
# Build server binary
|
||||
echo "📦 Building server..."
|
||||
go build -o bin/server ./cmd/server
|
||||
|
||||
# Build greet CLI binary
|
||||
echo "📦 Building greet CLI..."
|
||||
go build -o bin/greet ./cmd/greet
|
||||
|
||||
echo "✅ Build complete!"
|
||||
echo " Server binary: ./bin/server"
|
||||
echo " Greet binary: ./bin/greet"
|
||||
echo ""
|
||||
echo "💡 To run the server: ./bin/server"
|
||||
echo "💡 To use the greet CLI: ./bin/greet [name]"
|
||||
Reference in New Issue
Block a user