package ekko import ( "time" "github.com/labstack/echo/v4" "github.com/labstack/echo/v4/middleware" "github.com/prometheus/client_golang/prometheus" slogecho "github.com/samber/slog-echo" ) // Ekko represents an enhanced Echo web server with pre-configured middleware stack. // It encapsulates server configuration, middleware options, and lifecycle management // for NTP Pool web services. Use New() with functional options to configure. type Ekko struct { name string prom prometheus.Registerer port int routeFn func(e *echo.Echo) error logFilters []slogecho.Filter otelmiddleware echo.MiddlewareFunc gzipConfig *middleware.GzipConfig writeTimeout time.Duration readHeaderTimeout time.Duration } // RouteFn defines a function type for configuring Echo routes and handlers. // It receives a configured Echo instance and should register all application // routes, middleware, and handlers. Return an error to abort server startup. type RouteFn func(e *echo.Echo) error // WithPort sets the HTTP server port. This option is required when using Start(). // The port should be available and the process should have permission to bind to it. func WithPort(port int) func(*Ekko) { return func(ek *Ekko) { ek.port = port } } // WithPrometheus enables Prometheus metrics collection using the provided registerer. // Metrics include HTTP request duration, request count, and response size histograms. // The service name is used as the metrics subsystem for namespacing. func WithPrometheus(reg prometheus.Registerer) func(*Ekko) { return func(ek *Ekko) { ek.prom = reg } } // WithEchoSetup configures application routes and handlers via a setup function. // The provided function receives the configured Echo instance after all middleware // is applied and should register routes, custom middleware, and handlers. func WithEchoSetup(rfn RouteFn) func(*Ekko) { return func(ek *Ekko) { ek.routeFn = rfn } } // WithLogFilters configures access log filtering to reduce log noise. // Filters can exclude specific paths, methods, or status codes from access logs. // Useful for excluding health checks, metrics endpoints, and other high-frequency requests. func WithLogFilters(f []slogecho.Filter) func(*Ekko) { return func(ek *Ekko) { ek.logFilters = f } } // WithOtelMiddleware replaces the default OpenTelemetry middleware with a custom implementation. // The default middleware provides distributed tracing for all requests. Use this option // when you need custom trace configuration or want to disable tracing entirely. func WithOtelMiddleware(mw echo.MiddlewareFunc) func(*Ekko) { return func(ek *Ekko) { ek.otelmiddleware = mw } } // WithWriteTimeout configures the HTTP server write timeout. // This is the maximum duration before timing out writes of the response. // Default is 60 seconds. Should be longer than expected response generation time. func WithWriteTimeout(t time.Duration) func(*Ekko) { return func(ek *Ekko) { ek.writeTimeout = t } } // WithReadHeaderTimeout configures the HTTP server read header timeout. // This is the amount of time allowed to read request headers. // Default is 30 seconds. Should be sufficient for slow clients and large headers. func WithReadHeaderTimeout(t time.Duration) func(*Ekko) { return func(ek *Ekko) { ek.readHeaderTimeout = t } } // WithGzipConfig provides custom gzip compression configuration. // By default, gzip compression is enabled with standard settings. // Use this option to customize compression level, skip patterns, or disable compression. func WithGzipConfig(gzipConfig *middleware.GzipConfig) func(*Ekko) { return func(ek *Ekko) { ek.gzipConfig = gzipConfig } }