github.com/grafana/pyroscope@v1.18.0/pkg/api/index.go (about)

     1  // SPDX-License-Identifier: AGPL-3.0-only
     2  // Provenance-includes-location: https://github.com/cortexproject/cortex/blob/master/pkg/api/handlers.go
     3  // Provenance-includes-license: Apache-2.0
     4  // Provenance-includes-copyright: The Cortex Authors.
     5  
     6  package api
     7  
     8  import (
     9  	"embed"
    10  	"html/template"
    11  	"net/http"
    12  	"path"
    13  	"sort"
    14  	"sync"
    15  
    16  	httputil "github.com/grafana/pyroscope/pkg/util/http"
    17  )
    18  
    19  // List of weights to order link groups in the same order as weights are ordered here.
    20  const (
    21  	serviceStatusWeight = iota
    22  	configWeight
    23  	runtimeConfigWeight
    24  	defaultWeight
    25  	memberlistWeight
    26  	dangerousWeight
    27  	openAPIDefinitionWeight
    28  	buildInfoWeight
    29  )
    30  
    31  func NewIndexPageContent() *IndexPageContent {
    32  	return &IndexPageContent{}
    33  }
    34  
    35  // IndexPageContent is a map of sections to path -> description.
    36  type IndexPageContent struct {
    37  	mu sync.Mutex
    38  
    39  	elements []IndexPageLinkGroup
    40  }
    41  
    42  type IndexPageLinkGroup struct {
    43  	weight int
    44  	Desc   string
    45  	Links  []IndexPageLink
    46  }
    47  
    48  type IndexPageLink struct {
    49  	Desc      string
    50  	Path      string
    51  	Dangerous bool
    52  }
    53  
    54  func (pc *IndexPageContent) AddLinks(weight int, groupDesc string, links []IndexPageLink) {
    55  	pc.mu.Lock()
    56  	defer pc.mu.Unlock()
    57  
    58  	pc.elements = append(pc.elements, IndexPageLinkGroup{weight: weight, Desc: groupDesc, Links: links})
    59  }
    60  
    61  func (pc *IndexPageContent) GetContent() []IndexPageLinkGroup {
    62  	pc.mu.Lock()
    63  	els := append([]IndexPageLinkGroup(nil), pc.elements...)
    64  	pc.mu.Unlock()
    65  
    66  	sort.Slice(els, func(i, j int) bool {
    67  		if els[i].weight != els[j].weight {
    68  			return els[i].weight < els[j].weight
    69  		}
    70  		return els[i].Desc < els[j].Desc
    71  	})
    72  
    73  	return els
    74  }
    75  
    76  //go:embed index.gohtml
    77  var indexPageHTML string
    78  
    79  type indexPageContents struct {
    80  	LinkGroups []IndexPageLinkGroup
    81  }
    82  
    83  //go:embed static
    84  var staticFiles embed.FS
    85  
    86  func indexHandler(httpPathPrefix string, content *IndexPageContent) http.HandlerFunc {
    87  	templ := template.New("main")
    88  	templ.Funcs(map[string]interface{}{
    89  		"AddPathPrefix": func(link string) string {
    90  			return path.Join(httpPathPrefix, link)
    91  		},
    92  	})
    93  	template.Must(templ.Parse(indexPageHTML))
    94  
    95  	return func(w http.ResponseWriter, r *http.Request) {
    96  		err := templ.Execute(w, indexPageContents{LinkGroups: content.GetContent()})
    97  		if err != nil {
    98  			httputil.Error(w, err)
    99  		}
   100  	}
   101  }