App
API reference for the Rivaas App package - a batteries-included web framework with integrated observability.
This is the API reference for the rivaas.dev/app package. For learning-focused documentation, see the App Guide.
Overview
The App package provides a high-level, opinionated framework built on top of the Rivaas router. It includes:
- Integrated observability (metrics, tracing, logging)
- Lifecycle management with hooks
- Graceful shutdown handling
- Health and debug endpoints
- OpenAPI spec generation
- Request binding and validation
- Import Path:
rivaas.dev/app - Go Version: 1.25+
- License: Apache 2.0
Architecture
┌─────────────────────────────────────────┐
│ Application Layer │
│ (app package) │
│ │
│ • Configuration Management │
│ • Lifecycle Hooks │
│ • Observability Integration │
│ • Server Management │
│ • Request Binding/Validation │
└──────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Router Layer │
│ (router package) │
│ │
│ • HTTP Routing │
│ • Middleware Chain │
│ • Request Context │
│ • Path Parameters │
└──────────────┬──────────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ Standard Library │
│ (net/http) │
└─────────────────────────────────────────┘
Quick Reference
Core Types
- App - Main application type
- Context - Request context with app-level features
- HandlerFunc - Handler function type
Key Functions
- New() - Create a new app (returns error)
- MustNew() - Create a new app (panics on error)
Configuration
API Reference
Resources
App Type
The main application type that wraps the router with app-level features.
type App struct {
// contains filtered or unexported fields
}
Creating Apps
// Returns (*App, error) for error handling
a, err := app.New(
app.WithServiceName("my-api"),
app.WithServiceVersion("v1.0.0"),
)
if err != nil {
log.Fatal(err)
}
// Panics on error (like regexp.MustCompile)
a := app.MustNew(
app.WithServiceName("my-api"),
)
HTTP Methods
Register routes for HTTP methods:
a.GET(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.POST(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.PUT(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.DELETE(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.PATCH(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.HEAD(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.OPTIONS(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
a.Any(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
Server Management
a.Start(ctx context.Context, addr string) error
a.StartTLS(ctx context.Context, addr, certFile, keyFile string) error
a.StartMTLS(ctx context.Context, addr string, cert tls.Certificate, opts ...MTLSOption) error
Lifecycle Hooks
a.OnStart(fn func(context.Context) error)
a.OnReady(fn func())
a.OnShutdown(fn func(context.Context))
a.OnStop(fn func())
a.OnRoute(fn func(*route.Route))
See Lifecycle Hooks for details.
Context Type
Request context that extends router.Context with app-level features.
type Context struct {
*router.Context
// contains filtered or unexported fields
}
Request Binding
c.Bind(out any) error
c.BindJSONStrict(out any) error
c.BindAndValidate(out any, opts ...validation.Option) error
c.BindAndValidateStrict(out any, opts ...validation.Option) error
c.MustBindAndValidate(out any, opts ...validation.Option) bool
Error Handling
c.Error(err error)
c.ErrorStatus(err error, status int)
c.NotFound(message string)
c.BadRequest(message string)
c.Unauthorized(message string)
c.Forbidden(message string)
c.InternalError(err error)
Logging
See Context API for complete reference.
HandlerFunc
Handler function type that receives an app Context.
type HandlerFunc func(*Context)
Example:
func handler(c *app.Context) {
c.JSON(http.StatusOK, data)
}
a.GET("/", handler)
Next Steps
1 - API Reference
Complete API reference for the App package.
Core Functions
New
func New(opts ...Option) (*App, error)
Creates a new App instance with the given options. Returns an error if configuration is invalid.
Parameters:
opts - Configuration options
Returns:
*App - The app instanceerror - Configuration validation errors
Example:
a, err := app.New(
app.WithServiceName("my-api"),
app.WithServiceVersion("v1.0.0"),
)
if err != nil {
log.Fatal(err)
}
MustNew
func MustNew(opts ...Option) *App
Creates a new App instance or panics on error. Use for initialization in main() functions.
Parameters:
opts - Configuration options
Returns:
Panics: If configuration is invalid
Example:
a := app.MustNew(
app.WithServiceName("my-api"),
)
App Methods
HTTP Method Shortcuts
func (a *App) GET(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) POST(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) PUT(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) DELETE(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) PATCH(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) HEAD(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) OPTIONS(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
func (a *App) Any(path string, handler HandlerFunc, opts ...RouteOption) *route.Route
Register routes for HTTP methods.
Middleware
func (a *App) Use(middleware ...HandlerFunc)
Adds middleware to the app. Middleware executes for all routes registered after Use().
Route Groups
func (a *App) Group(prefix string, middleware ...HandlerFunc) *Group
func (a *App) Version(version string) *VersionGroup
Create route groups and version groups.
Static Files
func (a *App) Static(prefix, root string)
func (a *App) File(path, filepath string)
func (a *App) StaticFS(prefix string, fs http.FileSystem)
func (a *App) NoRoute(handler HandlerFunc)
Serve static files and set custom 404 handler.
Server Management
func (a *App) Start(ctx context.Context, addr string) error
func (a *App) StartTLS(ctx context.Context, addr, certFile, keyFile string) error
func (a *App) StartMTLS(ctx context.Context, addr string, cert tls.Certificate, opts ...MTLSOption) error
Start HTTP, HTTPS, or mTLS servers with graceful shutdown.
Lifecycle Hooks
func (a *App) OnStart(fn func(context.Context) error)
func (a *App) OnReady(fn func())
func (a *App) OnShutdown(fn func(context.Context))
func (a *App) OnStop(fn func())
func (a *App) OnRoute(fn func(*route.Route))
Register lifecycle hooks. See Lifecycle Hooks for details.
Accessors
func (a *App) Router() *router.Router
func (a *App) Metrics() *metrics.Recorder
func (a *App) Tracing() *tracing.Tracer
func (a *App) Readiness() *ReadinessManager
func (a *App) ServiceName() string
func (a *App) ServiceVersion() string
func (a *App) Environment() string
Access underlying components and configuration.
Route Management
func (a *App) Route(name string) (*route.Route, bool)
func (a *App) Routes() []*route.Route
func (a *App) URLFor(routeName string, params map[string]string, query map[string][]string) (string, error)
func (a *App) MustURLFor(routeName string, params map[string]string, query map[string][]string) string
Route lookup and URL generation. Router must be frozen (after Start()).
Metrics
func (a *App) GetMetricsHandler() (http.Handler, error)
func (a *App) GetMetricsServerAddress() string
Access metrics handler and server address.
Logging
func (a *App) BaseLogger() *slog.Logger
Returns the application’s base logger. Never returns nil.
Testing
func (a *App) Test(req *http.Request, opts ...TestOption) (*http.Response, error)
func (a *App) TestJSON(method, path string, body any, opts ...TestOption) (*http.Response, error)
Test routes without starting a server.
Helper Functions
ExpectJSON
func ExpectJSON(t testingT, resp *http.Response, statusCode int, out any)
Test helper that asserts response status and decodes JSON.
Generic Binding
func BindAndValidateInto[T any](c *Context, opts ...validation.Option) (T, error)
func MustBindAndValidateInto[T any](c *Context, opts ...validation.Option) (T, bool)
Type-safe binding with generics.
Types
HandlerFunc
type HandlerFunc func(*Context)
Handler function that receives an app Context.
TestOption
type TestOption func(*testConfig)
func WithTimeout(d time.Duration) TestOption
func WithContext(ctx context.Context) TestOption
Options for testing.
Next Steps
2 - Configuration Options
App-level configuration options reference.
Service Configuration
WithServiceName
func WithServiceName(name string) Option
Sets the service name used in observability metadata. This includes metrics, traces, and logs. If empty, validation fails.
Default: "rivaas-app"
WithServiceVersion
func WithServiceVersion(version string) Option
Sets the service version used in observability and API documentation. Must be non-empty or validation fails.
Default: "1.0.0"
WithEnvironment
func WithEnvironment(env string) Option
Sets the environment mode. Valid values: "development", "production". Invalid values cause validation to fail.
Default: "development"
Server Configuration
WithServer
func WithServer(opts ...ServerOption) Option
Configures server settings. See Server Options for sub-options.
Observability
WithObservability
func WithObservability(opts ...ObservabilityOption) Option
Configures all observability components (metrics, tracing, logging). See Observability Options for sub-options.
Endpoints
WithHealthEndpoints
func WithHealthEndpoints(opts ...HealthOption) Option
Enables health endpoints. See Health Options for sub-options.
WithDebugEndpoints
func WithDebugEndpoints(opts ...DebugOption) Option
Enables debug endpoints. See Debug Options for sub-options.
Middleware
WithMiddleware
func WithMiddleware(middlewares ...HandlerFunc) Option
Adds middleware during app initialization. Multiple calls accumulate.
WithoutDefaultMiddleware
func WithoutDefaultMiddleware() Option
Disables default middleware (recovery). Use when you want full control over middleware.
Router
WithRouter
func WithRouter(opts ...router.Option) Option
Passes router options to the underlying router. Multiple calls accumulate.
OpenAPI
WithOpenAPI
func WithOpenAPI(opts ...openapi.Option) Option
Enables OpenAPI specification generation. Service name and version are automatically injected from app-level configuration.
func WithErrorFormatter(formatter errors.Formatter) Option
Configures a single error formatter for all error responses.
func WithErrorFormatters(formatters map[string]errors.Formatter) Option
Configures multiple error formatters with content negotiation based on Accept header.
func WithDefaultErrorFormat(mediaType string) Option
Sets the default format when no Accept header matches. Only used with WithErrorFormatters.
Complete Example
a, err := app.New(
// Service
app.WithServiceName("orders-api"),
app.WithServiceVersion("v2.0.0"),
app.WithEnvironment("production"),
// Server
app.WithServer(
app.WithReadTimeout(10 * time.Second),
app.WithWriteTimeout(15 * time.Second),
app.WithShutdownTimeout(30 * time.Second),
),
// Observability
app.WithObservability(
app.WithLogging(logging.WithJSONHandler()),
app.WithMetrics(),
app.WithTracing(tracing.WithOTLP("localhost:4317")),
),
// Health endpoints
app.WithHealthEndpoints(
app.WithReadinessCheck("database", dbCheck),
),
// OpenAPI
app.WithOpenAPI(
openapi.WithSwaggerUI(true, "/docs"),
),
)
Next Steps
3 - Server Options
Server configuration options reference.
Server Options
These options are used with WithServer():
app.WithServer(
app.WithReadTimeout(10 * time.Second),
app.WithWriteTimeout(15 * time.Second),
)
Timeout Options
WithReadTimeout
func WithReadTimeout(d time.Duration) ServerOption
Maximum time to read entire request (including body). Must be positive.
Default: 10s
WithWriteTimeout
func WithWriteTimeout(d time.Duration) ServerOption
Maximum time to write response. Must be positive. Should be >= ReadTimeout.
Default: 10s
WithIdleTimeout
func WithIdleTimeout(d time.Duration) ServerOption
Maximum time to wait for next request on keep-alive connection. Must be positive.
Default: 60s
func WithReadHeaderTimeout(d time.Duration) ServerOption
Maximum time to read request headers. Must be positive.
Default: 2s
WithShutdownTimeout
func WithShutdownTimeout(d time.Duration) ServerOption
Graceful shutdown timeout. Must be at least 1 second.
Default: 30s
Size Options
func WithMaxHeaderBytes(n int) ServerOption
Maximum request header size in bytes. Must be at least 1KB (1024 bytes).
Default: 1MB (1048576 bytes)
Validation
Configuration is automatically validated:
- All timeouts must be positive
- ReadTimeout should not exceed WriteTimeout
- ShutdownTimeout must be at least 1 second
- MaxHeaderBytes must be at least 1KB
Invalid configuration causes app.New() to return an error.
4 - Observability Options
Observability configuration options reference (metrics, tracing, logging).
Observability Options
These options are used with WithObservability():
app.WithObservability(
app.WithLogging(logging.WithJSONHandler()),
app.WithMetrics(),
app.WithTracing(tracing.WithOTLP("localhost:4317")),
)
Component Options
WithLogging
func WithLogging(opts ...logging.Option) ObservabilityOption
Enables structured logging with slog. Service name/version automatically injected.
WithMetrics
func WithMetrics(opts ...metrics.Option) ObservabilityOption
Enables metrics collection (Prometheus by default). Service name/version automatically injected.
WithTracing
func WithTracing(opts ...tracing.Option) ObservabilityOption
Enables distributed tracing. Service name/version automatically injected.
Metrics Server Options
WithMetricsOnMainRouter
func WithMetricsOnMainRouter(path string) ObservabilityOption
Mounts metrics endpoint on the main HTTP server (default: separate server).
WithMetricsSeparateServer
func WithMetricsSeparateServer(addr, path string) ObservabilityOption
Configures separate metrics server address and path.
Default: :9090/metrics
Path Filtering
WithExcludePaths
func WithExcludePaths(paths ...string) ObservabilityOption
Excludes exact paths from observability.
WithExcludePrefixes
func WithExcludePrefixes(prefixes ...string) ObservabilityOption
Excludes path prefixes from observability.
WithExcludePatterns
func WithExcludePatterns(patterns ...string) ObservabilityOption
Excludes paths matching regex patterns from observability.
WithoutDefaultExclusions
func WithoutDefaultExclusions() ObservabilityOption
Disables default path exclusions (/health*, /metrics, /debug/*).
Access Logging
WithAccessLogging
func WithAccessLogging(enabled bool) ObservabilityOption
Enables or disables access logging.
Default: true
WithLogOnlyErrors
func WithLogOnlyErrors() ObservabilityOption
Logs only errors and slow requests (reduces log volume).
Default: false in development, true in production
In production, this is automatically enabled to reduce log volume. Normal successful requests are not logged, but errors (status >= 400) and slow requests are always logged.
WithSlowThreshold
func WithSlowThreshold(d time.Duration) ObservabilityOption
Marks requests as slow if they exceed this duration.
Default: 1s
Example
app.WithObservability(
// Components
app.WithLogging(logging.WithJSONHandler()),
app.WithMetrics(metrics.WithPrometheus(":9090", "/metrics")),
app.WithTracing(tracing.WithOTLP("localhost:4317")),
// Path filtering
app.WithExcludePaths("/healthz", "/readyz"),
app.WithExcludePrefixes("/internal/"),
// Access logging
app.WithLogOnlyErrors(),
app.WithSlowThreshold(500 * time.Millisecond),
)
5 - Health Options
Health endpoint configuration options reference.
Health Options
These options are used with WithHealthEndpoints():
app.WithHealthEndpoints(
app.WithReadinessCheck("database", dbCheck),
app.WithHealthTimeout(800 * time.Millisecond),
)
Path Configuration
WithHealthPrefix
func WithHealthPrefix(prefix string) HealthOption
Mounts health endpoints under a prefix.
Default: "" (root)
WithHealthzPath
func WithHealthzPath(path string) HealthOption
Custom liveness probe path.
Default: "/healthz"
WithReadyzPath
func WithReadyzPath(path string) HealthOption
Custom readiness probe path.
Default: "/readyz"
Check Configuration
WithHealthTimeout
func WithHealthTimeout(d time.Duration) HealthOption
Timeout for each health check.
Default: 1s
WithLivenessCheck
func WithLivenessCheck(name string, fn CheckFunc) HealthOption
Adds a liveness check. Liveness checks should be dependency-free and fast.
WithReadinessCheck
func WithReadinessCheck(name string, fn CheckFunc) HealthOption
Adds a readiness check. Readiness checks verify external dependencies.
CheckFunc
type CheckFunc func(context.Context) error
Health check function that returns nil if healthy, error if unhealthy.
Example
app.WithHealthEndpoints(
app.WithHealthPrefix("/_system"),
app.WithHealthTimeout(800 * time.Millisecond),
app.WithLivenessCheck("process", func(ctx context.Context) error {
return nil
}),
app.WithReadinessCheck("database", func(ctx context.Context) error {
return db.PingContext(ctx)
}),
)
// Endpoints:
// GET /_system/healthz - Liveness (200 if all checks pass)
// GET /_system/readyz - Readiness (204 if all checks pass)
6 - Debug Options
Debug endpoint configuration options reference.
Debug Options
These options are used with WithDebugEndpoints():
app.WithDebugEndpoints(
app.WithPprofIf(os.Getenv("PPROF_ENABLED") == "true"),
)
Path Configuration
WithDebugPrefix
func WithDebugPrefix(prefix string) DebugOption
Mounts debug endpoints under a custom prefix.
Default: "/debug"
pprof Options
WithPprof
func WithPprof() DebugOption
Enables pprof endpoints unconditionally.
WithPprofIf
func WithPprofIf(condition bool) DebugOption
Conditionally enables pprof endpoints based on a boolean condition.
Available Endpoints
When pprof is enabled:
GET /debug/pprof/ - Main pprof indexGET /debug/pprof/cmdline - Command lineGET /debug/pprof/profile - CPU profileGET /debug/pprof/symbol - Symbol lookupGET /debug/pprof/trace - Execution traceGET /debug/pprof/allocs - Memory allocationsGET /debug/pprof/block - Block profileGET /debug/pprof/goroutine - Goroutine profileGET /debug/pprof/heap - Heap profileGET /debug/pprof/mutex - Mutex profileGET /debug/pprof/threadcreate - Thread creation profile
Security Warning
⚠️ Never enable pprof in production without proper authentication. Debug endpoints expose sensitive runtime information.
Example
// Development: enable unconditionally
app.WithDebugEndpoints(
app.WithPprof(),
)
// Production: enable conditionally
app.WithDebugEndpoints(
app.WithDebugPrefix("/_internal/debug"),
app.WithPprofIf(os.Getenv("PPROF_ENABLED") == "true"),
)
7 - Context API
Context methods for request handling.
Request Binding
Bind
func (c *Context) Bind(out any) error
Automatically binds from all relevant sources based on struct tags (path, query, header, cookie, json, form).
BindJSONStrict
func (c *Context) BindJSONStrict(out any) error
Binds JSON with unknown field rejection.
BindAndValidate
func (c *Context) BindAndValidate(out any, opts ...validation.Option) error
Binds and validates in one call.
BindAndValidateStrict
func (c *Context) BindAndValidateStrict(out any, opts ...validation.Option) error
Binds JSON strictly (rejects unknown fields) and validates.
MustBindAndValidate
func (c *Context) MustBindAndValidate(out any, opts ...validation.Option) bool
Binds and validates, automatically sending error responses on failure. Returns true if successful.
Error Handling
Error
func (c *Context) Error(err error)
Sends a formatted error response using the configured formatter.
ErrorStatus
func (c *Context) ErrorStatus(err error, status int)
Sends an error response with explicit status code.
NotFound
func (c *Context) NotFound(message string)
Sends a 404 Not Found error.
BadRequest
func (c *Context) BadRequest(message string)
Sends a 400 Bad Request error.
Unauthorized
func (c *Context) Unauthorized(message string)
Sends a 401 Unauthorized error.
Forbidden
func (c *Context) Forbidden(message string)
Sends a 403 Forbidden error.
InternalError
func (c *Context) InternalError(err error)
Sends a 500 Internal Server Error.
Logging
Logger
func (c *Context) Logger() *slog.Logger
Returns the request-scoped logger with automatic context (HTTP metadata, trace IDs, request ID). Never returns nil.
Presence
Presence
func (c *Context) Presence() validation.PresenceMap
Returns the presence map for the current request (tracks which fields were present in JSON).
ResetBinding
func (c *Context) ResetBinding()
Resets binding metadata (useful for testing).
Router Context
The app Context embeds router.Context, providing access to all router features:
c.Request - HTTP requestc.Response - HTTP response writerc.Param(name) - Path parameterc.Query(name) - Query parameterc.JSON(status, data) - Send JSON responsec.String(status, text) - Send text responsec.HTML(status, html) - Send HTML response- And more…
See Router Context API for complete router context reference.
8 - Lifecycle Hooks
Lifecycle hook APIs and execution order.
Hook Methods
OnStart
func (a *App) OnStart(fn func(context.Context) error)
Called before server starts. Hooks run sequentially and stop on first error.
Use for: Database connections, migrations, initialization that must succeed.
OnReady
func (a *App) OnReady(fn func())
Called after server starts listening. Hooks run asynchronously and don’t block startup.
Use for: Warmup tasks, service discovery registration.
OnShutdown
func (a *App) OnShutdown(fn func(context.Context))
Called during graceful shutdown. Hooks run in LIFO order with shutdown timeout.
Use for: Closing connections, flushing buffers, cleanup that must complete within timeout.
OnStop
func (a *App) OnStop(fn func())
Called after shutdown completes. Hooks run in best-effort mode and panics are caught.
Use for: Final cleanup that doesn’t need timeout.
OnRoute
func (a *App) OnRoute(fn func(*route.Route))
Called when a route is registered. Disabled after router freeze.
Use for: Route validation, logging, documentation generation.
Execution Flow
1. app.Start(ctx, ":8080") called
2. OnStart hooks execute (sequential, stop on error)
3. Server starts listening
4. OnReady hooks execute (async, non-blocking)
5. Server handles requests...
6. Context canceled (SIGTERM/SIGINT)
7. OnShutdown hooks execute (LIFO order, with timeout)
8. Server shutdown complete
9. OnStop hooks execute (best-effort, no timeout)
10. Process exits
Hook Characteristics
| Hook | Order | Error Handling | Timeout | Async |
|---|
| OnStart | Sequential | Stop on first error | No | No |
| OnReady | - | Panic caught and logged | No | Yes |
| OnShutdown | LIFO | Errors ignored | Yes (shutdown timeout) | No |
| OnStop | - | Panic caught and logged | No | No |
| OnRoute | Sequential | - | No | No |
Example
a := app.MustNew()
// OnStart: Initialize (sequential, stops on error)
a.OnStart(func(ctx context.Context) error {
return db.Connect(ctx)
})
// OnReady: Post-startup (async, non-blocking)
a.OnReady(func() {
consul.Register("my-service", ":8080")
})
// OnShutdown: Graceful cleanup (LIFO, with timeout)
a.OnShutdown(func(ctx context.Context) {
db.Close()
})
// OnStop: Final cleanup (best-effort)
a.OnStop(func() {
cleanupTempFiles()
})
9 - Troubleshooting
Common issues and solutions for the App package.
Configuration Errors
Validation Errors
Problem: app.New() returns validation errors.
Solution: Check error message for specific field. Common issues:
- Empty service name or version.
- Invalid environment. Must be “development” or “production”.
- ReadTimeout greater than WriteTimeout.
- ShutdownTimeout less than 1 second.
- MaxHeaderBytes less than 1KB.
Example:
a, err := app.New(
app.WithServiceName(""), // ❌ Empty
)
// Error: "serviceName must not be empty"
Import Errors
Problem: Cannot import rivaas.dev/app.
Solution:
go get rivaas.dev/app
go mod tidy
Ensure Go 1.25+ is installed.
Server Issues
Port Already in Use
Problem: Server fails to start with “address already in use”.
Solution: Check if port is in use:
lsof -i :8080
# Or
netstat -an | grep 8080
Kill the process or use a different port.
Routes Not Registering
Problem: Routes return 404 even though registered.
Solution:
- Ensure routes registered before
Start(). - Check paths match exactly. They are case-sensitive.
- Verify HTTP method matches.
- Router freezes on startup. Can’t add routes after.
Graceful Shutdown Not Working
Problem: Server doesn’t shut down cleanly.
Solution:
- Increase shutdown timeout:
WithShutdownTimeout(60 * time.Second). - Check OnShutdown hooks complete quickly.
- Verify handlers respect context cancellation.
Observability Issues
Metrics Not Appearing
Problem: Metrics endpoint returns 404.
Solution:
- Ensure metrics enabled:
WithMetrics() - Check metrics address:
a.GetMetricsServerAddress() - Default is separate server on
:9090/metrics - Use
WithMetricsOnMainRouter("/metrics") to mount on main router
Tracing Not Working
Problem: No traces appear in backend.
Solution:
- Verify tracing enabled:
WithTracing() - Check OTLP endpoint configuration
- Ensure tracing backend is running and accessible
- Verify network connectivity
- Check logs for tracing initialization errors
Logs Not Appearing
Problem: No logs are written.
Solution:
- Ensure logging enabled:
WithLogging() - Check log level configuration
- Verify logger handler is correct (JSON, Console, etc.)
- Use
c.Logger() in handlers, not package-level logger
Middleware Issues
Middleware Not Executing
Problem: Middleware functions aren’t being called.
Solution:
- Ensure middleware added before routes
- Check middleware calls
c.Next() - Verify middleware isn’t returning early
- Default recovery middleware is included automatically
Authentication Failing
Problem: Auth middleware not working correctly.
Solution:
- Check header/token extraction logic
- Verify middleware order (auth should run early)
- Ensure
c.Next() is called on success - Test middleware in isolation
Testing Issues
Test Hangs
Problem: a.Test() never returns.
Solution:
- Set timeout:
a.Test(req, app.WithTimeout(5*time.Second)) - Check for infinite loops in handler
- Verify middleware calls
c.Next()
Test Fails with Panic
Problem: Test panics instead of returning error.
Solution:
- Use
recover() in test or - Check that handler doesn’t panic
- Recovery middleware catches panics in real server
Health Check Issues
Health Checks Always Failing
Problem: /healthz or /readyz always returns 503.
Solution:
- Check health check functions return nil on success
- Verify dependencies (database, cache) are accessible
- Check health timeout is sufficient
- Test health checks independently
Health Checks Never Complete
Problem: Health checks timeout.
Solution:
- Increase timeout:
WithHealthTimeout(2 * time.Second) - Check dependencies respond within timeout
- Verify no deadlocks in check functions
- Use context timeout in check functions
Debugging Tips
Enable Development Mode
app.WithEnvironment("development")
Enables verbose logging and route table display.
Check Observability Status
if a.Metrics() != nil {
fmt.Println("Metrics:", a.GetMetricsServerAddress())
}
if a.Tracing() != nil {
fmt.Println("Tracing enabled")
}
Use Test Helpers
resp, err := a.Test(req) // Test without starting server
Enable GC Tracing
GODEBUG=gctrace=1 go run main.go
Getting Help