* docs: add specification for production readiness & website launch Covers DevOps hooks, CI/CD, Prometheus observability, Docker/Helm deployment, and synapbus.dev website with documentation and blog. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs: add implementation plan and research for production readiness Covers 5 workstreams: git hooks, CI/CD, observability, deployment artifacts, and website. All constitution gates pass. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add pre-commit and pre-push git hooks Pre-commit runs go vet, golangci-lint (optional), and fast tests. Pre-push runs full test suite and build verification. Installable via `make hooks`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * ci: add GitHub Actions for PR checks and releases ci.yml: lint, test, build on PRs to main. release.yml: multi-platform binaries + Docker image on version tags. Targets: linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64. Docker pushed to ghcr.io/smart-mcp-proxy/synapbus. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Dockerfile, docker-compose, and Helm chart Multi-stage Docker build (node + golang + scratch), ~30MB image. docker-compose.yml for local development with volume persistence. Helm chart with configurable Deployment, Service, PVC, Ingress, and Prometheus ServiceMonitor. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Prometheus metrics and Kubernetes health endpoints Add internal/metrics package with Prometheus collectors (HTTP requests, duration, messages, agents, connections) and chi-compatible middleware. Add internal/health package with /healthz (liveness) and /readyz (readiness with DB ping) endpoints. Wire into main.go with promhttp handler at /metrics. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update Go version to 1.25, fix Docker build issues - Update Dockerfile golang image from 1.23 to 1.25 (matches go.mod) - Add tzdata package for timezone support in scratch image - Use npm install --legacy-peer-deps for web frontend build - Update CI/release workflows to use Go 1.25 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve CI failures - golangci-lint v2 and npm peer deps - Upgrade golangci-lint-action to v7 with v2.1 (supports Go 1.25) - Use npm install --legacy-peer-deps instead of npm ci for web builds Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: replace golangci-lint with go vet (golangci-lint doesn't support Go 1.25 yet) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
55 lines
1.3 KiB
Go
55 lines
1.3 KiB
Go
package metrics
|
|
|
|
import (
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// responseWriter wraps http.ResponseWriter to capture the status code.
|
|
type responseWriter struct {
|
|
http.ResponseWriter
|
|
statusCode int
|
|
written bool
|
|
}
|
|
|
|
func newResponseWriter(w http.ResponseWriter) *responseWriter {
|
|
return &responseWriter{ResponseWriter: w, statusCode: http.StatusOK}
|
|
}
|
|
|
|
func (rw *responseWriter) WriteHeader(code int) {
|
|
if !rw.written {
|
|
rw.statusCode = code
|
|
rw.written = true
|
|
}
|
|
rw.ResponseWriter.WriteHeader(code)
|
|
}
|
|
|
|
func (rw *responseWriter) Write(b []byte) (int, error) {
|
|
if !rw.written {
|
|
rw.written = true
|
|
}
|
|
return rw.ResponseWriter.Write(b)
|
|
}
|
|
|
|
// Unwrap returns the underlying ResponseWriter, supporting http.Flusher etc.
|
|
func (rw *responseWriter) Unwrap() http.ResponseWriter {
|
|
return rw.ResponseWriter
|
|
}
|
|
|
|
// Middleware records HTTP request count and duration for every request.
|
|
func Middleware(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
start := time.Now()
|
|
wrapped := newResponseWriter(w)
|
|
|
|
next.ServeHTTP(wrapped, r)
|
|
|
|
duration := time.Since(start).Seconds()
|
|
status := strconv.Itoa(wrapped.statusCode)
|
|
|
|
HTTPRequestsTotal.WithLabelValues(r.Method, r.URL.Path, status).Inc()
|
|
HTTPRequestDuration.WithLabelValues(r.Method, r.URL.Path).Observe(duration)
|
|
})
|
|
}
|