Skip to content

Commit b792f4b

Browse files
committed
feat: expose DERP server debug metrics
1 parent 53c5543 commit b792f4b

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

coderd/coderd.go

+17
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"crypto/tls"
66
"crypto/x509"
77
"database/sql"
8+
"expvar"
89
"flag"
910
"fmt"
1011
"io"
@@ -85,6 +86,8 @@ func init() {
8586
globalHTTPSwaggerHandler = httpSwagger.Handler(httpSwagger.URL("/swagger/doc.json"))
8687
}
8788

89+
var expDERPOnce = sync.Once{}
90+
8891
// Options are requires parameters for Coder to start.
8992
type Options struct {
9093
AccessURL *url.URL
@@ -561,6 +564,16 @@ func New(options *Options) *API {
561564

562565
derpHandler := derphttp.Handler(api.DERPServer)
563566
derpHandler, api.derpCloseFunc = tailnet.WithWebsocketSupport(api.DERPServer, derpHandler)
567+
// Register DERP on expvar HTTP handler, which we serve below in the router, c.f. expvar.Handler()
568+
// These are the metrics the DERP server exposes.
569+
// TODO: export via prometheus
570+
expDERPOnce.Do(func() {
571+
// We need to do this via a global Once because expvar registry is global and panics if we
572+
// register multiple times. In production there is only one Coderd and one DERP server per
573+
// process, but in testing, we create multiple of both, so the Once protects us from
574+
// panicking.
575+
expvar.Publish("derp", api.DERPServer.ExpVar())
576+
})
564577
cors := httpmw.Cors(options.DeploymentValues.Dangerous.AllowAllCors.Value())
565578
prometheusMW := httpmw.Prometheus(options.PrometheusRegistry)
566579

@@ -1038,6 +1051,10 @@ func New(options *Options) *API {
10381051
r.Use(httpmw.ExtractUserParam(options.Database))
10391052
r.Get("/debug-link", api.userDebugOIDC)
10401053
})
1054+
r.Route("/derp", func(r chi.Router) {
1055+
r.Get("/traffic", options.DERPServer.ServeDebugTraffic)
1056+
})
1057+
r.Mount("/expvar", expvar.Handler()) // contains DERP metrics as well as cmdline and memstats
10411058
})
10421059
})
10431060

coderd/debug.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ func validateHealthSettings(settings codersdk.HealthSettings) error {
276276
}
277277

278278
// For some reason the swagger docs need to be attached to a function.
279-
//
279+
280280
// @Summary Debug Info Websocket Test
281281
// @ID debug-info-websocket-test
282282
// @Security CoderSessionToken
@@ -287,6 +287,24 @@ func validateHealthSettings(settings codersdk.HealthSettings) error {
287287
// @x-apidocgen {"skip": true}
288288
func _debugws(http.ResponseWriter, *http.Request) {} //nolint:unused
289289

290+
// @Summary Debug DERP traffic
291+
// @ID debug-derp-traffic
292+
// @Security CoderSessionToken
293+
// @Produce json
294+
// @Tags Debug
295+
// @Router /debug/derp/traffic [get]
296+
// @x-apidocgen {"skip": true}
297+
func _debugDERPTraffic(http.ResponseWriter, *http.Request) {} //nolint:unused
298+
299+
// @Summary Debug expvar
300+
// @ID debug-expvar
301+
// @Security CoderSessionToken
302+
// @Produce json
303+
// @Tags Debug
304+
// @Router /debug/expvar [get]
305+
// @x-apidocgen {"skip": true}
306+
func _debugExpVar(http.ResponseWriter, *http.Request) {} //nolint:unused
307+
290308
func loadDismissedHealthchecks(ctx context.Context, db database.Store, logger slog.Logger) []codersdk.HealthSection {
291309
dismissedHealthchecks := []codersdk.HealthSection{}
292310
settingsJSON, err := db.GetHealthSettings(ctx)

0 commit comments

Comments
 (0)