https://github.com/atomicgo/service
📦 Template repository for AtomicGo repositories
https://github.com/atomicgo/service
atomicgo go golang golang-library hacktoberfest
Last synced: 12 months ago
JSON representation
📦 Template repository for AtomicGo repositories
- Host: GitHub
- URL: https://github.com/atomicgo/service
- Owner: atomicgo
- License: mit
- Created: 2025-07-11T17:51:24.000Z (12 months ago)
- Default Branch: main
- Last Pushed: 2025-07-11T20:15:19.000Z (12 months ago)
- Last Synced: 2025-07-11T20:33:33.378Z (12 months ago)
- Topics: atomicgo, go, golang, golang-library, hacktoberfest
- Language: Go
- Homepage: https://atomicgo.dev
- Size: 34.2 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
AtomicGo | service

---
Documentation
|
Contributing
|
Code of Conduct
---
go get atomicgo.dev/service
---
A minimal boilerplate wrapper for building production-ready Go HTTP services. This library reduces the boilerplate of writing production/enterprise-grade Go services to a minimum.
**What this library provides:**
- Essential production features out of the box (metrics, health checks, graceful shutdown)
- Kubernetes and containerization boilerplate
- Lightweight wrapper around http.Server for high availability services
**What this library does NOT provide:**
- HTTP framework or routing
- Business logic or application patterns
- Restrictions on how you write your HTTP handlers
- Opinionated application architecture
Write HTTP handlers exactly as you prefer, using any patterns or frameworks you choose. This library handles the operational concerns while staying out of your application logic.
## Features
- **Minimal Boilerplate**: Reduces production service setup to a few lines of code
- **HTTP Server Wrapper**: Lightweight wrapper around http.Server with production defaults
- **Metrics**: Built-in Prometheus metrics collection with automatic request tracking
- **Logging**: Structured logging with slog integration and context-aware loggers
- **Middleware**: Extensible middleware system with built-in recovery and logging
- **Configuration**: Environment-based configuration with sensible defaults
- **Graceful Shutdown**: Signal handling with configurable shutdown hooks
- **Health Checks**: Built-in health check endpoints for Kubernetes
- **Framework Agnostic**: Works with any HTTP patterns or frameworks you prefer (as long as the framework supports the standard `http` package)
## Quick Start
Minimal boilerplate to get a production-ready service with metrics, health checks, and graceful shutdown:
```go
package main
import (
"log/slog"
"net/http"
"os"
"atomicgo.dev/service"
)
func main() {
// Create service with default configuration
svc := service.New("my-service", nil)
// Write HTTP handlers exactly as you prefer
svc.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
logger := service.GetLogger(r) // Easy access to the logger
logger.Info("Hello, World!")
w.Write([]byte("Hello, World!"))
})
// Start service (includes graceful shutdown, metrics, health checks)
if err := svc.Start(); err != nil {
os.Exit(1)
}
}
```
That's it! Your service now has:
- Prometheus metrics at `:9090/metrics`
- Comprehensive health checks at `:9090/health`
- Kubernetes readiness probe at `:9090/ready`
- Kubernetes liveness probe at `:9090/live`
- Graceful shutdown handling
- Structured logging
- Kubernetes-ready configuration
## Configuration
The framework supports configuration via environment variables with sensible defaults:
| Variable | Default | Description |
|----------|---------|-------------|
| `ADDR` | `:8080` | HTTP server address |
| `METRICS_ADDR` | `:9090` | Metrics server address |
| `METRICS_PATH` | `/metrics` | Metrics endpoint path |
| `HEALTH_PATH` | `/health` | Health check endpoint path |
| `READINESS_PATH` | `/ready` | Readiness probe endpoint path |
| `LIVENESS_PATH` | `/live` | Liveness probe endpoint path |
| `SERVICE_VERSION` | `v1.0.0` | Service version for health checks |
| `READ_TIMEOUT` | `10s` | HTTP read timeout |
| `WRITE_TIMEOUT` | `10s` | HTTP write timeout |
| `IDLE_TIMEOUT` | `120s` | HTTP idle timeout |
| `SHUTDOWN_TIMEOUT` | `30s` | Graceful shutdown timeout |
```go
// Load configuration from environment
config, err := service.LoadFromEnv()
if err != nil {
log.Fatal(err)
}
// Create service with custom configuration
svc := service.New("my-service", config)
```
## Middleware
The framework includes several built-in middleware:
- **LoggerMiddleware**: Injects logger into request context
- **RecoveryMiddleware**: Recovers from panics and logs errors
- **RequestLoggingMiddleware**: Logs incoming requests
- **MetricsMiddleware**: Tracks HTTP metrics for Prometheus
```go
// Add custom middleware
svc.Use(func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Custom", "value")
next.ServeHTTP(w, r)
})
})
```
## Metrics
The framework provides a flexible metrics system with built-in HTTP metrics and support for custom metrics.
### Built-in HTTP Metrics
The framework automatically collects these Prometheus metrics for every service:
- `{service_name}_http_requests_total`: Total HTTP requests by method, endpoint, and status
- `{service_name}_http_request_duration_seconds`: Request duration histogram by method, endpoint, and status
- `{service_name}_http_requests_in_flight`: Current number of in-flight requests
These metrics are provided automatically without any configuration required.
### Custom Metrics
You can easily register and use custom metrics in your service:
```go
func main() {
svc := service.New("my-service", nil)
// Register custom metrics
svc.RegisterCounter(service.MetricConfig{
Name: "user_registrations_total",
Help: "Total number of user registrations",
Labels: []string{"source", "status"},
})
svc.RegisterGauge(service.MetricConfig{
Name: "active_users",
Help: "Number of currently active users",
Labels: []string{"user_type"},
})
svc.RegisterHistogram(service.MetricConfig{
Name: "request_processing_duration_seconds",
Help: "Time spent processing requests",
Labels: []string{"operation"},
Buckets: []float64{0.001, 0.01, 0.1, 1.0, 10.0},
})
svc.RegisterSummary(service.MetricConfig{
Name: "response_size_bytes",
Help: "Size of responses in bytes",
Labels: []string{"endpoint"},
Objectives: map[float64]float64{0.5: 0.05, 0.9: 0.01, 0.99: 0.001},
})
// Use metrics in handlers
svc.HandleFunc("/register", func(w http.ResponseWriter, r *http.Request) {
// Increment counter
service.IncCounter(r, "user_registrations_total", "web", "success")
// Set gauge value
service.SetGauge(r, "active_users", 42.0, "premium")
// Observe histogram
service.ObserveHistogram(r, "request_processing_duration_seconds", 0.25, "registration")
// Observe summary
service.ObserveSummary(r, "response_size_bytes", 1024.0, "/register")
w.Write([]byte("User registered"))
})
svc.Start()
}
```
### Metric Types
The framework supports all standard Prometheus metric types:
- **Counter**: Monotonically increasing values (e.g., total requests, errors)
- **Gauge**: Values that can go up and down (e.g., active connections, memory usage)
- **Histogram**: Observations in configurable buckets (e.g., request duration, response size)
- **Summary**: Observations with configurable quantiles (e.g., request latency percentiles)
### Direct Access
For advanced use cases, you can access the metrics collector directly:
```go
func myHandler(w http.ResponseWriter, r *http.Request) {
metrics := service.GetMetrics(r)
if metrics != nil {
// Direct access to metrics collector
metrics.IncCounter("my_counter", "label_value")
metrics.SetGauge("my_gauge", 42.0, "label_value")
// Access the underlying Prometheus registry
registry := metrics.GetRegistry()
// Use registry for custom integrations
}
}
```
All metrics are available at `:9090/metrics` by default.
## Graceful Shutdown
The framework includes graceful shutdown by default with signal handling and custom hooks:
```go
// Add shutdown hooks
svc.AddShutdownHook(func() error {
// Cleanup resources
return nil
})
// Start service (includes graceful shutdown)
svc.Start()
```
## Logging
The framework uses structured logging with slog and provides context-aware loggers:
```go
func myHandler(w http.ResponseWriter, r *http.Request) {
logger := service.GetLogger(r)
logger.Info("request processed", "path", r.URL.Path)
}
```
## Health Checks
The framework integrates with [HelloFresh's health-go library](https://github.com/hellofresh/health-go) to provide comprehensive health checking capabilities.
### Built-in Health Endpoints
Health check endpoints are automatically available on the metrics server:
- `:9090/health`: Comprehensive health check with detailed status information
- `:9090/ready`: Kubernetes readiness probe endpoint
- `:9090/live`: Kubernetes liveness probe endpoint
- `:9090/metrics`: Prometheus metrics
### Adding Custom Health Checks
You can register custom health checks using the `RegisterHealthCheck` method:
```go
func main() {
svc := service.New("my-service", nil)
// Register a database health check
svc.RegisterHealthCheck(health.Config{
Name: "database",
Timeout: time.Second * 5,
SkipOnErr: false, // This check is critical
Check: func(ctx context.Context) error {
// Your database health check logic here
return db.PingContext(ctx)
},
})
// Register a Redis health check
svc.RegisterHealthCheck(health.Config{
Name: "redis",
Timeout: time.Second * 3,
SkipOnErr: true, // This check is optional
Check: func(ctx context.Context) error {
// Your Redis health check logic here
return redisClient.Ping(ctx).Err()
},
})
svc.Start()
}
```
### Using Built-in Health Checkers
The health-go library provides several built-in health checkers for common services:
```go
import (
"github.com/hellofresh/health-go/v5"
healthPostgres "github.com/hellofresh/health-go/v5/checks/postgres"
healthRedis "github.com/hellofresh/health-go/v5/checks/redis"
)
func main() {
svc := service.New("my-service", nil)
// PostgreSQL health check
svc.RegisterHealthCheck(health.Config{
Name: "postgresql",
Timeout: time.Second * 5,
SkipOnErr: false, // Critical check - service is unhealthy if DB is down
Check: healthPostgres.New(healthPostgres.Config{
DSN: dbURL,
}),
})
// Redis health check
svc.RegisterHealthCheck(health.Config{
Name: "redis",
Timeout: time.Second * 3,
Check: healthRedis.New(healthRedis.Config{
Addr: "localhost:6379",
}),
})
svc.Start()
}
```
### Health Check Configuration
You can configure health check endpoints using environment variables:
| Variable | Default | Description |
|----------|---------|-------------|
| `HEALTH_PATH` | `/health` | Main health check endpoint path |
| `READINESS_PATH` | `/ready` | Kubernetes readiness probe path |
| `LIVENESS_PATH` | `/live` | Kubernetes liveness probe path |
### Accessing Health Checker in Handlers
You can access the health checker in your HTTP handlers:
```go
func myHandler(w http.ResponseWriter, r *http.Request) {
healthChecker := service.GetHealthChecker(r)
if healthChecker != nil {
check := healthChecker.Measure(r.Context())
// Use status information
w.Write([]byte(fmt.Sprintf("Health checks: %+v", check)))
}
}
```
## Kubernetes Deployment
The library provides all the boilerplate needed for Kubernetes deployments:
- Graceful shutdown handling SIGTERM
- Health check endpoints for liveness/readiness probes
- Prometheus metrics for monitoring
- Configurable resource limits via environment variables
- No additional Kubernetes-specific code required
## Examples
See the `_examples/` directory for complete working examples demonstrating:
- **minimal/**: Basic service setup with default configuration
- **custom-metrics/**: Comprehensive custom metrics registration and usage
- **prometheus-counter/**: Simple custom counter example (HTTP metrics are automatic)
- **health-check-***: Various health check integrations
- **shutdown-hook/**: Graceful shutdown with custom cleanup
## Best Practices
1. **Minimal setup** - Start with default configuration and customize only what you need
2. **Write HTTP handlers naturally** - Use any patterns or frameworks you prefer
3. **Add custom shutdown hooks** for resource cleanup when needed
4. **Use structured logging** for better observability
5. **Monitor metrics** in production environments
## Contributing
We welcome contributions! Please see our [Contributing Guide](https://github.com/atomicgo/atomicgo/blob/main/CONTRIBUTING.md) for details.
## License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
---
> [AtomicGo.dev](https://atomicgo.dev) ·
> with ❤️ by [@MarvinJWendt](https://github.com/MarvinJWendt) |
> [MarvinJWendt.com](https://marvinjwendt.com)