github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/server/index.go (about) 1 package server 2 3 import ( 4 "encoding/json" 5 "net/http" 6 "os" 7 8 "github.com/sirupsen/logrus" 9 10 "github.com/pyroscope-io/pyroscope/pkg/build" 11 "github.com/pyroscope-io/pyroscope/pkg/server/httputils" 12 "github.com/pyroscope-io/pyroscope/pkg/util/updates" 13 ) 14 15 type Flags struct { 16 EnableAdhocUI bool `json:"enableAdhocUI"` 17 GoogleEnabled bool `json:"googleEnabled"` 18 GitlabEnabled bool `json:"gitlabEnabled"` 19 GithubEnabled bool `json:"githubEnabled"` 20 InternalAuthEnabled bool `json:"internalAuthEnabled"` 21 SignupEnabled bool `json:"signupEnabled"` 22 ExportToFlamegraphDotComEnabled bool `json:"exportToFlamegraphDotComEnabled"` 23 IsAuthRequired bool `json:"isAuthRequired"` 24 ExemplarsPageEnabled bool `json:"exemplarsPageEnabled"` 25 } 26 27 type IndexHandlerConfig struct { 28 Flags Flags 29 BaseURL string 30 } 31 32 type IndexHandler struct { 33 log *logrus.Logger 34 dir http.FileSystem 35 fs http.Handler 36 stats StatsReceiver 37 notifier Notifier 38 cfg *IndexHandlerConfig 39 httpUtils httputils.Utils 40 } 41 42 func (ctrl *Controller) indexHandler() http.HandlerFunc { 43 cfg := &IndexHandlerConfig{ 44 Flags: Flags{ 45 EnableAdhocUI: !ctrl.config.NoAdhocUI, 46 GoogleEnabled: ctrl.config.Auth.Google.Enabled, 47 GitlabEnabled: ctrl.config.Auth.Gitlab.Enabled, 48 GithubEnabled: ctrl.config.Auth.Github.Enabled, 49 InternalAuthEnabled: ctrl.config.Auth.Internal.Enabled, 50 SignupEnabled: ctrl.config.Auth.Internal.SignupEnabled, 51 ExportToFlamegraphDotComEnabled: !ctrl.config.DisableExportToFlamegraphDotCom, 52 IsAuthRequired: ctrl.isAuthRequired(), 53 ExemplarsPageEnabled: ctrl.config.EnableExperimentalExemplarsPage, 54 }, 55 BaseURL: ctrl.config.BaseURL, 56 } 57 return NewIndexHandler(ctrl.log, ctrl.dir, ctrl, ctrl.notifier, cfg, ctrl.httpUtils).ServeHTTP 58 } 59 60 //revive:disable:argument-limit TODO(petethepig): we will refactor this later 61 func NewIndexHandler( 62 log *logrus.Logger, 63 dir http.FileSystem, 64 stats StatsReceiver, 65 notifier Notifier, 66 cfg *IndexHandlerConfig, 67 httpUtils httputils.Utils, 68 ) http.Handler { 69 fs := http.FileServer(dir) 70 return &IndexHandler{ 71 log: log, 72 dir: dir, 73 fs: fs, 74 stats: stats, 75 notifier: notifier, 76 cfg: cfg, 77 httpUtils: httpUtils, 78 } 79 } 80 81 func (ih *IndexHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 82 ih.stats.StatsInc("index") 83 ih.renderIndexPage(w, r) 84 } 85 86 func (ih *IndexHandler) renderIndexPage(w http.ResponseWriter, r *http.Request) { 87 tmpl, err := getTemplate(ih.dir, "/index.html") 88 if err != nil { 89 ih.httpUtils.WriteInternalServerError(r, w, err, "could not render index page") 90 return 91 } 92 93 var b []byte 94 if err != nil { 95 ih.httpUtils.WriteJSONEncodeError(r, w, err) 96 return 97 } 98 99 var extraMetadataStr string 100 extraMetadataPath := os.Getenv("PYROSCOPE_EXTRA_METADATA") 101 if extraMetadataPath != "" { 102 b, err = os.ReadFile(extraMetadataPath) 103 if err != nil { 104 logrus.Errorf("failed to read file at %s", extraMetadataPath) 105 } 106 extraMetadataStr = string(b) 107 } 108 109 // Feature Flags 110 // Add this intermediate layer instead of just exposing as it comes from ctrl.config 111 // Since we may probably want to rename these flags when exposing to the frontend 112 b, err = json.Marshal(ih.cfg.Flags) 113 if err != nil { 114 ih.httpUtils.WriteJSONEncodeError(r, w, err) 115 return 116 } 117 featuresStr := string(b) 118 119 w.Header().Add("Content-Type", "text/html") 120 mustExecute(tmpl, w, map[string]string{ 121 "BuildInfo": build.JSON(), 122 "LatestVersionInfo": updates.LatestVersionJSON(), 123 "ExtraMetadata": extraMetadataStr, 124 "BaseURL": ih.cfg.BaseURL, 125 "NotificationText": ih.notifier.NotificationText(), 126 "Features": featuresStr, 127 }) 128 }