mirror of
https://github.com/3ybactuk/marketplace-go-service-project.git
synced 2025-10-30 14:03:45 +03:00
[hw-7] add metrics, tracing
This commit is contained in:
52
cart/internal/infra/http/metrics/metrics.go
Normal file
52
cart/internal/infra/http/metrics/metrics.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
||||
var (
|
||||
requestCounter = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: "app",
|
||||
Name: "requests_total",
|
||||
Help: "Total amount of request by handler",
|
||||
}, []string{"method", "path", "status_code"})
|
||||
|
||||
requestDurationHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Namespace: "app",
|
||||
Name: "request_duration_seconds",
|
||||
Help: "Latency of handler processing, seconds",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
}, []string{"method", "path", "status_code"})
|
||||
|
||||
outboundCounter = promauto.NewCounterVec(prometheus.CounterOpts{
|
||||
Namespace: "app",
|
||||
Name: "outbound_requests_total",
|
||||
Help: "Total HTTP requests to external services",
|
||||
}, []string{"method", "url", "status_code"})
|
||||
|
||||
outboundDurationHistogram = promauto.NewHistogramVec(prometheus.HistogramOpts{
|
||||
Namespace: "app",
|
||||
Name: "outbound_request_duration_seconds",
|
||||
Help: "Latency of outbound HTTP requests, seconds",
|
||||
Buckets: prometheus.DefBuckets,
|
||||
}, []string{"method", "url", "status_code"})
|
||||
)
|
||||
|
||||
func IncRequestHandlerCount(method, path, statusCode string) {
|
||||
requestCounter.WithLabelValues(method, path, statusCode).Inc()
|
||||
}
|
||||
|
||||
func StoreHandlerRequestDuration(method, path, statusCode string, d time.Duration) {
|
||||
requestDurationHistogram.WithLabelValues(method, path, statusCode).Observe(d.Seconds())
|
||||
}
|
||||
|
||||
func IncOutboundRequestCount(method, url, status string) {
|
||||
outboundCounter.WithLabelValues(method, url, status).Inc()
|
||||
}
|
||||
|
||||
func StoreOutboundRequestDuration(method, url, status string, d time.Duration) {
|
||||
outboundDurationHistogram.WithLabelValues(method, url, status).Observe(d.Seconds())
|
||||
}
|
||||
16
cart/internal/infra/http/metrics/repository.go
Normal file
16
cart/internal/infra/http/metrics/repository.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package metrics
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promauto"
|
||||
)
|
||||
|
||||
var inMemoryObjectsGauge = promauto.NewGauge(prometheus.GaugeOpts{
|
||||
Namespace: "app",
|
||||
Name: "inmemory_repo_objects",
|
||||
Help: "Current in-memory repository size",
|
||||
})
|
||||
|
||||
func SetInMemoryObjects(n int) {
|
||||
inMemoryObjectsGauge.Set(float64(n))
|
||||
}
|
||||
38
cart/internal/infra/http/middlewares/metrics.go
Normal file
38
cart/internal/infra/http/middlewares/metrics.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"route256/cart/internal/infra/http/metrics"
|
||||
)
|
||||
|
||||
type statusWriter struct {
|
||||
http.ResponseWriter
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (w *statusWriter) WriteHeader(code int) {
|
||||
w.statusCode = code
|
||||
w.ResponseWriter.WriteHeader(code)
|
||||
}
|
||||
|
||||
func NewMetricsMiddleware(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
sw := &statusWriter{
|
||||
ResponseWriter: w,
|
||||
statusCode: http.StatusOK,
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
|
||||
h.ServeHTTP(sw, r)
|
||||
|
||||
path := r.URL.Path
|
||||
status := strconv.Itoa(sw.statusCode)
|
||||
|
||||
metrics.IncRequestHandlerCount(r.Method, path, status)
|
||||
metrics.StoreHandlerRequestDuration(r.Method, path, status, time.Since(start))
|
||||
})
|
||||
}
|
||||
17
cart/internal/infra/http/middlewares/tracing.go
Normal file
17
cart/internal/infra/http/middlewares/tracing.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"route256/cart/internal/infra/tracing"
|
||||
)
|
||||
|
||||
func NewTracingMiddleware(h http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx, span := tracing.Tracer().Start(r.Context(),
|
||||
r.Method+" "+r.URL.Path)
|
||||
defer span.End()
|
||||
|
||||
h.ServeHTTP(w, r.WithContext(ctx))
|
||||
})
|
||||
}
|
||||
37
cart/internal/infra/http/round_trippers/metrics.go
Normal file
37
cart/internal/infra/http/round_trippers/metrics.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package round_trippers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"route256/cart/internal/infra/http/metrics"
|
||||
)
|
||||
|
||||
type MetricsRoundTripper struct {
|
||||
rt http.RoundTripper
|
||||
}
|
||||
|
||||
func NewMetricsRoundTripper(rt http.RoundTripper) http.RoundTripper {
|
||||
return &MetricsRoundTripper{
|
||||
rt: rt,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MetricsRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
start := time.Now()
|
||||
resp, err := m.rt.RoundTrip(r)
|
||||
|
||||
status := "error"
|
||||
|
||||
if resp != nil {
|
||||
status = strconv.Itoa(resp.StatusCode)
|
||||
}
|
||||
|
||||
url := r.URL.Path
|
||||
|
||||
metrics.IncOutboundRequestCount(r.Method, url, status)
|
||||
metrics.StoreOutboundRequestDuration(r.Method, url, status, time.Since(start))
|
||||
|
||||
return resp, err
|
||||
}
|
||||
Reference in New Issue
Block a user