| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | // Copyright 2019 The Prometheus Authors
 | 
					
						
							|  |  |  | // Licensed under the Apache License, Version 2.0 (the "License");
 | 
					
						
							|  |  |  | // you may not use this file except in compliance with the License.
 | 
					
						
							|  |  |  | // You may obtain a copy of the License at
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // http://www.apache.org/licenses/LICENSE-2.0
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Unless required by applicable law or agreed to in writing, software
 | 
					
						
							|  |  |  | // distributed under the License is distributed on an "AS IS" BASIS,
 | 
					
						
							|  |  |  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
					
						
							|  |  |  | // See the License for the specific language governing permissions and
 | 
					
						
							|  |  |  | // limitations under the License.
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-03 04:35:24 -07:00
										 |  |  | //go:build !noperf
 | 
					
						
							| 
									
										
										
										
											2020-06-12 01:26:30 -07:00
										 |  |  | // +build !noperf
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | package collector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2020-02-19 05:34:05 -08:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-03-07 00:25:05 -08:00
										 |  |  | 	"github.com/alecthomas/kingpin/v2" | 
					
						
							| 
									
										
										
										
											2019-12-31 08:19:37 -08:00
										 |  |  | 	"github.com/hodgesds/perf-utils" | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 	"github.com/prometheus/client_golang/prometheus" | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	"golang.org/x/sys/unix" | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	perfSubsystem = "perf" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | var ( | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	perfCPUsFlag       = kingpin.Flag("collector.perf.cpus", "List of CPUs from which perf metrics should be collected").Default("").String() | 
					
						
							|  |  |  | 	perfTracepointFlag = kingpin.Flag("collector.perf.tracepoint", "perf tracepoint that should be collected").Strings() | 
					
						
							| 
									
										
										
										
											2022-12-06 20:52:46 -08:00
										 |  |  | 	perfNoHwProfiler   = kingpin.Flag("collector.perf.disable-hardware-profilers", "disable perf hardware profilers").Default("false").Bool() | 
					
						
							|  |  |  | 	perfHwProfilerFlag = kingpin.Flag("collector.perf.hardware-profilers", "perf hardware profilers that should be collected").Strings() | 
					
						
							|  |  |  | 	perfNoSwProfiler   = kingpin.Flag("collector.perf.disable-software-profilers", "disable perf software profilers").Default("false").Bool() | 
					
						
							|  |  |  | 	perfSwProfilerFlag = kingpin.Flag("collector.perf.software-profilers", "perf software profilers that should be collected").Strings() | 
					
						
							|  |  |  | 	perfNoCaProfiler   = kingpin.Flag("collector.perf.disable-cache-profilers", "disable perf cache profilers").Default("false").Bool() | 
					
						
							|  |  |  | 	perfCaProfilerFlag = kingpin.Flag("collector.perf.cache-profilers", "perf cache profilers that should be collected").Strings() | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | func init() { | 
					
						
							|  |  |  | 	registerCollector(perfSubsystem, defaultDisabled, NewPerfCollector) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 20:52:46 -08:00
										 |  |  | var ( | 
					
						
							|  |  |  | 	perfHardwareProfilerMap = map[string]perf.HardwareProfilerType{ | 
					
						
							|  |  |  | 		"CpuCycles":             perf.CpuCyclesProfiler, | 
					
						
							|  |  |  | 		"CpuInstr":              perf.CpuInstrProfiler, | 
					
						
							|  |  |  | 		"CacheRef":              perf.CacheRefProfiler, | 
					
						
							|  |  |  | 		"CacheMisses":           perf.CacheMissesProfiler, | 
					
						
							|  |  |  | 		"BranchInstr":           perf.BranchInstrProfiler, | 
					
						
							|  |  |  | 		"BranchMisses":          perf.BranchMissesProfiler, | 
					
						
							|  |  |  | 		"StalledCyclesBackend":  perf.StalledCyclesBackendProfiler, | 
					
						
							|  |  |  | 		"StalledCyclesFrontend": perf.StalledCyclesFrontendProfiler, | 
					
						
							|  |  |  | 		"RefCpuCycles":          perf.RefCpuCyclesProfiler, | 
					
						
							|  |  |  | 		// "BusCycles":             perf.BusCyclesProfiler,
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	perfSoftwareProfilerMap = map[string]perf.SoftwareProfilerType{ | 
					
						
							|  |  |  | 		"PageFault":     perf.PageFaultProfiler, | 
					
						
							|  |  |  | 		"ContextSwitch": perf.ContextSwitchProfiler, | 
					
						
							|  |  |  | 		"CpuMigration":  perf.CpuMigrationProfiler, | 
					
						
							|  |  |  | 		"MinorFault":    perf.MinorFaultProfiler, | 
					
						
							|  |  |  | 		"MajorFault":    perf.MajorFaultProfiler, | 
					
						
							|  |  |  | 		// "CpuClock":      perf.CpuClockProfiler,
 | 
					
						
							|  |  |  | 		// "TaskClock":     perf.TaskClockProfiler,
 | 
					
						
							|  |  |  | 		// "AlignFault":    perf.AlignFaultProfiler,
 | 
					
						
							|  |  |  | 		// "EmuFault":      perf.EmuFaultProfiler,
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	perfCacheProfilerMap = map[string]perf.CacheProfilerType{ | 
					
						
							|  |  |  | 		"L1DataReadHit":    perf.L1DataReadHitProfiler, | 
					
						
							|  |  |  | 		"L1DataReadMiss":   perf.L1DataReadMissProfiler, | 
					
						
							|  |  |  | 		"L1DataWriteHit":   perf.L1DataWriteHitProfiler, | 
					
						
							|  |  |  | 		"L1InstrReadMiss":  perf.L1InstrReadMissProfiler, | 
					
						
							|  |  |  | 		"LLReadHit":        perf.LLReadHitProfiler, | 
					
						
							|  |  |  | 		"LLReadMiss":       perf.LLReadMissProfiler, | 
					
						
							|  |  |  | 		"LLWriteHit":       perf.LLWriteHitProfiler, | 
					
						
							|  |  |  | 		"LLWriteMiss":      perf.LLWriteMissProfiler, | 
					
						
							|  |  |  | 		"InstrTLBReadHit":  perf.InstrTLBReadHitProfiler, | 
					
						
							|  |  |  | 		"InstrTLBReadMiss": perf.InstrTLBReadMissProfiler, | 
					
						
							|  |  |  | 		"BPUReadHit":       perf.BPUReadHitProfiler, | 
					
						
							|  |  |  | 		"BPUReadMiss":      perf.BPUReadMissProfiler, | 
					
						
							|  |  |  | 		// "L1InstrReadHit":     perf.L1InstrReadHitProfiler,
 | 
					
						
							|  |  |  | 		// "DataTLBReadHit":     perf.DataTLBReadHitProfiler,
 | 
					
						
							|  |  |  | 		// "DataTLBReadMiss":    perf.DataTLBReadMissProfiler,
 | 
					
						
							|  |  |  | 		// "DataTLBWriteHit":    perf.DataTLBWriteHitProfiler,
 | 
					
						
							|  |  |  | 		// "DataTLBWriteMiss":   perf.DataTLBWriteMissProfiler,
 | 
					
						
							|  |  |  | 		// "NodeCacheReadHit":   perf.NodeCacheReadHitProfiler,
 | 
					
						
							|  |  |  | 		// "NodeCacheReadMiss":  perf.NodeCacheReadMissProfiler,
 | 
					
						
							|  |  |  | 		// "NodeCacheWriteHit":  perf.NodeCacheWriteHitProfiler,
 | 
					
						
							|  |  |  | 		// "NodeCacheWriteMiss": perf.NodeCacheWriteMissProfiler,
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | // perfTracepointFlagToTracepoints returns the set of configured tracepoints.
 | 
					
						
							|  |  |  | func perfTracepointFlagToTracepoints(tracepointsFlag []string) ([]*perfTracepoint, error) { | 
					
						
							|  |  |  | 	tracepoints := make([]*perfTracepoint, len(tracepointsFlag)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, tracepoint := range tracepointsFlag { | 
					
						
							|  |  |  | 		split := strings.Split(tracepoint, ":") | 
					
						
							|  |  |  | 		if len(split) != 2 { | 
					
						
							| 
									
										
										
										
											2022-04-08 22:36:59 -07:00
										 |  |  | 			return nil, fmt.Errorf("invalid tracepoint config %v", tracepoint) | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		tracepoints[i] = &perfTracepoint{ | 
					
						
							|  |  |  | 			subsystem: split[0], | 
					
						
							|  |  |  | 			event:     split[1], | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tracepoints, nil | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // perfCPUFlagToCPUs returns a set of CPUs for the perf collectors to monitor.
 | 
					
						
							|  |  |  | func perfCPUFlagToCPUs(cpuFlag string) ([]int, error) { | 
					
						
							|  |  |  | 	var err error | 
					
						
							|  |  |  | 	cpus := []int{} | 
					
						
							|  |  |  | 	for _, subset := range strings.Split(cpuFlag, ",") { | 
					
						
							|  |  |  | 		// First parse a single CPU.
 | 
					
						
							|  |  |  | 		if !strings.Contains(subset, "-") { | 
					
						
							|  |  |  | 			cpu, err := strconv.Atoi(subset) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			cpus = append(cpus, cpu) | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		stride := 1 | 
					
						
							|  |  |  | 		// Handle strides, ie 1-10:5 should yield 1,5,10
 | 
					
						
							|  |  |  | 		strideSet := strings.Split(subset, ":") | 
					
						
							|  |  |  | 		if len(strideSet) == 2 { | 
					
						
							|  |  |  | 			stride, err = strconv.Atoi(strideSet[1]) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		rangeSet := strings.Split(strideSet[0], "-") | 
					
						
							|  |  |  | 		if len(rangeSet) != 2 { | 
					
						
							|  |  |  | 			return nil, fmt.Errorf("invalid flag value %q", cpuFlag) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		start, err := strconv.Atoi(rangeSet[0]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		end, err := strconv.Atoi(rangeSet[1]) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		for i := start; i <= end; i += stride { | 
					
						
							|  |  |  | 			cpus = append(cpus, i) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cpus, nil | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | // perfTracepoint is a struct for holding tracepoint information.
 | 
					
						
							|  |  |  | type perfTracepoint struct { | 
					
						
							|  |  |  | 	subsystem string | 
					
						
							|  |  |  | 	event     string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // label returns the tracepoint name in the format of subsystem_tracepoint.
 | 
					
						
							|  |  |  | func (t *perfTracepoint) label() string { | 
					
						
							|  |  |  | 	return t.subsystem + "_" + t.event | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // tracepoint returns the tracepoint name in the format of subsystem:tracepoint.
 | 
					
						
							|  |  |  | func (t *perfTracepoint) tracepoint() string { | 
					
						
							|  |  |  | 	return t.subsystem + ":" + t.event | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // perfCollector is a Collector that uses the perf subsystem to collect
 | 
					
						
							|  |  |  | // metrics. It uses perf_event_open an ioctls for profiling. Due to the fact
 | 
					
						
							|  |  |  | // that the perf subsystem is highly dependent on kernel configuration and
 | 
					
						
							|  |  |  | // settings not all profiler values may be exposed on the target system at any
 | 
					
						
							|  |  |  | // given time.
 | 
					
						
							|  |  |  | type perfCollector struct { | 
					
						
							|  |  |  | 	hwProfilerCPUMap    map[*perf.HardwareProfiler]int | 
					
						
							|  |  |  | 	swProfilerCPUMap    map[*perf.SoftwareProfiler]int | 
					
						
							|  |  |  | 	cacheProfilerCPUMap map[*perf.CacheProfiler]int | 
					
						
							|  |  |  | 	perfHwProfilers     map[int]*perf.HardwareProfiler | 
					
						
							|  |  |  | 	perfSwProfilers     map[int]*perf.SoftwareProfiler | 
					
						
							|  |  |  | 	perfCacheProfilers  map[int]*perf.CacheProfiler | 
					
						
							|  |  |  | 	desc                map[string]*prometheus.Desc | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger              *slog.Logger | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	tracepointCollector *perfTracepointCollector | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type perfTracepointCollector struct { | 
					
						
							|  |  |  | 	// desc is the mapping of subsystem to tracepoint *prometheus.Desc.
 | 
					
						
							|  |  |  | 	descs map[string]map[string]*prometheus.Desc | 
					
						
							|  |  |  | 	// collection order is the sorted configured collection order of the profiler.
 | 
					
						
							|  |  |  | 	collectionOrder []string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger    *slog.Logger | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	profilers map[int]perf.GroupProfiler | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // update is used collect all tracepoints across all tracepoint profilers.
 | 
					
						
							|  |  |  | func (c *perfTracepointCollector) update(ch chan<- prometheus.Metric) error { | 
					
						
							|  |  |  | 	for cpu := range c.profilers { | 
					
						
							|  |  |  | 		if err := c.updateCPU(cpu, ch); err != nil { | 
					
						
							|  |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // updateCPU is used to update metrics per CPU profiler.
 | 
					
						
							|  |  |  | func (c *perfTracepointCollector) updateCPU(cpu int, ch chan<- prometheus.Metric) error { | 
					
						
							|  |  |  | 	profiler := c.profilers[cpu] | 
					
						
							| 
									
										
										
										
											2022-03-28 08:58:13 -07:00
										 |  |  | 	p := &perf.GroupProfileValue{} | 
					
						
							|  |  |  | 	if err := profiler.Profile(p); err != nil { | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 		c.logger.Error("Failed to collect tracepoint profile", "err", err) | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 	cpuid := strconv.Itoa(cpu) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	for i, value := range p.Values { | 
					
						
							|  |  |  | 		// Get the Desc from the ordered group value.
 | 
					
						
							|  |  |  | 		descKey := c.collectionOrder[i] | 
					
						
							|  |  |  | 		descKeySlice := strings.Split(descKey, ":") | 
					
						
							|  |  |  | 		ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 			c.descs[descKeySlice[0]][descKeySlice[1]], | 
					
						
							|  |  |  | 			prometheus.CounterValue, | 
					
						
							|  |  |  | 			float64(value), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 			cpuid, | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // newPerfTracepointCollector returns a configured perfTracepointCollector.
 | 
					
						
							|  |  |  | func newPerfTracepointCollector( | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | 	logger *slog.Logger, | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	tracepointsFlag []string, | 
					
						
							|  |  |  | 	cpus []int, | 
					
						
							|  |  |  | ) (*perfTracepointCollector, error) { | 
					
						
							|  |  |  | 	tracepoints, err := perfTracepointFlagToTracepoints(tracepointsFlag) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	collectionOrder := make([]string, len(tracepoints)) | 
					
						
							|  |  |  | 	descs := map[string]map[string]*prometheus.Desc{} | 
					
						
							|  |  |  | 	eventAttrs := make([]unix.PerfEventAttr, len(tracepoints)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, tracepoint := range tracepoints { | 
					
						
							|  |  |  | 		eventAttr, err := perf.TracepointEventAttr(tracepoint.subsystem, tracepoint.event) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		eventAttrs[i] = *eventAttr | 
					
						
							|  |  |  | 		collectionOrder[i] = tracepoint.tracepoint() | 
					
						
							|  |  |  | 		if _, ok := descs[tracepoint.subsystem]; !ok { | 
					
						
							|  |  |  | 			descs[tracepoint.subsystem] = map[string]*prometheus.Desc{} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		descs[tracepoint.subsystem][tracepoint.event] = prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				tracepoint.label(), | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Perf tracepoint "+tracepoint.tracepoint(), | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	profilers := make(map[int]perf.GroupProfiler, len(cpus)) | 
					
						
							|  |  |  | 	for _, cpu := range cpus { | 
					
						
							|  |  |  | 		profiler, err := perf.NewGroupProfiler(-1, cpu, 0, eventAttrs...) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		profilers[cpu] = profiler | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	c := &perfTracepointCollector{ | 
					
						
							|  |  |  | 		descs:           descs, | 
					
						
							|  |  |  | 		collectionOrder: collectionOrder, | 
					
						
							|  |  |  | 		profilers:       profilers, | 
					
						
							|  |  |  | 		logger:          logger, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, profiler := range c.profilers { | 
					
						
							|  |  |  | 		if err := profiler.Start(); err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return c, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | // NewPerfCollector returns a new perf based collector, it creates a profiler
 | 
					
						
							|  |  |  | // per CPU.
 | 
					
						
							| 
									
										
										
										
											2024-09-11 01:51:28 -07:00
										 |  |  | func NewPerfCollector(logger *slog.Logger) (Collector, error) { | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	collector := &perfCollector{ | 
					
						
							|  |  |  | 		perfHwProfilers:     map[int]*perf.HardwareProfiler{}, | 
					
						
							|  |  |  | 		perfSwProfilers:     map[int]*perf.SoftwareProfiler{}, | 
					
						
							|  |  |  | 		perfCacheProfilers:  map[int]*perf.CacheProfiler{}, | 
					
						
							|  |  |  | 		hwProfilerCPUMap:    map[*perf.HardwareProfiler]int{}, | 
					
						
							|  |  |  | 		swProfilerCPUMap:    map[*perf.SoftwareProfiler]int{}, | 
					
						
							|  |  |  | 		cacheProfilerCPUMap: map[*perf.CacheProfiler]int{}, | 
					
						
							|  |  |  | 		logger:              logger, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 03:05:59 -08:00
										 |  |  | 	var ( | 
					
						
							|  |  |  | 		cpus []int | 
					
						
							|  |  |  | 		err  error | 
					
						
							|  |  |  | 	) | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	if perfCPUsFlag != nil && *perfCPUsFlag != "" { | 
					
						
							| 
									
										
										
										
											2020-02-20 03:05:59 -08:00
										 |  |  | 		cpus, err = perfCPUFlagToCPUs(*perfCPUsFlag) | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-20 03:05:59 -08:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		cpus = make([]int, runtime.NumCPU()) | 
					
						
							|  |  |  | 		for i := range cpus { | 
					
						
							|  |  |  | 			cpus[i] = i | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	// First configure any tracepoints.
 | 
					
						
							|  |  |  | 	if *perfTracepointFlag != nil && len(*perfTracepointFlag) > 0 { | 
					
						
							|  |  |  | 		tracepointCollector, err := newPerfTracepointCollector(logger, *perfTracepointFlag, cpus) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		collector.tracepointCollector = tracepointCollector | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 20:52:46 -08:00
										 |  |  | 	// Configure perf profilers
 | 
					
						
							|  |  |  | 	hardwareProfilers := perf.AllHardwareProfilers | 
					
						
							|  |  |  | 	if *perfHwProfilerFlag != nil && len(*perfHwProfilerFlag) > 0 { | 
					
						
							|  |  |  | 		// hardwareProfilers = 0
 | 
					
						
							|  |  |  | 		for _, hf := range *perfHwProfilerFlag { | 
					
						
							|  |  |  | 			if v, ok := perfHardwareProfilerMap[hf]; ok { | 
					
						
							|  |  |  | 				hardwareProfilers |= v | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	softwareProfilers := perf.AllSoftwareProfilers | 
					
						
							|  |  |  | 	if *perfSwProfilerFlag != nil && len(*perfSwProfilerFlag) > 0 { | 
					
						
							|  |  |  | 		// softwareProfilers = 0
 | 
					
						
							|  |  |  | 		for _, sf := range *perfSwProfilerFlag { | 
					
						
							|  |  |  | 			if v, ok := perfSoftwareProfilerMap[sf]; ok { | 
					
						
							|  |  |  | 				softwareProfilers |= v | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	cacheProfilers := perf.L1DataReadHitProfiler | perf.L1DataReadMissProfiler | perf.L1DataWriteHitProfiler | perf.L1InstrReadMissProfiler | perf.InstrTLBReadHitProfiler | perf.InstrTLBReadMissProfiler | perf.LLReadHitProfiler | perf.LLReadMissProfiler | perf.LLWriteHitProfiler | perf.LLWriteMissProfiler | perf.BPUReadHitProfiler | perf.BPUReadMissProfiler | 
					
						
							|  |  |  | 	if *perfCaProfilerFlag != nil && len(*perfCaProfilerFlag) > 0 { | 
					
						
							|  |  |  | 		cacheProfilers = 0 | 
					
						
							|  |  |  | 		for _, cf := range *perfCaProfilerFlag { | 
					
						
							|  |  |  | 			if v, ok := perfCacheProfilerMap[cf]; ok { | 
					
						
							|  |  |  | 				cacheProfilers |= v | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	// Configure all profilers for the specified CPUs.
 | 
					
						
							| 
									
										
										
										
											2020-02-20 03:05:59 -08:00
										 |  |  | 	for _, cpu := range cpus { | 
					
						
							|  |  |  | 		// Use -1 to profile all processes on the CPU, see:
 | 
					
						
							|  |  |  | 		// man perf_event_open
 | 
					
						
							| 
									
										
										
										
											2022-12-06 20:52:46 -08:00
										 |  |  | 		if !*perfNoHwProfiler { | 
					
						
							|  |  |  | 			hwProf, err := perf.NewHardwareProfiler( | 
					
						
							|  |  |  | 				-1, | 
					
						
							|  |  |  | 				cpu, | 
					
						
							|  |  |  | 				hardwareProfilers, | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 			if err != nil && !hwProf.HasProfilers() { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err := hwProf.Start(); err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			collector.perfHwProfilers[cpu] = &hwProf | 
					
						
							|  |  |  | 			collector.hwProfilerCPUMap[&hwProf] = cpu | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-06 20:52:46 -08:00
										 |  |  | 		if !*perfNoSwProfiler { | 
					
						
							|  |  |  | 			swProf, err := perf.NewSoftwareProfiler(-1, cpu, softwareProfilers) | 
					
						
							|  |  |  | 			if err != nil && !swProf.HasProfilers() { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err := swProf.Start(); err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			collector.perfSwProfilers[cpu] = &swProf | 
					
						
							|  |  |  | 			collector.swProfilerCPUMap[&swProf] = cpu | 
					
						
							| 
									
										
										
										
											2021-10-03 04:35:24 -07:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-12-06 20:52:46 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if !*perfNoCaProfiler { | 
					
						
							|  |  |  | 			cacheProf, err := perf.NewCacheProfiler( | 
					
						
							|  |  |  | 				-1, | 
					
						
							|  |  |  | 				cpu, | 
					
						
							|  |  |  | 				cacheProfilers, | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 			if err != nil && !cacheProf.HasProfilers() { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			if err := cacheProf.Start(); err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			collector.perfCacheProfilers[cpu] = &cacheProf | 
					
						
							|  |  |  | 			collector.cacheProfilerCPUMap[&cacheProf] = cpu | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	collector.desc = map[string]*prometheus.Desc{ | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		"cpucycles_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cpucycles_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of CPU cycles (frequency scaled)", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"instructions_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"instructions_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of CPU instructions", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"branch_instructions_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"branch_instructions_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of CPU branch instructions", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"branch_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"branch_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of CPU branch misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_refs_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_refs_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of cache references (non frequency scaled)", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of cache misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"ref_cpucycles_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"ref_cpucycles_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of CPU cycles", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							| 
									
										
										
										
											2022-08-02 05:42:48 -07:00
										 |  |  | 		"stalled_cycles_backend_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"stalled_cycles_backend_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of stalled backend CPU cycles", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"stalled_cycles_frontend_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"stalled_cycles_frontend_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of stalled frontend CPU cycles", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		"page_faults_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"page_faults_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of page faults", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"context_switches_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"context_switches_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of context switches", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cpu_migrations_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cpu_migrations_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of CPU process migrations", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"minor_faults_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"minor_faults_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of minor page faults", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"major_faults_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"major_faults_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number of major page faults", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_l1d_read_hits_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_l1d_read_hits_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number L1 data cache read hits", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_l1d_read_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_l1d_read_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number L1 data cache read misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_l1d_write_hits_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_l1d_write_hits_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number L1 data cache write hits", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_l1_instr_read_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_l1_instr_read_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number instruction L1 instruction read misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_tlb_instr_read_hits_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_tlb_instr_read_hits_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number instruction TLB read hits", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_tlb_instr_read_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_tlb_instr_read_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number instruction TLB read misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_ll_read_hits_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_ll_read_hits_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number last level read hits", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_ll_read_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_ll_read_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number last level read misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_ll_write_hits_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_ll_write_hits_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number last level write hits", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_ll_write_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_ll_write_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number last level write misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_bpu_read_hits_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_bpu_read_hits_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number BPU read hits", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 		"cache_bpu_read_misses_total": prometheus.NewDesc( | 
					
						
							|  |  |  | 			prometheus.BuildFQName( | 
					
						
							|  |  |  | 				namespace, | 
					
						
							|  |  |  | 				perfSubsystem, | 
					
						
							|  |  |  | 				"cache_bpu_read_misses_total", | 
					
						
							|  |  |  | 			), | 
					
						
							|  |  |  | 			"Number BPU read misses", | 
					
						
							|  |  |  | 			[]string{"cpu"}, | 
					
						
							|  |  |  | 			nil, | 
					
						
							|  |  |  | 		), | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	return collector, nil | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Update implements the Collector interface and will collect metrics per CPU.
 | 
					
						
							|  |  |  | func (c *perfCollector) Update(ch chan<- prometheus.Metric) error { | 
					
						
							|  |  |  | 	if err := c.updateHardwareStats(ch); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := c.updateSoftwareStats(ch); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if err := c.updateCacheStats(ch); err != nil { | 
					
						
							|  |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-04-17 03:02:08 -07:00
										 |  |  | 	if c.tracepointCollector != nil { | 
					
						
							|  |  |  | 		return c.tracepointCollector.update(ch) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *perfCollector) updateHardwareStats(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	for _, profiler := range c.perfHwProfilers { | 
					
						
							| 
									
										
										
										
											2022-03-28 08:58:13 -07:00
										 |  |  | 		hwProfile := &perf.HardwareProfile{} | 
					
						
							|  |  |  | 		if err := (*profiler).Profile(hwProfile); err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 		cpuid := strconv.Itoa(c.hwProfilerCPUMap[profiler]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		if hwProfile.CPUCycles != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cpucycles_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.CPUCycles), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.Instructions != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["instructions_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.Instructions), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.BranchInstr != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["branch_instructions_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.BranchInstr), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.BranchMisses != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["branch_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.BranchMisses), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.CacheRefs != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_refs_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.CacheRefs), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.CacheMisses != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.CacheMisses), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.RefCPUCycles != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["ref_cpucycles_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.RefCPUCycles), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2022-08-02 05:42:48 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.StalledCyclesBackend != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["stalled_cycles_backend_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.StalledCyclesBackend), | 
					
						
							|  |  |  | 				cpuid, | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if hwProfile.StalledCyclesFrontend != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["stalled_cycles_frontend_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*hwProfile.StalledCyclesFrontend), | 
					
						
							|  |  |  | 				cpuid, | 
					
						
							|  |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *perfCollector) updateSoftwareStats(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	for _, profiler := range c.perfSwProfilers { | 
					
						
							| 
									
										
										
										
											2022-03-28 08:58:13 -07:00
										 |  |  | 		swProfile := &perf.SoftwareProfile{} | 
					
						
							|  |  |  | 		if err := (*profiler).Profile(swProfile); err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 		cpuid := strconv.Itoa(c.swProfilerCPUMap[profiler]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		if swProfile.PageFaults != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["page_faults_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*swProfile.PageFaults), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if swProfile.ContextSwitches != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["context_switches_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*swProfile.ContextSwitches), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if swProfile.CPUMigrations != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cpu_migrations_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*swProfile.CPUMigrations), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if swProfile.MinorPageFaults != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["minor_faults_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*swProfile.MinorPageFaults), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if swProfile.MajorPageFaults != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["major_faults_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*swProfile.MajorPageFaults), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *perfCollector) updateCacheStats(ch chan<- prometheus.Metric) error { | 
					
						
							| 
									
										
										
										
											2020-02-20 02:36:33 -08:00
										 |  |  | 	for _, profiler := range c.perfCacheProfilers { | 
					
						
							| 
									
										
										
										
											2022-03-28 08:58:13 -07:00
										 |  |  | 		cacheProfile := &perf.CacheProfile{} | 
					
						
							|  |  |  | 		if err := (*profiler).Profile(cacheProfile); err != nil { | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			return err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 		cpuid := strconv.Itoa(c.cacheProfilerCPUMap[profiler]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 		if cacheProfile.L1DataReadHit != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_l1d_read_hits_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.L1DataReadHit), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.L1DataReadMiss != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_l1d_read_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.L1DataReadMiss), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.L1DataWriteHit != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_l1d_write_hits_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.L1DataWriteHit), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.L1InstrReadMiss != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_l1_instr_read_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.L1InstrReadMiss), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.InstrTLBReadHit != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_tlb_instr_read_hits_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.InstrTLBReadHit), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.InstrTLBReadMiss != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_tlb_instr_read_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.InstrTLBReadMiss), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.LastLevelReadHit != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_ll_read_hits_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.LastLevelReadHit), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.LastLevelReadMiss != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_ll_read_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.LastLevelReadMiss), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.LastLevelWriteHit != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_ll_write_hits_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.LastLevelWriteHit), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.LastLevelWriteMiss != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_ll_write_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.LastLevelWriteMiss), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.BPUReadHit != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_bpu_read_hits_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.BPUReadHit), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if cacheProfile.BPUReadMiss != nil { | 
					
						
							|  |  |  | 			ch <- prometheus.MustNewConstMetric( | 
					
						
							|  |  |  | 				c.desc["cache_bpu_read_misses_total"], | 
					
						
							|  |  |  | 				prometheus.CounterValue, float64(*cacheProfile.BPUReadMiss), | 
					
						
							| 
									
										
										
										
											2021-10-22 12:03:10 -07:00
										 |  |  | 				cpuid, | 
					
						
							| 
									
										
										
										
											2019-05-07 04:21:41 -07:00
										 |  |  | 			) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |