@@ -392,7 +392,13 @@ func (e *Exporter) Describe(ch chan<- *prometheus.Desc) {
392392 e .perfEventArrayCollectors = append (e .perfEventArrayCollectors , perfSink )
393393 }
394394
395- addDescs (cfg .Name , counter .Name , counter .Help , counter .Labels )
395+ if counter .Values != nil {
396+ for _ , value := range counter .Values {
397+ addDescs (cfg .Name , value .Name , value .Help , counter .Labels )
398+ }
399+ } else {
400+ addDescs (cfg .Name , counter .Name , counter .Help , counter .Labels )
401+ }
396402 }
397403
398404 for _ , histogram := range cfg .Metrics .Histograms {
@@ -477,10 +483,14 @@ func (e *Exporter) collectCounters(ch chan<- prometheus.Metric) {
477483
478484 aggregatedMapValues := aggregateMapValues (mapValues )
479485
480- desc := e.descs [cfg.Name ][counter.Name ]
481-
482486 for _ , metricValue := range aggregatedMapValues {
483- ch <- prometheus .MustNewConstMetric (desc , prometheus .CounterValue , metricValue .value , metricValue .labels ... )
487+ if counter .Values != nil {
488+ for i , value := range counter .Values {
489+ ch <- prometheus .MustNewConstMetric (e.descs [cfg.Name ][value.Name ], prometheus .CounterValue , metricValue .value [i ], metricValue .labels ... )
490+ }
491+ } else {
492+ ch <- prometheus .MustNewConstMetric (e.descs [cfg.Name ][counter.Name ], prometheus .CounterValue , metricValue .value [0 ], metricValue .labels ... )
493+ }
484494 }
485495 }
486496 }
@@ -531,7 +541,7 @@ func (e *Exporter) collectHistograms(ch chan<- prometheus.Metric) {
531541 break
532542 }
533543
534- histograms [key ].buckets [float64 (leUint )] = uint64 (metricValue .value )
544+ histograms [key ].buckets [float64 (leUint )] = uint64 (metricValue .value [ 0 ] )
535545 }
536546
537547 if skip {
@@ -673,29 +683,33 @@ func (e *Exporter) MapsHandler(w http.ResponseWriter, r *http.Request) {
673683}
674684
675685func validateMaps (module * libbpfgo.Module , cfg config.Config ) error {
676- maps := [] string {}
686+ sizes := map [ string ] int {}
677687
678688 for _ , counter := range cfg .Metrics .Counters {
679689 if counter .Name != "" && ! counter .PerfEventArray {
680- maps = append (maps , counter .Name )
690+ if counter .Values != nil {
691+ sizes [counter .Name ] = len (counter .Values ) * 8
692+ } else {
693+ sizes [counter .Name ] = 8
694+ }
681695 }
682696 }
683697
684698 for _ , histogram := range cfg .Metrics .Histograms {
685699 if histogram .Name != "" {
686- maps = append ( maps , histogram .Name )
700+ sizes [ histogram .Name ] = 8
687701 }
688702 }
689703
690- for _ , name := range maps {
704+ for name , expected := range sizes {
691705 m , err := module .GetMap (name )
692706 if err != nil {
693707 return fmt .Errorf ("failed to get map %q: %w" , name , err )
694708 }
695709
696710 valueSize := m .ValueSize ()
697- if valueSize != 8 {
698- return fmt .Errorf ("value size for map %q is not expected 8 bytes (u64), it is %d bytes" , name , valueSize )
711+ if valueSize != expected {
712+ 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 )
699713 }
700714 }
701715
@@ -721,7 +735,9 @@ func aggregateMapValues(values []metricValue) []aggregatedMetricValue {
721735 value : value .value ,
722736 }
723737 } else {
724- existing .value += value .value
738+ for i := range existing .value {
739+ existing .value [i ] += value .value [i ]
740+ }
725741 }
726742 }
727743
@@ -785,17 +801,18 @@ func readMapValues(m *libbpfgo.BPFMap, labels []config.Label) ([]metricValue, er
785801 return metricValues , nil
786802}
787803
788- func mapValue (m * libbpfgo.BPFMap , key []byte ) (float64 , error ) {
804+ func mapValue (m * libbpfgo.BPFMap , key []byte ) ([] float64 , error ) {
789805 v , err := m .GetValue (unsafe .Pointer (& key [0 ]))
790806 if err != nil {
791- return 0.0 , err
807+ return [] float64 { 0.0 } , err
792808 }
793809
794810 return decodeValue (v ), nil
795811}
796812
797- func mapValuePerCPU (m * libbpfgo.BPFMap , key []byte ) ([]float64 , error ) {
798- values := []float64 {}
813+ func mapValuePerCPU (m * libbpfgo.BPFMap , key []byte ) ([][]float64 , error ) {
814+ values := [][]float64 {}
815+
799816 size := m .ValueSize ()
800817
801818 value , err := m .GetValue (unsafe .Pointer (& key [0 ]))
@@ -811,8 +828,14 @@ func mapValuePerCPU(m *libbpfgo.BPFMap, key []byte) ([]float64, error) {
811828}
812829
813830// Assuming counter's value type is always u64
814- func decodeValue (value []byte ) float64 {
815- return float64 (util .GetHostByteOrder ().Uint64 (value ))
831+ func decodeValue (value []byte ) []float64 {
832+ values := make ([]float64 , len (value )/ 8 )
833+
834+ for i := range values {
835+ values [i ] = float64 (util .GetHostByteOrder ().Uint64 (value [i * 8 :]))
836+ }
837+
838+ return values
816839}
817840
818841// metricValue is a row in a kernel map
@@ -822,13 +845,13 @@ type metricValue struct {
822845 // labels are decoded from the raw key
823846 labels []string
824847 // value is the kernel map value
825- value float64
848+ value [] float64
826849}
827850
828851// aggregatedMetricValue is a value after aggregation of equal label sets
829852type aggregatedMetricValue struct {
830853 // labels are decoded from the raw key
831854 labels []string
832855 // value is the kernel map value
833- value float64
856+ value [] float64
834857}
0 commit comments