@@ -234,7 +234,13 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
234234 e .perfEventArrayCollectors = append (e .perfEventArrayCollectors , perfSink )
235235 }
236236
237- addDescs (cfg .Name , counter .Name , counter .Help , counter .Labels )
237+ if counter .Values != nil {
238+ for _ , value := range counter .Values {
239+ addDescs (cfg .Name , value .Name , value .Help , counter .Labels )
240+ }
241+ } else {
242+ addDescs (cfg .Name , counter .Name , counter .Help , counter .Labels )
243+ }
238244 }
239245
240246 for _ , histogram := range cfg .Metrics .Histograms {
@@ -303,10 +309,14 @@ func (e *Exporter) collectCounters(ch chan<- prometheus.Metric) {
303309
304310 aggregatedMapValues := aggregateMapValues (mapValues )
305311
306- desc := e.descs [cfg.Name ][counter.Name ]
307-
308312 for _ , metricValue := range aggregatedMapValues {
309- ch <- prometheus .MustNewConstMetric (desc , prometheus .CounterValue , metricValue .value , metricValue .labels ... )
313+ if counter .Values != nil {
314+ for i , value := range counter .Values {
315+ ch <- prometheus .MustNewConstMetric (e.descs [cfg.Name ][value.Name ], prometheus .CounterValue , metricValue .value [i ], metricValue .labels ... )
316+ }
317+ } else {
318+ ch <- prometheus .MustNewConstMetric (e.descs [cfg.Name ][counter.Name ], prometheus .CounterValue , metricValue .value [0 ], metricValue .labels ... )
319+ }
310320 }
311321 }
312322 }
@@ -356,7 +366,7 @@ func (e *Exporter) collectHistograms(ch chan<- prometheus.Metric) {
356366 break
357367 }
358368
359- histograms [key ].buckets [float64 (leUint )] = uint64 (metricValue .value )
369+ histograms [key ].buckets [float64 (leUint )] = uint64 (metricValue .value [ 0 ] )
360370 }
361371
362372 if skip {
@@ -497,29 +507,33 @@ func (e *Exporter) MapsHandler(w http.ResponseWriter, r *http.Request) {
497507}
498508
499509func validateMaps (module * libbpfgo.Module , cfg config.Config ) error {
500- maps := [] string {}
510+ sizes := map [ string ] int {}
501511
502512 for _ , counter := range cfg .Metrics .Counters {
503513 if counter .Name != "" {
504- maps = append (maps , counter .Name )
514+ if counter .Values != nil {
515+ sizes [counter .Name ] = len (counter .Values ) * 8
516+ } else {
517+ sizes [counter .Name ] = 8
518+ }
505519 }
506520 }
507521
508522 for _ , histogram := range cfg .Metrics .Histograms {
509523 if histogram .Name != "" {
510- maps = append ( maps , histogram .Name )
524+ sizes [ histogram .Name ] = 8
511525 }
512526 }
513527
514- for _ , name := range maps {
528+ for name , expected := range sizes {
515529 m , err := module .GetMap (name )
516530 if err != nil {
517531 return fmt .Errorf ("failed to get map %q: %v" , name , err )
518532 }
519533
520534 valueSize := m .ValueSize ()
521- if valueSize != 8 {
522- return fmt .Errorf ("value size for map %q is not expected 8 bytes (u64), it is %d bytes" , name , valueSize )
535+ if valueSize != expected {
536+ return fmt .Errorf ("value size for map %q is not expected %d bytes (8 bytes per u64 value ), it is %d bytes" , name , expected , valueSize )
523537 }
524538 }
525539
@@ -545,7 +559,9 @@ func aggregateMapValues(values []metricValue) []aggregatedMetricValue {
545559 value : value .value ,
546560 }
547561 } else {
548- existing .value += value .value
562+ for i := range existing .value {
563+ existing .value [i ] += value .value [i ]
564+ }
549565 }
550566 }
551567
@@ -609,17 +625,17 @@ func readMapValues(m *libbpfgo.BPFMap, labels []config.Label) ([]metricValue, er
609625 return metricValues , nil
610626}
611627
612- func mapValue (m * libbpfgo.BPFMap , key []byte ) (float64 , error ) {
628+ func mapValue (m * libbpfgo.BPFMap , key []byte ) ([] float64 , error ) {
613629 v , err := m .GetValue (unsafe .Pointer (& key [0 ]))
614630 if err != nil {
615- return 0.0 , err
631+ return [] float64 { 0.0 } , err
616632 }
617633
618634 return decodeValue (v ), nil
619635}
620636
621- func mapValuePerCPU (m * libbpfgo.BPFMap , key []byte ) ([]float64 , error ) {
622- values := []float64 {}
637+ func mapValuePerCPU (m * libbpfgo.BPFMap , key []byte ) ([][] float64 , error ) {
638+ values := [][] float64 {}
623639
624640 size := m .ValueSize ()
625641 value := make ([]byte , size * runtime .NumCPU ())
@@ -636,8 +652,14 @@ func mapValuePerCPU(m *libbpfgo.BPFMap, key []byte) ([]float64, error) {
636652}
637653
638654// Assuming counter's value type is always u64
639- func decodeValue (value []byte ) float64 {
640- return float64 (util .GetHostByteOrder ().Uint64 (value ))
655+ func decodeValue (value []byte ) []float64 {
656+ values := make ([]float64 , len (value )/ 8 )
657+
658+ for i := range values {
659+ values [i ] = float64 (util .GetHostByteOrder ().Uint64 (value [i * 8 :]))
660+ }
661+
662+ return values
641663}
642664
643665// metricValue is a row in a kernel map
@@ -647,13 +669,13 @@ type metricValue struct {
647669 // labels are decoded from the raw key
648670 labels []string
649671 // value is the kernel map value
650- value float64
672+ value [] float64
651673}
652674
653675// aggregatedMetricValue is a value after aggregation of equal label sets
654676type aggregatedMetricValue struct {
655677 // labels are decoded from the raw key
656678 labels []string
657679 // value is the kernel map value
658- value float64
680+ value [] float64
659681}
0 commit comments