Skip to content

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

5 Commits

Folders and files

Repository files navigation

caching-fire-go

A minimal, production-ready Go HTTP service with OpenTelemetry traces, metrics, and logs wired up out of the box. Clone it, rename the module, add your business logic.

What's inside

caching-fire-go/
├── cmd/server/main.go              # Entry point — wires everything together
├── internal/
│   ├── config/config.go            # Env-based config with defaults
│   ├── observability/
│   │   ├── setup.go                # Single Setup() call returns one shutdown func
│   │   ├── tracer.go               # OTLP gRPC trace exporter + propagator
│   │   ├── meter.go                # OTLP gRPC metric exporter (periodic reader)
│   │   └── logger.go               # slog → stdout (JSON) AND OTel collector
│   └── handler/
│       └── example.go              # Example GET /example handler — replace with your logic
├── deploy/
│   ├── docker-compose.yml          # app + otel-collector
│   └── otel-collector.yaml         # collector config: OTLP in, debug + prometheus out
├── Dockerfile
└── .env.example

Observability stack

Signal How Where it lands
Traces otelgin middleware + manual spans OTel collector → debug log
Metrics otel.Meter counters + histograms OTel collector → Prometheus
Logs slog with multiHandler stdout (JSON) + OTel collector

Logs go to both stdout and the OTel collector simultaneously. Pod logs and the collector both have the full log stream.

Endpoints

Endpoint Description
GET /example Example handler with trace, metric, and log
GET /healthz Returns {"status": "ok"}

Getting started

1. Rename the module

# Replace with your own module path
find . -type f -name "*.go" | xargs sed -i 's|github.com/your-org/caching-fire-go|github.com/you/your-service|g'
sed -i 's|github.com/your-org/caching-fire-go|github.com/you/your-service|g' go.mod

2. Run locally with Docker Compose

cd deploy
docker compose up

3. Run locally without Docker

# Requires an OTLP collector on localhost:4317
cp .env.example .env
go mod tidy
go run ./cmd/server

4. Hit the service

curl localhost:8080/example
curl localhost:8080/healthz

Cache demo on Kubernetes (kind + Valkey operator)

This repo ships a full local Kubernetes test: a Valkey cluster managed by the Valkey operator, the Go app pointed at it via /hit and /fetch, and a k6 Job driving the /hit → wait 5s → /fetch pattern from inside the cluster. Everything is wrapped in make targets and runs on kind.

Cache endpoints under test:

Endpoint Description
POST /hit Generates a 2 KB payload, stores it in Valkey under a fresh key (TTL 10s), returns the key
GET /fetch?key= 200 if the key is still cached, 404 once its TTL has elapsed

Prerequisites

  • docker, kind, kubectl, helm

  • A Helm repo named valkey added locally — this is where the operator and cluster charts are pulled from. The Makefile runs helm install … valkey/valkey-operator and valkey/valkey-resources verbatim:

    helm repo add valkey <your-valkey-charts-repo-url>
    helm repo update

Run the whole thing

From the repo root:

make kind-all

This creates the kind cluster and then runs, in order:

  1. valkey-operator — helm install valkey-operator valkey/valkey-operator -n valkey-operator-system --create-namespace
  2. valkey-cluster — helm install my-cluster valkey/valkey-resources -n valkey --create-namespace, then waits for the ValkeyCluster pods to be Ready
  3. kind-image — builds the app image and side-loads it into the cluster (kind load)
  4. deploy-app — helm upgrade --install the app chart with values-kind.yaml into ns/caching-fire
  5. k6-job — runs the k6 load Job in-cluster and tails its results

Each step is also a standalone target — run make help to list them, or step through them one at a time.

How the app finds Valkey

The operator names the Valkey Service after the release, not my-cluster. For the my-cluster release in ns/valkey it creates a headless Service (CLUSTER-IP: None) named valkey-my-cluster-valkey-resources, so the app is configured with:

VALKEY_ADDR=valkey-my-cluster-valkey-resources.valkey.svc.cluster.local:6379

(set in deploy/helm/caching-fire-go/values-kind.yaml). If your release or namespace differs, confirm the name with make valkey-svc and update that one line — the app fail-fasts on a bad address, so pods CrashLoopBackOff rather than start.

Re-run the load test / teardown

make k6-job        # re-run k6 against the running app
make app-forward   # forward svc/caching-fire-go -> localhost:8080 to curl by hand
make kind-down     # delete the whole kind cluster

Full walkthrough, architecture diagram, and troubleshooting live in deploy/kind/README.md.

Environment variables

Variable Default Description
HTTP_ADDR :8080 Address the HTTP server listens on
OTEL_EXPORTER_OTLP_ENDPOINT localhost:4317 gRPC endpoint of the OTel collector
OTEL_SERVICE_NAME caching-fire-go Service name in all OTel signals
LOG_LEVEL info Minimum log level for stdout
VALKEY_ADDR localhost:6379 Address of the Valkey cache
CACHE_TTL_SECONDS 10 TTL for /hit payloads

Adding your own handler

  1. Create internal/handler/yourhandler.go following the pattern in example.go:
    • Pull ctx from c.Request.Context() and pass it to every downstream call
    • Start child spans with otel.Tracer(...).Start(ctx, "span.name")
    • Record metrics via otel.Meter(...)
    • Log with slog.InfoContext(ctx, ...) — trace IDs are correlated automatically
  2. Register the route in cmd/server/main.go

Shutdown

The service handles SIGINT/SIGTERM gracefully:

  1. HTTP server drains in-flight requests (10 s timeout)
  2. OTel providers flush buffered traces, metrics, and logs before exit

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages