Add OpenTelemetry instrumentation with middleware-only approach
This commit is contained in:
@@ -11,16 +11,41 @@ import (
|
||||
|
||||
// Config represents the application configuration
|
||||
type Config struct {
|
||||
Server struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
}
|
||||
Shutdown struct {
|
||||
Timeout time.Duration `mapstructure:"timeout"`
|
||||
}
|
||||
Logging struct {
|
||||
JSON bool `mapstructure:"json"`
|
||||
}
|
||||
Server ServerConfig `mapstructure:"server"`
|
||||
Shutdown ShutdownConfig `mapstructure:"shutdown"`
|
||||
Logging LoggingConfig `mapstructure:"logging"`
|
||||
Telemetry TelemetryConfig `mapstructure:"telemetry"`
|
||||
}
|
||||
|
||||
// ServerConfig holds server-related configuration
|
||||
type ServerConfig struct {
|
||||
Host string `mapstructure:"host"`
|
||||
Port int `mapstructure:"port"`
|
||||
}
|
||||
|
||||
// ShutdownConfig holds shutdown-related configuration
|
||||
type ShutdownConfig struct {
|
||||
Timeout time.Duration `mapstructure:"timeout"`
|
||||
}
|
||||
|
||||
// LoggingConfig holds logging-related configuration
|
||||
type LoggingConfig struct {
|
||||
JSON bool `mapstructure:"json"`
|
||||
}
|
||||
|
||||
// TelemetryConfig holds OpenTelemetry-related configuration
|
||||
type TelemetryConfig struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
OTLPEndpoint string `mapstructure:"otlp_endpoint"`
|
||||
ServiceName string `mapstructure:"service_name"`
|
||||
Insecure bool `mapstructure:"insecure"`
|
||||
Sampler SamplerConfig `mapstructure:"sampler"`
|
||||
}
|
||||
|
||||
// SamplerConfig holds tracing sampler configuration
|
||||
type SamplerConfig struct {
|
||||
Type string `mapstructure:"type"`
|
||||
Ratio float64 `mapstructure:"ratio"`
|
||||
}
|
||||
|
||||
// LoadConfig loads configuration from file, environment variables, and defaults
|
||||
@@ -28,13 +53,21 @@ type Config struct {
|
||||
// To specify a custom config file path, set DLC_CONFIG_FILE environment variable
|
||||
func LoadConfig() (*Config, error) {
|
||||
v := viper.New()
|
||||
|
||||
|
||||
// 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)
|
||||
|
||||
|
||||
// Telemetry defaults
|
||||
v.SetDefault("telemetry.enabled", false)
|
||||
v.SetDefault("telemetry.otlp_endpoint", "localhost:4317")
|
||||
v.SetDefault("telemetry.service_name", "DanceLessonsCoach")
|
||||
v.SetDefault("telemetry.insecure", true)
|
||||
v.SetDefault("telemetry.sampler.type", "parentbased_always_on")
|
||||
v.SetDefault("telemetry.sampler.ratio", 1.0)
|
||||
|
||||
// Check for custom config file path via environment variable
|
||||
if configFile := os.Getenv("DLC_CONFIG_FILE"); configFile != "" {
|
||||
v.SetConfigFile(configFile)
|
||||
@@ -45,7 +78,7 @@ func LoadConfig() (*Config, error) {
|
||||
v.SetConfigType("yaml")
|
||||
v.AddConfigPath(".")
|
||||
}
|
||||
|
||||
|
||||
// Read config file if it exists
|
||||
if err := v.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
||||
@@ -56,7 +89,7 @@ func LoadConfig() (*Config, error) {
|
||||
} else {
|
||||
log.Info().Str("config_file", v.ConfigFileUsed()).Msg("Config file loaded")
|
||||
}
|
||||
|
||||
|
||||
// Bind environment variables
|
||||
v.AutomaticEnv()
|
||||
v.SetEnvPrefix("DLC") // DanceLessonsCoach prefix
|
||||
@@ -64,25 +97,65 @@ 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")
|
||||
|
||||
|
||||
// Telemetry environment variables
|
||||
v.BindEnv("telemetry.enabled", "DLC_TELEMETRY_ENABLED")
|
||||
v.BindEnv("telemetry.otlp_endpoint", "DLC_TELEMETRY_OTLP_ENDPOINT")
|
||||
v.BindEnv("telemetry.service_name", "DLC_TELEMETRY_SERVICE_NAME")
|
||||
v.BindEnv("telemetry.insecure", "DLC_TELEMETRY_INSECURE")
|
||||
v.BindEnv("telemetry.sampler.type", "DLC_TELEMETRY_SAMPLER_TYPE")
|
||||
v.BindEnv("telemetry.sampler.ratio", "DLC_TELEMETRY_SAMPLER_RATIO")
|
||||
|
||||
// Unmarshal into Config struct
|
||||
var config Config
|
||||
if err := v.Unmarshal(&config); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to unmarshal config")
|
||||
return nil, fmt.Errorf("config unmarshal error: %w", err)
|
||||
}
|
||||
|
||||
|
||||
log.Info().
|
||||
Str("host", config.Server.Host).
|
||||
Int("port", config.Server.Port).
|
||||
Dur("shutdown_timeout", config.Shutdown.Timeout).
|
||||
Bool("logging_json", config.Logging.JSON).
|
||||
Bool("telemetry_enabled", config.Telemetry.Enabled).
|
||||
Str("telemetry_service", config.Telemetry.ServiceName).
|
||||
Msg("Configuration loaded")
|
||||
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// GetServerAddress returns the formatted server address (host:port)
|
||||
func (c *Config) GetServerAddress() string {
|
||||
return fmt.Sprintf("%s:%d", c.Server.Host, c.Server.Port)
|
||||
}
|
||||
}
|
||||
|
||||
// GetTelemetryEnabled returns whether telemetry is enabled
|
||||
func (c *Config) GetTelemetryEnabled() bool {
|
||||
return c.Telemetry.Enabled
|
||||
}
|
||||
|
||||
// GetOTLPEndpoint returns the OTLP endpoint for telemetry
|
||||
func (c *Config) GetOTLPEndpoint() string {
|
||||
return c.Telemetry.OTLPEndpoint
|
||||
}
|
||||
|
||||
// GetServiceName returns the service name for telemetry
|
||||
func (c *Config) GetServiceName() string {
|
||||
return c.Telemetry.ServiceName
|
||||
}
|
||||
|
||||
// GetTelemetryInsecure returns whether to use insecure connection
|
||||
func (c *Config) GetTelemetryInsecure() bool {
|
||||
return c.Telemetry.Insecure
|
||||
}
|
||||
|
||||
// GetSamplerType returns the sampler type
|
||||
func (c *Config) GetSamplerType() string {
|
||||
return c.Telemetry.Sampler.Type
|
||||
}
|
||||
|
||||
// GetSamplerRatio returns the sampler ratio
|
||||
func (c *Config) GetSamplerRatio() float64 {
|
||||
return c.Telemetry.Sampler.Ratio
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user