github.com/safing/portbase@v0.19.5/metrics/metrics_runtime.go (about) 1 package metrics 2 3 import ( 4 "bufio" 5 "bytes" 6 "fmt" 7 "io" 8 "strings" 9 10 vm "github.com/VictoriaMetrics/metrics" 11 12 "github.com/safing/portbase/api" 13 "github.com/safing/portbase/config" 14 "github.com/safing/portbase/log" 15 ) 16 17 func registerRuntimeMetric() error { 18 runtimeBase, err := newMetricBase("_runtime", nil, Options{ 19 Name: "Golang Runtime", 20 Permission: api.PermitAdmin, 21 ExpertiseLevel: config.ExpertiseLevelDeveloper, 22 }) 23 if err != nil { 24 return err 25 } 26 27 return register(&runtimeMetrics{ 28 metricBase: runtimeBase, 29 }) 30 } 31 32 type runtimeMetrics struct { 33 *metricBase 34 } 35 36 func (r *runtimeMetrics) WritePrometheus(w io.Writer) { 37 // If there nothing to change, just write directly to w. 38 if metricNamespace == "" && len(globalLabels) == 0 { 39 vm.WriteProcessMetrics(w) 40 return 41 } 42 43 // Write metrics to buffer. 44 buf := new(bytes.Buffer) 45 vm.WriteProcessMetrics(buf) 46 47 // Add namespace and label per line. 48 scanner := bufio.NewScanner(buf) 49 scanner.Split(bufio.ScanLines) 50 for scanner.Scan() { 51 line := scanner.Text() 52 53 // Add namespace, if set. 54 if metricNamespace != "" { 55 line = metricNamespace + "_" + line 56 } 57 58 // Add global labels, if set. 59 if len(globalLabels) > 0 { 60 // Find where to insert. 61 mergeWithExisting := true 62 insertAt := strings.Index(line, "{") + 1 63 if insertAt <= 0 { 64 mergeWithExisting = false 65 insertAt = strings.Index(line, " ") 66 if insertAt < 0 { 67 continue 68 } 69 } 70 71 // Write new line directly to w. 72 fmt.Fprint(w, line[:insertAt]) 73 if !mergeWithExisting { 74 fmt.Fprint(w, "{") 75 } 76 labelsAdded := 0 77 for labelKey, labelValue := range globalLabels { 78 fmt.Fprintf(w, "%s=%q", labelKey, labelValue) 79 // Add separator if not last label. 80 labelsAdded++ 81 if labelsAdded < len(globalLabels) { 82 fmt.Fprint(w, ", ") 83 } 84 } 85 if mergeWithExisting { 86 fmt.Fprint(w, ", ") 87 } else { 88 fmt.Fprint(w, "}") 89 } 90 fmt.Fprintln(w, line[insertAt:]) 91 } 92 } 93 94 // Check if there was an error in the scanner. 95 if scanner.Err() != nil { 96 log.Warningf("metrics: failed to scan go process metrics: %s", scanner.Err()) 97 } 98 }