mirror of
https://github.com/sourcegraph/sourcegraph.git
synced 2026-02-06 16:51:55 +00:00
repo-updater: allow filter debug dumper by name (#37915)
This commit is contained in:
parent
5c0a6c5600
commit
67f2ce8349
@ -13,7 +13,6 @@ import (
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/golang/gddo/httputil"
|
||||
"github.com/graph-gophers/graphql-go/relay"
|
||||
"github.com/opentracing/opentracing-go"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@ -59,7 +58,7 @@ var stateHTMLTemplate string
|
||||
|
||||
// EnterpriseInit is a function that allows enterprise code to be triggered when dependencies
|
||||
// created in Main are ready for use.
|
||||
type EnterpriseInit func(logger log.Logger, db database.DB, store repos.Store, keyring keyring.Ring, cf *httpcli.Factory, server *repoupdater.Server) []debugserver.Dumper
|
||||
type EnterpriseInit func(logger log.Logger, db database.DB, store repos.Store, keyring keyring.Ring, cf *httpcli.Factory, server *repoupdater.Server) map[string]debugserver.Dumper
|
||||
|
||||
type LazyDebugserverEndpoint struct {
|
||||
repoUpdaterStateEndpoint http.HandlerFunc
|
||||
@ -159,7 +158,7 @@ func Main(enterpriseInit EnterpriseInit) {
|
||||
}
|
||||
|
||||
// All dependencies ready
|
||||
var debugDumpers []debugserver.Dumper
|
||||
debugDumpers := make(map[string]debugserver.Dumper)
|
||||
if enterpriseInit != nil {
|
||||
debugDumpers = enterpriseInit(logger, db, store, keyring.Default(), cf, server)
|
||||
}
|
||||
@ -230,7 +229,8 @@ func Main(enterpriseInit EnterpriseInit) {
|
||||
|
||||
globals.WatchExternalURL(nil)
|
||||
|
||||
debugserverEndpoints.repoUpdaterStateEndpoint = repoUpdaterStatsHandler(db, updateScheduler, debugDumpers)
|
||||
debugDumpers["repos"] = updateScheduler
|
||||
debugserverEndpoints.repoUpdaterStateEndpoint = repoUpdaterStatsHandler(db, debugDumpers)
|
||||
debugserverEndpoints.listAuthzProvidersEndpoint = listAuthzProvidersHandler()
|
||||
debugserverEndpoints.gitserverReposStatusEndpoint = gitserverReposStatusHandler(db)
|
||||
debugserverEndpoints.rateLimiterStateEndpoint = rateLimiterStateHandler
|
||||
@ -413,44 +413,20 @@ func listAuthzProvidersHandler() http.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func repoUpdaterStatsHandler(db database.DB, scheduler *repos.UpdateScheduler, debugDumpers []debugserver.Dumper) http.HandlerFunc {
|
||||
func repoUpdaterStatsHandler(db database.DB, debugDumpers map[string]debugserver.Dumper) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
dumps := []any{
|
||||
scheduler.DebugDump(r.Context(), db),
|
||||
}
|
||||
for _, dumper := range debugDumpers {
|
||||
dumps = append(dumps, dumper.DebugDump())
|
||||
}
|
||||
wantDumper := r.URL.Query().Get("dumper")
|
||||
wantFormat := r.URL.Query().Get("format")
|
||||
|
||||
const (
|
||||
textPlain = "text/plain"
|
||||
applicationJson = "application/json"
|
||||
)
|
||||
|
||||
// Negotiate the content type.
|
||||
contentTypeOffers := []string{textPlain, applicationJson}
|
||||
defaultOffer := textPlain
|
||||
contentType := httputil.NegotiateContentType(r, contentTypeOffers, defaultOffer)
|
||||
|
||||
// Allow users to override the negotiated content type so that e.g. browser
|
||||
// users can easily request json by adding ?format=json to
|
||||
// the URL.
|
||||
switch r.URL.Query().Get("format") {
|
||||
case "json":
|
||||
contentType = applicationJson
|
||||
}
|
||||
|
||||
switch contentType {
|
||||
case applicationJson:
|
||||
p, err := json.MarshalIndent(dumps, "", " ")
|
||||
if err != nil {
|
||||
http.Error(w, "failed to marshal snapshot: "+err.Error(), http.StatusInternalServerError)
|
||||
// Showing the HTML version of repository syncing schedule as the default,
|
||||
// also the only dumper that supports rendering the HTML version.
|
||||
if (wantDumper == "" || wantDumper == "repos") && wantFormat != "json" {
|
||||
reposDumper, ok := debugDumpers["repos"].(*repos.UpdateScheduler)
|
||||
if !ok {
|
||||
http.Error(w, "No debug dumper for repos found", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write(p)
|
||||
|
||||
default:
|
||||
// This case also applies for defaultOffer. Note that this is preferred
|
||||
// over e.g. a 406 status code, according to the MDN:
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/406
|
||||
@ -460,12 +436,29 @@ func repoUpdaterStatsHandler(db database.DB, scheduler *repos.UpdateScheduler, d
|
||||
},
|
||||
})
|
||||
template.Must(tmpl.Parse(stateHTMLTemplate))
|
||||
err := tmpl.Execute(w, dumps)
|
||||
err := tmpl.Execute(w, reposDumper.DebugDump(r.Context(), db.ExternalServices()))
|
||||
if err != nil {
|
||||
http.Error(w, "failed to render template: "+err.Error(), http.StatusInternalServerError)
|
||||
http.Error(w, "Failed to render template: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var dumps []any
|
||||
for name, dumper := range debugDumpers {
|
||||
if wantDumper != "" && wantDumper != name {
|
||||
continue
|
||||
}
|
||||
dumps = append(dumps, dumper.DebugDump(r.Context(), db.ExternalServices()))
|
||||
}
|
||||
|
||||
p, err := json.MarshalIndent(dumps, "", " ")
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to marshal dumps: "+err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write(p)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -14,13 +14,11 @@
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
{{$schedulerDump := index . 0}}
|
||||
{{if gt (len .) 1}}
|
||||
<div class="alert alert-info mt-5 mx-auto text-center" onclick="loadJSON()" role="button">
|
||||
To view additional debug dumps, please request a JSON response
|
||||
<i class="fas fa-link ml-2"></i>
|
||||
</div>
|
||||
{{end}}
|
||||
{{$schedulerDump := .}}
|
||||
<div class="alert alert-info mt-5 mx-auto text-center" onclick="loadJSON()" role="button">
|
||||
To view additional debug dumps, please request a JSON response.
|
||||
<i class="fas fa-link ml-2"></i>
|
||||
</div>
|
||||
|
||||
<div class="mt-5 w-9/12" id="Index">
|
||||
<li><a href="#Schedule">Schedule</a></li>
|
||||
|
||||
@ -24,6 +24,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/authz"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/debugserver"
|
||||
"github.com/sourcegraph/sourcegraph/internal/errcode"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc"
|
||||
"github.com/sourcegraph/sourcegraph/internal/extsvc/github"
|
||||
@ -1323,7 +1324,7 @@ func (s *PermsSyncer) runSchedule(ctx context.Context) {
|
||||
}
|
||||
|
||||
// DebugDump returns the state of the permissions syncer for debugging.
|
||||
func (s *PermsSyncer) DebugDump() any {
|
||||
func (s *PermsSyncer) DebugDump(_ context.Context, _ debugserver.ExternalServicesStore) any {
|
||||
type requestInfo struct {
|
||||
Meta *requestMeta
|
||||
Acquired bool
|
||||
|
||||
@ -39,7 +39,7 @@ func enterpriseInit(
|
||||
keyring keyring.Ring,
|
||||
cf *httpcli.Factory,
|
||||
server *repoupdater.Server,
|
||||
) (debugDumpers []debugserver.Dumper) {
|
||||
) (debugDumpers map[string]debugserver.Dumper) {
|
||||
debug, _ := strconv.ParseBool(os.Getenv("DEBUG"))
|
||||
if debug {
|
||||
logger.Info("enterprise edition")
|
||||
@ -60,12 +60,13 @@ func enterpriseInit(
|
||||
permsStore := edb.Perms(logger, db, timeutil.Now)
|
||||
permsSyncer := authz.NewPermsSyncer(logger.Scoped("PermsSyncer", "repository and user permissions syncer"), db, repoStore, permsStore, timeutil.Now, ratelimit.DefaultRegistry)
|
||||
go startBackgroundPermsSync(ctx, permsSyncer, db)
|
||||
debugDumpers = append(debugDumpers, permsSyncer)
|
||||
if server != nil {
|
||||
server.PermsSyncer = permsSyncer
|
||||
}
|
||||
|
||||
return debugDumpers
|
||||
return map[string]debugserver.Dumper{
|
||||
"repoPerms": permsSyncer,
|
||||
}
|
||||
}
|
||||
|
||||
// startBackgroundPermsSync sets up background permissions syncing.
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package debugserver
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -17,6 +18,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/env"
|
||||
"github.com/sourcegraph/sourcegraph/internal/goroutine"
|
||||
"github.com/sourcegraph/sourcegraph/internal/httpserver"
|
||||
"github.com/sourcegraph/sourcegraph/internal/types"
|
||||
)
|
||||
|
||||
var addr = env.Get("SRC_PROF_HTTP", ":6060", "net/http/pprof http bind address.")
|
||||
@ -70,10 +72,14 @@ type Service struct {
|
||||
DefaultPath string
|
||||
}
|
||||
|
||||
type ExternalServicesStore interface {
|
||||
GetSyncJobs(ctx context.Context) ([]*types.ExternalServiceSyncJob, error)
|
||||
}
|
||||
|
||||
// Dumper is a service which can dump its state for debugging.
|
||||
type Dumper interface {
|
||||
// DebugDump returns a snapshot of the current state.
|
||||
DebugDump() any
|
||||
DebugDump(ctx context.Context, esStore ExternalServicesStore) any
|
||||
}
|
||||
|
||||
// NewServerRoutine returns a background routine that exposes pprof and metrics endpoints.
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
"github.com/sourcegraph/sourcegraph/internal/api"
|
||||
"github.com/sourcegraph/sourcegraph/internal/conf"
|
||||
"github.com/sourcegraph/sourcegraph/internal/database"
|
||||
"github.com/sourcegraph/sourcegraph/internal/debugserver"
|
||||
"github.com/sourcegraph/sourcegraph/internal/gitserver"
|
||||
gitserverprotocol "github.com/sourcegraph/sourcegraph/internal/gitserver/protocol"
|
||||
"github.com/sourcegraph/sourcegraph/internal/mutablelimiter"
|
||||
@ -397,7 +398,7 @@ func (s *UpdateScheduler) UpdateOnce(id api.RepoID, name api.RepoName) {
|
||||
}
|
||||
|
||||
// DebugDump returns the state of the update scheduler for debugging.
|
||||
func (s *UpdateScheduler) DebugDump(ctx context.Context, db database.DB) any {
|
||||
func (s *UpdateScheduler) DebugDump(ctx context.Context, esStore debugserver.ExternalServicesStore) any {
|
||||
data := struct {
|
||||
Name string
|
||||
UpdateQueue []*repoUpdate
|
||||
@ -446,7 +447,7 @@ func (s *UpdateScheduler) DebugDump(ctx context.Context, db database.DB) any {
|
||||
}
|
||||
|
||||
var err error
|
||||
data.SyncJobs, err = db.ExternalServices().GetSyncJobs(ctx)
|
||||
data.SyncJobs, err = esStore.GetSyncJobs(ctx)
|
||||
if err != nil {
|
||||
s.logger.Warn("getting external service sync jobs for debug page", log.Error(err))
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user