diff --git a/internal/proxy/director/director.go b/internal/proxy/director/director.go index 4d74625..ad45655 100644 --- a/internal/proxy/director/director.go +++ b/internal/proxy/director/director.go @@ -4,6 +4,7 @@ import ( "context" "net/http" "sort" + "time" "forge.cadoles.com/Cadoles/go-proxy" "forge.cadoles.com/Cadoles/go-proxy/wildcard" @@ -28,12 +29,12 @@ type Director struct { const proxiesCacheKey = "proxies" -func (d *Director) rewriteRequest(r *http.Request) (*http.Request, error) { +func (d *Director) rewriteRequest(r *http.Request) (*http.Request, []store.ProxyName, error) { ctx := r.Context() proxies, _, err := d.cachedProxies.Get(ctx, proxiesCacheKey) if err != nil { - return r, errors.WithStack(err) + return r, nil, errors.WithStack(err) } url := getRequestURL(r) @@ -42,12 +43,16 @@ func (d *Director) rewriteRequest(r *http.Request) (*http.Request, error) { layers := make([]*store.Layer, 0) + matchingProxies := make([]store.ProxyName, 0) + for _, p := range proxies { for _, from := range p.From { if matches := wildcard.Match(url.String(), from); !matches { continue } + matchingProxies = append(matchingProxies, p.Name) + proxyCtx := logger.With(ctx, logger.F("proxy", p.Name), logger.F("host", r.Host), @@ -58,7 +63,7 @@ func (d *Director) rewriteRequest(r *http.Request) (*http.Request, error) { proxyLayers, _, err := d.cachedLayers.Get(proxyCtx, string(p.Name)) if err != nil { - return r, errors.WithStack(err) + return r, nil, errors.WithStack(err) } layers = append(layers, proxyLayers...) @@ -69,7 +74,7 @@ func (d *Director) rewriteRequest(r *http.Request) (*http.Request, error) { toURL, err := url.Parse(p.To) if err != nil { - return r, errors.WithStack(err) + return r, nil, errors.WithStack(err) } r.URL.Host = toURL.Host @@ -87,14 +92,14 @@ func (d *Director) rewriteRequest(r *http.Request) (*http.Request, error) { }) } - return r, nil + return r, matchingProxies, nil } } ctx = withLayers(ctx, layers) r = r.WithContext(ctx) - return r, nil + return r, matchingProxies, nil } func (d *Director) getProxies(ctx context.Context, key string) ([]*store.Proxy, error) { @@ -215,17 +220,26 @@ func (d *Director) ResponseTransformer() proxy.ResponseTransformer { func (d *Director) Middleware() proxy.Middleware { return func(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + sentry.ConfigureScope(func(scope *sentry.Scope) { ctx := withHandleError(r.Context(), d.handleError) ctx = withSentryScope(ctx, scope) r = r.WithContext(ctx) - r, err := d.rewriteRequest(r) + r, matched, err := d.rewriteRequest(r) if err != nil { HandleError(ctx, w, r, http.StatusInternalServerError, errors.Wrap(err, "could not rewrite request")) return } + defer func() { + elapsed := time.Since(start) + for _, p := range matched { + metricProxyResponsesDurationSeconds.WithLabelValues(string(p)).Observe(elapsed.Seconds()) + } + }() + ctx = r.Context() layers, err := ctxLayers(ctx) diff --git a/internal/proxy/director/metrics.go b/internal/proxy/director/metrics.go index 025124a..bc32c6b 100644 --- a/internal/proxy/director/metrics.go +++ b/internal/proxy/director/metrics.go @@ -18,3 +18,12 @@ var metricProxyRequestsTotal = promauto.NewCounterVec( }, []string{metricLabelProxy}, ) + +var metricProxyResponsesDurationSeconds = promauto.NewHistogramVec( + prometheus.HistogramOpts{ + Name: "proxy_responses_duration_seconds", + Help: "Bouncer proxy responses duration", + Namespace: metricNamespace, + }, + []string{metricLabelProxy}, +)