SleeperPy includes comprehensive observability with OpenTelemetry:
- Traces: End-to-end request flow visualization
- Metrics: Request counts, latency, cache efficiency, API calls
- Logs: Structured logging with trace correlation
docker-compose -f docker-compose.otel.yml up -dThis starts:
- OTEL Collector (localhost:4317) - Receives telemetry
- Jaeger UI (localhost:16686) - Traces visualization
- Prometheus (localhost:9090) - Metrics storage
- Grafana (localhost:3000) - Unified dashboards
# Install OTEL dependencies first
go get go.opentelemetry.io/otel
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc
go get go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc
go get go.opentelemetry.io/otel/sdk/trace
go get go.opentelemetry.io/otel/sdk/metric
go get go.opentelemetry.io/otel/sdk/resource
go get go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp
# Run with OTEL enabled
OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 \
ENVIRONMENT=development \
go run .- Jaeger: http://localhost:16686 - View distributed traces
- Prometheus: http://localhost:9090 - Query metrics
- Grafana: http://localhost:3000 - Dashboards (auto-login enabled)
http.requests.total- Total requests by route, method, statushttp.request.duration- Latency histogram (p50, p95, p99)http.requests.active- In-flight requests
cache.hits/cache.misses- Cache efficiencyapi.calls.total- External API calls (Sleeper, Boris Chen, KTC)api.call.duration- API response timesleagues.analyzed- Business metricusers.active- Active users
Logs include trace IDs for correlation:
import "sleeperpy/goapp/logger"
logger.Info(ctx, "fetching user leagues",
slog.String("user_id", userID),
slog.Int("league_count", len(leagues)),
)import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
)
var tracer = otel.Tracer("sleeperpy")
func myFunction(ctx context.Context) error {
ctx, span := tracer.Start(ctx, "myFunction")
defer span.End()
span.SetAttributes(attribute.String("key", "value"))
// Your code here
return nil
}import "sleeperpy/goapp/otel"
otel.CacheHits.Add(ctx, 1,
metric.WithAttributes(attribute.String("cache", "user")))OTEL_EXPORTER_OTLP_ENDPOINT=your-collector:4317
ENVIRONMENT=production- Development: 100% of traces
- Production: 10% of traces (configured in otel/otel.go)
Instead of self-hosting, you can use:
- Honeycomb - Free tier: 20GB/month
- Grafana Cloud - Free tier: 10k series, 50GB logs
- New Relic - Free tier: 100GB/month
Simply point OTEL_EXPORTER_OTLP_ENDPOINT to their collector endpoint.
docker ps | grep otel-collectordocker logs <otel-collector-container-id>curl http://localhost:55679/debug/tracezcurl http://localhost:8889/metrics- Small VPS (2 CPU, 4GB RAM): $10-15/month
- Medium VPS (4 CPU, 8GB RAM): $20-30/month
- Runs all components with 30-day retention
- Honeycomb: $0-20/month for small apps
- Grafana Cloud: $0-10/month
- New Relic: $0-15/month
- Instrument key functions in fetch.go with spans
- Add HTTP middleware with otelhttp
- Create custom Grafana dashboards
- Set up alerts for error rates and latency