1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
package main
import (
"fmt"
"strings"
"github.com/prometheus/prometheus/model/labels"
"github.com/prometheus/prometheus/model/relabel"
)
type Part struct{
Name string
Transforms []Transform
Source Source
}
func (self Part) Get() (MetricFamilies, error){
mf, err := self.Source.Get()
if err != nil{
return MetricFamilies{}, fmt.Errorf("while reading source: %w", err)
}
for _, t := range self.Transforms{
mf, err = t.Process(mf)
if err != nil{
return MetricFamilies{},
fmt.Errorf("while transforming input: %w", err)
}
}
return mf, nil
}
func PartFromArg(arg string, re map[string]*[]*relabel.Config) (Part, error){
tf := []Transform{}
namef := func(n string)string{ return n }
at := strings.Index(arg, "@")
if at >= 0 && strings.IndexAny(arg[0:at], "=,:") < 0{
name := arg[0:at]
namef = func(string)string{ return name }
arg = arg[at+1:]
}
for true{
sp := strings.IndexAny(arg, "=,:")
if sp < 0{
return Part{}, fmt.Errorf("Unexpected end of part spec")
}else if arg[sp] == ':'{
if arg[0:sp] == "http" || arg[0:sp] == "https"{
s, err := NewHttpSource(arg)
if err != nil{
return Part{}, err
}
return Part{
Name: namef(arg),
Transforms: tf,
Source: s,
}, nil
}else if arg[0:sp] == "file"{
fn := arg[sp+1:]
if strings.HasPrefix(fn, "//"){
fn = fn[2:]
}
return Part{
Name: namef(fn),
Transforms: tf,
Source: FileSource(fn),
}, nil
}else{
return Part{}, fmt.Errorf("Unknown protocol %q", arg[0:sp])
}
}else if arg[sp] == '='{
vstop := strings.Index(arg, ",")
if vstop < 0{
return Part{}, fmt.Errorf("Unexpected end of part spec")
}
tf = append(tf, SetLabel{
Name: arg[0:sp],
Val: arg[sp+1:vstop],
})
arg = arg[vstop+1:]
}else{ // arg[sp] == ','
r := re[arg[0:sp]]
if r == nil{
return Part{}, fmt.Errorf("Undefined relabel %q", arg[0:sp])
}
tf = append(tf, Relabel(*r))
arg = arg[sp+1:]
}
}
return Part{}, fmt.Errorf("impossible branch")
}
type Parts []Part
func (self Parts) Get() (MetricFamilies, error){
ret := EmptyMetricFamilies()
for _, part := range self{
p, err := part.Get()
if err != nil{
logger.Error(fmt.Sprintf("In %q: %s", part.Name, err.Error()))
}else{
ret.Merge(p)
}
}
return ret, nil
}
func PartsFromArgs(
args []string,
re map[string]*[]*relabel.Config,
) (Parts, error){
ret := Parts([]Part{})
for _, arg := range args{
p, err := PartFromArg(arg, re)
if err != nil{
return []Part{}, err
}
ret = append(ret, p)
}
return ret, nil
}
type Transform interface{
Process(target MetricFamilies) (MetricFamilies, error)
}
type Relabel []*relabel.Config
func (self Relabel) Process(target MetricFamilies) (MetricFamilies, error){
f := func(l labels.Labels) (labels.Labels, bool){
return relabel.Process(l, self...)
}
return target.Relabel(f), nil
}
type SetLabel struct{
Name string
Val string
}
func (self SetLabel) Process(target MetricFamilies) (MetricFamilies, error){
f := func(l labels.Labels) (labels.Labels, bool){
l = l.Copy()
for _, ll := range l{
if ll.Name == self.Name{
ll.Value = self.Val
goto FIN
}
}
l = append(l, labels.Label{
Name: self.Name,
Value: self.Val,
})
FIN:
return l, true
}
return target.Relabel(f), nil
}
|