-
Notifications
You must be signed in to change notification settings - Fork 3
/
marshall_prometheus.go
89 lines (76 loc) · 2.49 KB
/
marshall_prometheus.go
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
package bitflow
import (
"fmt"
"io"
"strings"
)
// PrometheusMarshaller marshals Headers and Samples to the prometheus exposition format
type PrometheusMarshaller struct {
}
// String implements the Marshaller interface.
func (PrometheusMarshaller) String() string {
return "prometheus"
}
// ShouldCloseAfterFirstSample defines that prometheus streams should close after first sent sample
func (PrometheusMarshaller) ShouldCloseAfterFirstSample() bool {
return true
}
// WriteHeader implements the Marshaller interface. It is empty, because
// the prometheus exposition format doesn't need one
func (PrometheusMarshaller) WriteHeader(header *Header, withTags bool, output io.Writer) error {
return nil
}
// WriteSample implements the Marshaller interface. See the PrometheusMarshaller godoc
// for information about the format.
func (m PrometheusMarshaller) WriteSample(sample *Sample, header *Header, withTags bool, writer io.Writer) error {
for i, value := range sample.Values {
line := fmt.Sprintf("%s\t%f\n",
m.renderMetricLine(header.Fields[i], "all"),
value,
)
_, err := writer.Write([]byte(line))
if err != nil {
return err
}
}
return nil
}
// renderMetricLine retrieves a sample field and renders a proper prometheus metric out of it
func (m PrometheusMarshaller) renderMetricLine(line string, group string) string {
defaultLine := fmt.Sprintf(
"%s{group=\"%s\"}",
m.stripDashes(strings.Replace(line, "/", "_", -1)),
group,
)
parts := strings.Split(line, "/")
numParts := len(parts)
if numParts == 1 {
return defaultLine
}
switch parts[0] {
case "disk-io", "disk-usage":
return fmt.Sprintf("%s_%s{group=\"%s\"}", m.stripDashes(parts[0]), parts[2], group)
case "disk":
return fmt.Sprintf("disk_io_%s{group=\"%s\"}", parts[1], group)
case "load":
return fmt.Sprintf("load{minutes=\"%s\"}", parts[1])
case "mem":
return fmt.Sprintf("mem_%s{group=\"%s\"}", parts[1], group)
case "net-io":
if numParts == 2 {
return fmt.Sprintf("%s_%s{group=\"%s\"}", m.stripDashes(parts[0]), parts[1], group)
} else {
nic := parts[2]
return fmt.Sprintf("%s_%s{group=\"%s\", nic=\"%s\"}", m.stripDashes(parts[0]), parts[3], group, nic)
}
case "net-proto":
return fmt.Sprintf("%s{group=\"%s\"}", m.stripDashes(strings.Join(parts, "_")), group)
case "proc":
newParts := parts[2:]
return m.renderMetricLine(strings.Join(newParts, "/"), parts[1])
}
return defaultLine
}
func (PrometheusMarshaller) stripDashes(s string) string {
return strings.Replace(s, "-", "_", -1)
}