logo
0
0
WeChat Login
Henry Huang<hhh@rutcode.com>
docs(metrics): document unified Prometheus registry usage; wire SetRegisterer examples

Configuration Package

This package provides configuration structures and validation for the trellis framework.

Overview

The configuration package defines all configuration structures used by the framework, including service configuration, logger settings, middleware configurations (rate limiting, circuit breaker, CORS, etc.), and more.

Configuration Structure

The main configuration structure is Config, which contains:

  • ServiceType: Type of service ("http" or "grpc")
  • ServiceConfig: Service-specific configuration
  • LoggerConfig: Logger configuration
  • HotReloadConfig: Configuration hot reload (fsnotify + signals)

Default Values

The framework automatically sets default values for configuration fields:

Service Configuration

  • ServiceType: Defaults to "http" if empty
  • ShutdownTimeout: Defaults to 30s if not set

Logger Configuration

  • Level: Defaults to logrus.InfoLevel if not set
  • Formatter: Defaults to "json" if empty
  • DefaultWriter: Defaults to "stderr" if empty

Configuration Files

The framework supports both YAML and JSON configuration files:

  • YAML: See config.example.yaml
  • JSON: See config.example.json

Usage

Loading from File

import ( "trellis.tech/trellis/framework.v0/services" ) service, err := services.New("config.yaml") if err != nil { log.Fatal(err) }

Programmatic Configuration

import ( "github.com/sirupsen/logrus" "trellis.tech/trellis/framework.v0/configs" "trellis.tech/trellis/framework.v0/services" ) cfg := &configs.Config{ ServiceType: configs.ServiceTypeHTTP, ServiceConfig: configs.ServiceConfig{ Name: "my_service", Address: ":8080", Mode: "release", }, LoggerConfig: configs.LoggerConfig{ Level: logrus.InfoLevel, Formatter: "json", DefaultWriter: "stderr", }, } // Defaults are automatically set during validation service, err := services.NewWithConfig(cfg) if err != nil { log.Fatal(err) }

Hot Reload

Enable configuration hot reload to apply changes without restarting:

hot_reload: enabled: true config_file: "./config.yaml" reload_signal: "SIGHUP" validate_before_reload: true debounce_interval: 1s reloadable_sections: [] # empty = reload all reloadable sections

Non-reloadable fields are preserved automatically (e.g., service.address, service.name, service_type).

Configuration Validation

The framework validates configuration automatically:

  • Service Name: Must match pattern ^[a-zA-Z][a-zA-Z0-9_]+$
  • Service Type: Must be "http", "grpc", or ""
  • Mode: Must be "debug", "test", "release", or ""
  • Formatter: Must be "json", "text", or ""

Setting Defaults

You can manually set defaults before validation:

cfg := &configs.Config{ ServiceConfig: configs.ServiceConfig{ Name: "my_service", }, } // Set defaults manually cfg.SetDefaults() // Or let Validate() set them automatically err := cfg.Validate()

Configuration Examples

Minimal Configuration

service: name: "my_service" address: ":8080"

Full Configuration

See config.example.yaml or config.example.json for a complete example with all available options.

Configuration Fields

ServiceConfig

  • name (required): Service name
  • mode: Gin framework mode ("debug", "test", "release")
  • address: Server listen address
  • shutdown_timeout: Graceful shutdown timeout
  • tls: TLS/HTTPS configuration
  • http2: HTTP/2 server configuration
  • metrics: Metrics collection configuration
  • static_path: Static file server path
  • cors: CORS middleware configuration
  • pprof: Performance profiling configuration
  • rate_limit: Rate limiting configuration
  • circuit_breaker: Circuit breaker configuration
  • servers: Server-specific configuration

LoggerConfig

  • level: Log level (panic, fatal, error, warn, info, debug, trace)
  • report_caller: Enable caller information in logs
  • default_writer: Log output (stdout, stderr, discard)
  • formatter: Log format (json, text)

CircuitBreakerConfig

  • enabled: Enable circuit breaker
  • name: Circuit breaker name
  • max_requests: Maximum requests allowed in half-open state
  • interval: Time period for counting errors (e.g., "60s", "1m")
  • timeout: Timeout before attempting to close from open state (e.g., "60s", "1m")
  • consecutive_failures: Number of consecutive failures before opening the circuit
  • skip_paths: Paths to skip circuit breaking (e.g., ["/health", "/metrics"])
  • status_code: HTTP status code when circuit is open (default: 503)
  • message: Error message when circuit is open

Configuration Reference

Complete Configuration Example

See config.example.yaml or config.example.json for a complete configuration example with all available options.

Configuration Validation

The framework automatically validates configuration when creating a service:

  • Service name must match pattern: ^[a-zA-Z][a-zA-Z0-9_]+$
  • Service type must be "http", "grpc", or "" (defaults to "http")
  • Mode must be "debug", "test", "release", or "" (defaults to "release")
  • Formatter must be "json", "text", or "" (defaults to "json")

Configuration Methods

  1. From File: Load configuration from YAML or JSON file
  2. Programmatic: Create configuration in code
  3. Environment Variables: Can be combined with file-based config (via your config loader)

Best Practices

  1. Use YAML for readability: YAML files are easier to read and maintain
  2. Set required fields: Always set service.name and service.address
  3. Use defaults when possible: Let the framework set defaults for optional fields
  4. Validate early: Call Validate() before using configuration
  5. Environment-specific configs: Use different config files for dev/staging/prod
  6. Version control: Keep configuration examples in version control
  7. Documentation: Document any custom configuration in your project README
  8. Hot Reload: Prefer reloading supported sections over restarts in production for safe, fast changes

Metrics Registry Integration

All HTTP and gRPC middlewares/interceptors register Prometheus metrics via trellis.tech/trellis/framework.v0/utils/metrics. This abstraction lets you swap the underlying prometheus.Registerer:

import ( \"github.com/prometheus/client_golang/prometheus\" \"github.com/prometheus/client_golang/prometheus/prometheus\" \"trellis.tech/trellis/framework.v0/utils/metrics\" ) func main() { reg := prometheus.NewRegistry() metrics.SetRegisterer(reg) // must be called before constructing the service // proceed to create services.NewWithConfig(...) }

If you prefer the built-in /metrics endpoint, set:

service: metrics: metric_path: \"/metrics\"

Alternatively, expose your custom registry via promhttp.HandlerFor(reg, ...) on your own mux.