internal: skip tracing for go healthcheck and metrics endpoints

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2022-06-10 22:19:48 +02:00
parent 85784f796c
commit 59b899ddff
10 changed files with 55 additions and 10 deletions

View File

@ -85,8 +85,9 @@ def sentry_init(**sentry_init_kwargs):
def traces_sampler(sampling_context: dict) -> float: def traces_sampler(sampling_context: dict) -> float:
"""Custom sampler to ignore certain routes""" """Custom sampler to ignore certain routes"""
path = sampling_context.get("asgi_scope", {}).get("path", "")
# Ignore all healthcheck routes # Ignore all healthcheck routes
if sampling_context.get("asgi_scope", {}).get("path", "").startswith("/-/health/"): if path.startswith("/-/health") or path.startswith("/-/metrics"):
return 0 return 0
return float(CONFIG.y("error_reporting.sample_rate", 0.5)) return float(CONFIG.y("error_reporting.sample_rate", 0.5))

View File

@ -44,7 +44,7 @@ for _authentik_app in get_apps():
) )
urlpatterns += [ urlpatterns += [
path("metrics/", MetricsView.as_view(), name="metrics"), path("-/metrics/", MetricsView.as_view(), name="metrics"),
path("-/health/live/", LiveView.as_view(), name="health-live"), path("-/health/live/", LiveView.as_view(), name="health-live"),
path("-/health/ready/", ReadyView.as_view(), name="health-ready"), path("-/health/ready/", ReadyView.as_view(), name="health-ready"),
] ]

View File

@ -15,6 +15,7 @@ import (
"goauthentik.io/internal/gounicorn" "goauthentik.io/internal/gounicorn"
"goauthentik.io/internal/outpost/ak" "goauthentik.io/internal/outpost/ak"
"goauthentik.io/internal/outpost/proxyv2" "goauthentik.io/internal/outpost/proxyv2"
sentryutils "goauthentik.io/internal/utils/sentry"
"goauthentik.io/internal/web" "goauthentik.io/internal/web"
"goauthentik.io/internal/web/tenant_tls" "goauthentik.io/internal/web/tenant_tls"
) )
@ -51,7 +52,7 @@ func main() {
err := sentry.Init(sentry.ClientOptions{ err := sentry.Init(sentry.ClientOptions{
Dsn: config.G.ErrorReporting.DSN, Dsn: config.G.ErrorReporting.DSN,
AttachStacktrace: true, AttachStacktrace: true,
TracesSampleRate: config.G.ErrorReporting.SampleRate, TracesSampler: sentryutils.SamplerFunc(config.G.ErrorReporting.SampleRate),
Release: fmt.Sprintf("authentik@%s", constants.VERSION), Release: fmt.Sprintf("authentik@%s", constants.VERSION),
Environment: config.G.ErrorReporting.Environment, Environment: config.G.ErrorReporting.Environment,
IgnoreErrors: []string{ IgnoreErrors: []string{

View File

@ -11,6 +11,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"goauthentik.io/api/v3" "goauthentik.io/api/v3"
"goauthentik.io/internal/constants" "goauthentik.io/internal/constants"
sentryutils "goauthentik.io/internal/utils/sentry"
) )
var initialSetup = false var initialSetup = false
@ -47,10 +48,10 @@ func doGlobalSetup(outpost api.Outpost, globalConfig *api.Config) {
l.WithField("env", globalConfig.ErrorReporting.Environment).Debug("Error reporting enabled") l.WithField("env", globalConfig.ErrorReporting.Environment).Debug("Error reporting enabled")
} }
err := sentry.Init(sentry.ClientOptions{ err := sentry.Init(sentry.ClientOptions{
Dsn: dsn, Dsn: dsn,
Environment: globalConfig.ErrorReporting.Environment, Environment: globalConfig.ErrorReporting.Environment,
TracesSampleRate: float64(globalConfig.ErrorReporting.TracesSampleRate), TracesSampler: sentryutils.SamplerFunc(float64(globalConfig.ErrorReporting.TracesSampleRate)),
Release: fmt.Sprintf("authentik@%s", constants.VERSION), Release: fmt.Sprintf("authentik@%s", constants.VERSION),
IgnoreErrors: []string{ IgnoreErrors: []string{
http.ErrAbortHandler.Error(), http.ErrAbortHandler.Error(),
}, },

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"goauthentik.io/internal/utils/sentry"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
@ -25,6 +26,7 @@ var (
func RunServer() { func RunServer() {
m := mux.NewRouter() m := mux.NewRouter()
l := log.WithField("logger", "authentik.outpost.metrics") l := log.WithField("logger", "authentik.outpost.metrics")
m.Use(sentry.SentryNoSampleMiddleware)
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) { m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(204) rw.WriteHeader(204)
}) })

View File

@ -11,6 +11,7 @@ import (
"goauthentik.io/api/v3" "goauthentik.io/api/v3"
"goauthentik.io/internal/outpost/proxyv2/application" "goauthentik.io/internal/outpost/proxyv2/application"
"goauthentik.io/internal/outpost/proxyv2/metrics" "goauthentik.io/internal/outpost/proxyv2/metrics"
sentryutils "goauthentik.io/internal/utils/sentry"
"goauthentik.io/internal/utils/web" "goauthentik.io/internal/utils/web"
staticWeb "goauthentik.io/web" staticWeb "goauthentik.io/web"
) )
@ -89,7 +90,7 @@ func (ps *ProxyServer) Handle(rw http.ResponseWriter, r *http.Request) {
return return
} }
if strings.HasPrefix(r.URL.Path, "/outpost.goauthentik.io/ping") { if strings.HasPrefix(r.URL.Path, "/outpost.goauthentik.io/ping") {
ps.HandlePing(rw, r) sentryutils.SentryNoSample(ps.HandlePing)(rw, r)
return return
} }
a, host := ps.lookupApp(r) a, host := ps.lookupApp(r)

View File

@ -4,6 +4,7 @@ import (
"net/http" "net/http"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"goauthentik.io/internal/utils/sentry"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus"
@ -25,6 +26,7 @@ var (
func RunServer() { func RunServer() {
m := mux.NewRouter() m := mux.NewRouter()
l := log.WithField("logger", "authentik.outpost.metrics") l := log.WithField("logger", "authentik.outpost.metrics")
m.Use(sentry.SentryNoSampleMiddleware)
m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) { m.HandleFunc("/outpost.goauthentik.io/ping", func(rw http.ResponseWriter, r *http.Request) {
rw.WriteHeader(204) rw.WriteHeader(204)
}) })

View File

@ -18,6 +18,7 @@ import (
"goauthentik.io/internal/outpost/ak" "goauthentik.io/internal/outpost/ak"
"goauthentik.io/internal/outpost/proxyv2/application" "goauthentik.io/internal/outpost/proxyv2/application"
"goauthentik.io/internal/outpost/proxyv2/metrics" "goauthentik.io/internal/outpost/proxyv2/metrics"
sentryutils "goauthentik.io/internal/utils/sentry"
"goauthentik.io/internal/utils/web" "goauthentik.io/internal/utils/web"
) )
@ -65,7 +66,7 @@ func NewProxyServer(ac *ak.APIController, portOffset int) *ProxyServer {
defaultCert: defaultCert, defaultCert: defaultCert,
} }
globalMux.PathPrefix("/outpost.goauthentik.io/static").HandlerFunc(s.HandleStatic) globalMux.PathPrefix("/outpost.goauthentik.io/static").HandlerFunc(s.HandleStatic)
globalMux.Path("/outpost.goauthentik.io/ping").HandlerFunc(s.HandlePing) globalMux.Path("/outpost.goauthentik.io/ping").HandlerFunc(sentryutils.SentryNoSample(s.HandlePing))
rootMux.PathPrefix("/").HandlerFunc(s.Handle) rootMux.PathPrefix("/").HandlerFunc(s.Handle)
return s return s
} }

View File

@ -0,0 +1,34 @@
package sentry
import (
"context"
"net/http"
"github.com/getsentry/sentry-go"
)
type contextSentryNoSample struct{}
func SentryNoSample(handler func(rw http.ResponseWriter, r *http.Request)) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), contextSentryNoSample{}, true)
handler(w, r.WithContext(ctx))
}
}
func SentryNoSampleMiddleware(h http.Handler) http.Handler {
return http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
ctx := context.WithValue(r.Context(), contextSentryNoSample{}, true)
h.ServeHTTP(rw, r.WithContext(ctx))
})
}
func SamplerFunc(defaultRate float64) sentry.TracesSamplerFunc {
return sentry.TracesSamplerFunc(func(ctx sentry.SamplingContext) sentry.Sampled {
data, ok := ctx.Span.Context().Value(contextSentryNoSample{}).(bool)
if data && ok {
return sentry.SampledFalse
}
return sentry.UniformTracesSampler(defaultRate).Sample(ctx)
})
}

View File

@ -10,6 +10,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/client_golang/prometheus/promhttp"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"goauthentik.io/internal/config" "goauthentik.io/internal/config"
"goauthentik.io/internal/utils/sentry"
) )
var ( var (
@ -22,6 +23,7 @@ var (
func RunMetricsServer() { func RunMetricsServer() {
m := mux.NewRouter() m := mux.NewRouter()
l := log.WithField("logger", "authentik.router.metrics") l := log.WithField("logger", "authentik.router.metrics")
m.Use(sentry.SentryNoSampleMiddleware)
m.Path("/metrics").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { m.Path("/metrics").HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
promhttp.InstrumentMetricHandler( promhttp.InstrumentMetricHandler(
prometheus.DefaultRegisterer, promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{ prometheus.DefaultRegisterer, promhttp.HandlerFor(prometheus.DefaultGatherer, promhttp.HandlerOpts{
@ -30,7 +32,7 @@ func RunMetricsServer() {
).ServeHTTP(rw, r) ).ServeHTTP(rw, r)
// Get upstream metrics // Get upstream metrics
re, err := http.NewRequest("GET", "http://localhost:8000/metrics/", nil) re, err := http.NewRequest("GET", "http://localhost:8000/-/metrics/", nil)
if err != nil { if err != nil {
l.WithError(err).Warning("failed to get upstream metrics") l.WithError(err).Warning("failed to get upstream metrics")
return return