ebpf_exporter
118 строк · 3.1 Кб
1package exporter2
3import (4"log"5"time"6
7"github.com/aquasecurity/libbpfgo"8"github.com/cloudflare/ebpf_exporter/v2/config"9"github.com/cloudflare/ebpf_exporter/v2/decoder"10"github.com/prometheus/client_golang/prometheus"11)
12
13type perfEventArraySink struct {14counterConfig config.Counter15counterVec *prometheus.CounterVec16dropCounter prometheus.Counter17}
18
19func newPerfEventArraySink(decoders *decoder.Set, module *libbpfgo.Module, counterConfig config.Counter) *perfEventArraySink {20var (21receiveCh = make(chan []byte)22lostCh = make(chan uint64)23)24
25sink := &perfEventArraySink{26counterConfig: counterConfig,27dropCounter: createDropCounterForPerfMap(counterConfig),28}29sink.resetCounterVec()30
31perfEventBuf, err := module.InitPerfBuf(counterConfig.Name, receiveCh, lostCh, 1024)32
33if err != nil {34log.Fatalf("Can't init PerfBuf: %s", err)35}36
37go func(sink *perfEventArraySink, receiveCh <-chan []byte) {38for rawBytes := range receiveCh {39// https://github.com/cilium/ebpf/pull/94#discussion_r42582337140// https://lore.kernel.org/patchwork/patch/1244339/41var validDataSize uint42for _, labelConfig := range sink.counterConfig.Labels {43validDataSize += labelConfig.Size44}45
46labelValues, err := decoders.DecodeLabels(rawBytes[:validDataSize], counterConfig.Name, sink.counterConfig.Labels)47if err != nil {48if err == decoder.ErrSkipLabelSet {49continue50}51
52log.Printf("Failed to decode labels: %s", err)53}54
55sink.counterVec.WithLabelValues(labelValues...).Inc()56}57}(sink, receiveCh)58
59go func(sink *perfEventArraySink, lostCh <-chan uint64) {60for droppedEvents := range lostCh {61sink.dropCounter.Add(float64(droppedEvents))62}63}(sink, lostCh)64
65go func(sink *perfEventArraySink) {66flushDuration := time.Hour67if sink.counterConfig.FlushInterval > 0 {68flushDuration = sink.counterConfig.FlushInterval69}70
71ticker := time.NewTicker(flushDuration)72
73for {74<-ticker.C75sink.resetCounterVec()76}77}(sink)78
79perfEventBuf.Poll(300)80
81return sink82}
83
84func (s *perfEventArraySink) Collect(ch chan<- prometheus.Metric) {85s.counterVec.Collect(ch)86}
87
88func (s *perfEventArraySink) Describe(ch chan<- *prometheus.Desc) {89s.counterVec.Describe(ch)90}
91
92func (s *perfEventArraySink) resetCounterVec() {93s.counterVec = createCounterVecForPerfMap(s.counterConfig, labelNamesFromCounterConfig(s.counterConfig))94}
95
96func createCounterVecForPerfMap(counterConfig config.Counter, labelNames []string) *prometheus.CounterVec {97return prometheus.NewCounterVec(prometheus.CounterOpts{98Namespace: prometheusNamespace,99Name: counterConfig.Name,100Help: counterConfig.Help,101}, labelNames)102}
103
104func createDropCounterForPerfMap(counterConfig config.Counter) prometheus.Counter {105return prometheus.NewCounterVec(prometheus.CounterOpts{106Namespace: "dropped_perf_event_map_events",107Name: counterConfig.Name,108Help: "Dropped perf map events",109}, []string{}).WithLabelValues()110}
111
112func labelNamesFromCounterConfig(counterConfig config.Counter) (labelNames []string) {113for _, label := range counterConfig.Labels {114labelNames = append(labelNames, label.Name)115}116
117return118}
119