# switchbot-api service Gin-based Go service with clean-ish layering, OpenTelemetry tracing (OTLP gRPC), Prometheus metrics, structured JSON logging, and graceful shutdown. ## Project structure ```text cmd/server/main.go internal/app/bootstrap internal/app/config internal/app/observability internal/domain/hello internal/domain/health internal/transport/http ``` ## Endpoints - `GET /healthz` -> `200 {"status":"ok"}` - `GET /readyz` -> `200 {"status":"ok"}` - `GET /hello` -> `200 {"message":"hello world"}` - `GET /metrics` -> Prometheus metrics ## Configuration (environment variables) - `PORT` (default: `8080`) - `SERVICE_NAME` (default: `switchbot-api`) - `ENV` (default: `local`) - `LOG_LEVEL` (default: `info`) - `OTEL_EXPORTER_OTLP_ENDPOINT` (default: empty; tracing export disabled) ### OTEL example env vars ```bash export SERVICE_NAME=switchbot-api export ENV=local export OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317 ``` ## Run locally (without collector) Tracing export is disabled by default when `OTEL_EXPORTER_OTLP_ENDPOINT` is not set. ```bash go mod tidy go run ./cmd/server ``` ## Run with OpenTelemetry Collector (Docker Compose) ```bash docker compose up --build ``` The collector prints received spans to stdout via the `logging` exporter. ## Example requests ```bash curl -i http://localhost:8080/healthz curl -i http://localhost:8080/readyz curl -i http://localhost:8080/hello curl -s http://localhost:8080/metrics | head ``` ## Notes - Request ID is propagated using `X-Request-Id` (generated if missing). - Request logs include `request_id`, `trace_id`, and `span_id`. - Error responses include `trace_id` and `request_id` when available. - `/readyz` already has a usecase and checker abstraction with a TODO for future dependency checks. - Optional tracing backend (Jaeger/Tempo) is not required for this setup. ## Verify ```bash go test ./... go vet ./... ```