Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / event / export / prometheus / prometheus.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package prometheus
6
7 import (
8         "bytes"
9         "context"
10         "fmt"
11         "net/http"
12         "sort"
13         "sync"
14
15         "golang.org/x/tools/internal/event"
16         "golang.org/x/tools/internal/event/core"
17         "golang.org/x/tools/internal/event/export/metric"
18         "golang.org/x/tools/internal/event/label"
19 )
20
21 func New() *Exporter {
22         return &Exporter{}
23 }
24
25 type Exporter struct {
26         mu      sync.Mutex
27         metrics []metric.Data
28 }
29
30 func (e *Exporter) ProcessEvent(ctx context.Context, ev core.Event, ln label.Map) context.Context {
31         if !event.IsMetric(ev) {
32                 return ctx
33         }
34         e.mu.Lock()
35         defer e.mu.Unlock()
36         metrics := metric.Entries.Get(ln).([]metric.Data)
37         for _, data := range metrics {
38                 name := data.Handle()
39                 // We keep the metrics in name sorted order so the page is stable and easy
40                 // to read. We do this with an insertion sort rather than sorting the list
41                 // each time
42                 index := sort.Search(len(e.metrics), func(i int) bool {
43                         return e.metrics[i].Handle() >= name
44                 })
45                 if index >= len(e.metrics) || e.metrics[index].Handle() != name {
46                         // we have a new metric, so we need to make a space for it
47                         old := e.metrics
48                         e.metrics = make([]metric.Data, len(old)+1)
49                         copy(e.metrics, old[:index])
50                         copy(e.metrics[index+1:], old[index:])
51                 }
52                 e.metrics[index] = data
53         }
54         return ctx
55 }
56
57 func (e *Exporter) header(w http.ResponseWriter, name, description string, isGauge, isHistogram bool) {
58         kind := "counter"
59         if isGauge {
60                 kind = "gauge"
61         }
62         if isHistogram {
63                 kind = "histogram"
64         }
65         fmt.Fprintf(w, "# HELP %s %s\n", name, description)
66         fmt.Fprintf(w, "# TYPE %s %s\n", name, kind)
67 }
68
69 func (e *Exporter) row(w http.ResponseWriter, name string, group []label.Label, extra string, value interface{}) {
70         fmt.Fprint(w, name)
71         buf := &bytes.Buffer{}
72         fmt.Fprint(buf, group)
73         if extra != "" {
74                 if buf.Len() > 0 {
75                         fmt.Fprint(buf, ",")
76                 }
77                 fmt.Fprint(buf, extra)
78         }
79         if buf.Len() > 0 {
80                 fmt.Fprint(w, "{")
81                 buf.WriteTo(w)
82                 fmt.Fprint(w, "}")
83         }
84         fmt.Fprintf(w, " %v\n", value)
85 }
86
87 func (e *Exporter) Serve(w http.ResponseWriter, r *http.Request) {
88         e.mu.Lock()
89         defer e.mu.Unlock()
90         for _, data := range e.metrics {
91                 switch data := data.(type) {
92                 case *metric.Int64Data:
93                         e.header(w, data.Info.Name, data.Info.Description, data.IsGauge, false)
94                         for i, group := range data.Groups() {
95                                 e.row(w, data.Info.Name, group, "", data.Rows[i])
96                         }
97
98                 case *metric.Float64Data:
99                         e.header(w, data.Info.Name, data.Info.Description, data.IsGauge, false)
100                         for i, group := range data.Groups() {
101                                 e.row(w, data.Info.Name, group, "", data.Rows[i])
102                         }
103
104                 case *metric.HistogramInt64Data:
105                         e.header(w, data.Info.Name, data.Info.Description, false, true)
106                         for i, group := range data.Groups() {
107                                 row := data.Rows[i]
108                                 for j, b := range data.Info.Buckets {
109                                         e.row(w, data.Info.Name+"_bucket", group, fmt.Sprintf(`le="%v"`, b), row.Values[j])
110                                 }
111                                 e.row(w, data.Info.Name+"_bucket", group, `le="+Inf"`, row.Count)
112                                 e.row(w, data.Info.Name+"_count", group, "", row.Count)
113                                 e.row(w, data.Info.Name+"_sum", group, "", row.Sum)
114                         }
115
116                 case *metric.HistogramFloat64Data:
117                         e.header(w, data.Info.Name, data.Info.Description, false, true)
118                         for i, group := range data.Groups() {
119                                 row := data.Rows[i]
120                                 for j, b := range data.Info.Buckets {
121                                         e.row(w, data.Info.Name+"_bucket", group, fmt.Sprintf(`le="%v"`, b), row.Values[j])
122                                 }
123                                 e.row(w, data.Info.Name+"_bucket", group, `le="+Inf"`, row.Count)
124                                 e.row(w, data.Info.Name+"_count", group, "", row.Count)
125                                 e.row(w, data.Info.Name+"_sum", group, "", row.Sum)
126                         }
127                 }
128         }
129 }