github.com/intel/goresctrl@v0.5.0/pkg/rdt/prometheus.go (about) 1 /* 2 Copyright 2020 Intel Corporation 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package rdt 18 19 import ( 20 "fmt" 21 "sync" 22 23 "github.com/prometheus/client_golang/prometheus" 24 ) 25 26 var customLabels []string = []string{} 27 28 // collector implements prometheus.Collector interface 29 type collector struct { 30 descriptors map[string]*prometheus.Desc 31 } 32 33 // NewCollector creates new Prometheus collector of RDT metrics 34 func NewCollector() (prometheus.Collector, error) { 35 c := &collector{descriptors: make(map[string]*prometheus.Desc)} 36 return c, nil 37 } 38 39 // RegisterCustomPrometheusLabels registers monitor group annotations to be 40 // exported as Prometheus metrics labels 41 func RegisterCustomPrometheusLabels(names ...string) { 42 Names: 43 for _, n := range names { 44 for _, c := range customLabels { 45 if n == c { 46 break Names 47 } 48 } 49 customLabels = append(customLabels, n) 50 } 51 } 52 53 // Describe method of the prometheus.Collector interface 54 func (c *collector) Describe(ch chan<- *prometheus.Desc) { 55 for resource, features := range GetMonFeatures() { 56 switch resource { 57 case MonResourceL3: 58 for _, f := range features { 59 ch <- c.describeL3(f) 60 } 61 } 62 } 63 } 64 65 // Collect method of the prometheus.Collector interface 66 func (c collector) Collect(ch chan<- prometheus.Metric) { 67 var wg sync.WaitGroup 68 69 for _, cls := range GetClasses() { 70 for _, monGrp := range cls.GetMonGroups() { 71 wg.Add(1) 72 g := monGrp 73 go func() { 74 defer wg.Done() 75 c.collectGroupMetrics(ch, g) 76 }() 77 } 78 } 79 wg.Wait() 80 } 81 82 func (c *collector) describeL3(feature string) *prometheus.Desc { 83 d, ok := c.descriptors[feature] 84 if !ok { 85 name := "l3_" + feature 86 help := "L3 " + feature 87 88 switch feature { 89 case "llc_occupancy": 90 help = "L3 (LLC) occupancy" 91 case "mbm_local_bytes": 92 help = "bytes transferred to/from local memory through LLC" 93 case "mbm_total_bytes": 94 help = "total bytes transferred to/from memory through LLC" 95 } 96 labels := append([]string{"rdt_class", "rdt_mon_group", "cache_id"}, customLabels...) 97 d = prometheus.NewDesc(name, help, labels, nil) 98 c.descriptors[feature] = d 99 } 100 return d 101 } 102 103 func (c *collector) collectGroupMetrics(ch chan<- prometheus.Metric, mg MonGroup) { 104 allData := mg.GetMonData() 105 106 annotations := mg.GetAnnotations() 107 customLabelValues := make([]string, len(customLabels)) 108 for i, name := range customLabels { 109 customLabelValues[i] = annotations[name] 110 } 111 112 for cacheID, data := range allData.L3 { 113 for feature, value := range data { 114 labels := append([]string{mg.Parent().Name(), mg.Name(), fmt.Sprint(cacheID)}, customLabelValues...) 115 116 ch <- prometheus.MustNewConstMetric( 117 c.describeL3(feature), 118 prometheus.CounterValue, 119 float64(value), 120 labels..., 121 ) 122 } 123 } 124 }