ebpf_exporter
135 строк · 3.9 Кб
1package config
2
3import (
4"fmt"
5"os"
6"path/filepath"
7"time"
8
9"gopkg.in/yaml.v2"
10)
11
12// Config describes how to configure and extract metrics
13type Config struct {
14Name string `yaml:"name"`
15Metrics Metrics `yaml:"metrics"`
16Kaddrs []string `yaml:"kaddrs"`
17BPFPath string
18}
19
20// Metrics is a collection of metrics attached to a program
21type Metrics struct {
22Counters []Counter `yaml:"counters"`
23Histograms []Histogram `yaml:"histograms"`
24}
25
26// Counter is a metric defining prometheus counter
27type Counter struct {
28Name string `yaml:"name"`
29Help string `yaml:"help"`
30PerfEventArray bool `yaml:"perf_event_array"`
31FlushInterval time.Duration `yaml:"flush_interval"`
32Labels []Label `yaml:"labels"`
33}
34
35// Histogram is a metric defining prometheus histogram
36type Histogram struct {
37Name string `yaml:"name"`
38Help string `yaml:"help"`
39BucketType HistogramBucketType `yaml:"bucket_type"`
40BucketMultiplier float64 `yaml:"bucket_multiplier"`
41BucketMin int `yaml:"bucket_min"`
42BucketMax int `yaml:"bucket_max"`
43BucketKeys []float64 `yaml:"bucket_keys"`
44Labels []Label `yaml:"labels"`
45}
46
47// Label defines how to decode an element from eBPF map key
48// with the list of decoders
49type Label struct {
50Name string `yaml:"name"`
51Size uint `yaml:"size"`
52Decoders []Decoder `yaml:"decoders"`
53}
54
55// Decoder defines how to decode value
56type Decoder struct {
57Name string `yaml:"name"`
58StaticMap map[string]string `yaml:"static_map"`
59Regexps []string `yaml:"regexps"`
60AllowUnknown bool `yaml:"allow_unknown"`
61}
62
63// HistogramBucketType is an enum to define how to interpret histogram
64type HistogramBucketType string
65
66const (
67// HistogramBucketExp2 means histograms with power-of-two keys
68HistogramBucketExp2 HistogramBucketType = "exp2"
69// HistogramBucketExp2WithZero means histograms with power-of-two keys where the first key is for zero
70HistogramBucketExp2WithZero HistogramBucketType = "exp2zero"
71// HistogramBucketLinear means histogram with linear keys
72HistogramBucketLinear HistogramBucketType = "linear"
73// HistogramBucketFixed means histogram with fixed user-defined keys
74HistogramBucketFixed HistogramBucketType = "fixed"
75)
76
77// ParseConfigs parses the named configs from the provided configs directory
78func ParseConfigs(dir string, names []string) ([]Config, error) {
79configs := make([]Config, len(names))
80
81for i, name := range names {
82path := filepath.Join(dir, fmt.Sprintf("%s.yaml", name))
83
84f, err := os.Open(path)
85if err != nil {
86return nil, fmt.Errorf("error opening %q for config %q: %v", path, name, err)
87}
88
89defer f.Close()
90
91err = yaml.NewDecoder(f).Decode(&configs[i])
92if err != nil {
93return nil, fmt.Errorf("error parsing %q for config %q: %v", path, name, err)
94}
95
96configs[i].Name = name
97
98err = validateConfig(&configs[i])
99if err != nil {
100return nil, fmt.Errorf("error validating config: %v", err)
101}
102
103configs[i].BPFPath = filepath.Join(dir, fmt.Sprintf("%s.bpf.o", name))
104}
105
106return configs, nil
107}
108
109func validateConfig(cfg *Config) error {
110if cfg.Metrics.Counters == nil && cfg.Metrics.Histograms == nil {
111return fmt.Errorf("metrics are not defined for config %q", cfg.Name)
112}
113
114for _, counter := range cfg.Metrics.Counters {
115if counter.Name == "" {
116return fmt.Errorf("counter %q in config %q lacks name", counter.Name, cfg.Name)
117}
118
119if counter.Help == "" {
120return fmt.Errorf("counter %q in config %q lacks help", counter.Name, cfg.Name)
121}
122}
123
124for _, histogram := range cfg.Metrics.Histograms {
125if histogram.Name == "" {
126return fmt.Errorf("histogram %q in config %q lacks name", histogram.Name, cfg.Name)
127}
128
129if histogram.Help == "" {
130return fmt.Errorf("histogram %q in config %q lacks help", histogram.Name, cfg.Name)
131}
132}
133
134return nil
135}
136