diff options
author | Silke Hofstra <silkeh@users.noreply.github.com> | 2020-02-19 15:48:51 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-02-19 15:48:51 +0100 |
commit | 8faa843fc42260cabb749cc9eb8886c191f28f7c (patch) | |
tree | 175a091379d2bb4b419a5b917647abfb40a00094 /collector/btrfs_linux.go | |
parent | ca1ac435eae5182b2795e14caa80713a7440687b (diff) | |
download | prometheus_node_collector-8faa843fc42260cabb749cc9eb8886c191f28f7c.tar.bz2 prometheus_node_collector-8faa843fc42260cabb749cc9eb8886c191f28f7c.tar.xz prometheus_node_collector-8faa843fc42260cabb749cc9eb8886c191f28f7c.zip |
Add Btrfs collector (#1512)
* Add procfs/btrfs to vendor folder
* Add Btrfs collector
Resolves #1100
Signed-off-by: Silke Hofstra <silke@slxh.eu>
Diffstat (limited to 'collector/btrfs_linux.go')
-rw-r--r-- | collector/btrfs_linux.go | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/collector/btrfs_linux.go b/collector/btrfs_linux.go new file mode 100644 index 0000000..2336e65 --- /dev/null +++ b/collector/btrfs_linux.go | |||
@@ -0,0 +1,189 @@ | |||
1 | // Copyright 2019 The Prometheus Authors | ||
2 | // Licensed under the Apache License, Version 2.0 (the "License"); | ||
3 | // you may not use this file except in compliance with the License. | ||
4 | // You may obtain a copy of the License at | ||
5 | // | ||
6 | // http://www.apache.org/licenses/LICENSE-2.0 | ||
7 | // | ||
8 | // Unless required by applicable law or agreed to in writing, software | ||
9 | // distributed under the License is distributed on an "AS IS" BASIS, | ||
10 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
11 | // See the License for the specific language governing permissions and | ||
12 | // limitations under the License. | ||
13 | |||
14 | // +build !nobtrfs | ||
15 | |||
16 | package collector | ||
17 | |||
18 | import ( | ||
19 | "fmt" | ||
20 | |||
21 | "github.com/go-kit/kit/log" | ||
22 | "github.com/prometheus/client_golang/prometheus" | ||
23 | "github.com/prometheus/procfs/btrfs" | ||
24 | ) | ||
25 | |||
26 | // A btrfsCollector is a Collector which gathers metrics from Btrfs filesystems. | ||
27 | type btrfsCollector struct { | ||
28 | fs btrfs.FS | ||
29 | logger log.Logger | ||
30 | } | ||
31 | |||
32 | func init() { | ||
33 | registerCollector("btrfs", defaultEnabled, NewBtrfsCollector) | ||
34 | } | ||
35 | |||
36 | // NewBtrfsCollector returns a new Collector exposing Btrfs statistics. | ||
37 | func NewBtrfsCollector(logger log.Logger) (Collector, error) { | ||
38 | fs, err := btrfs.NewFS(*sysPath) | ||
39 | if err != nil { | ||
40 | return nil, fmt.Errorf("failed to open sysfs: %v", err) | ||
41 | } | ||
42 | |||
43 | return &btrfsCollector{ | ||
44 | fs: fs, | ||
45 | logger: logger, | ||
46 | }, nil | ||
47 | } | ||
48 | |||
49 | // Update retrieves and exports Btrfs statistics. | ||
50 | // It implements Collector. | ||
51 | func (c *btrfsCollector) Update(ch chan<- prometheus.Metric) error { | ||
52 | stats, err := c.fs.Stats() | ||
53 | if err != nil { | ||
54 | return fmt.Errorf("failed to retrieve Btrfs stats: %v", err) | ||
55 | } | ||
56 | |||
57 | for _, s := range stats { | ||
58 | c.updateBtrfsStats(ch, s) | ||
59 | } | ||
60 | |||
61 | return nil | ||
62 | } | ||
63 | |||
64 | // btrfsMetric represents a single Btrfs metric that is converted into a Prometheus Metric. | ||
65 | type btrfsMetric struct { | ||
66 | name string | ||
67 | desc string | ||
68 | value float64 | ||
69 | extraLabel []string | ||
70 | extraLabelValue []string | ||
71 | } | ||
72 | |||
73 | // updateBtrfsStats collects statistics for one bcache ID. | ||
74 | func (c *btrfsCollector) updateBtrfsStats(ch chan<- prometheus.Metric, s *btrfs.Stats) { | ||
75 | const subsystem = "btrfs" | ||
76 | |||
77 | // Basic information about the filesystem. | ||
78 | devLabels := []string{"uuid"} | ||
79 | |||
80 | // Retrieve the metrics. | ||
81 | metrics := c.getMetrics(s) | ||
82 | |||
83 | // Convert all gathered metrics to Prometheus Metrics and add to channel. | ||
84 | for _, m := range metrics { | ||
85 | labels := append(devLabels, m.extraLabel...) | ||
86 | |||
87 | desc := prometheus.NewDesc( | ||
88 | prometheus.BuildFQName(namespace, subsystem, m.name), | ||
89 | m.desc, | ||
90 | labels, | ||
91 | nil, | ||
92 | ) | ||
93 | |||
94 | labelValues := []string{s.UUID} | ||
95 | if len(m.extraLabelValue) > 0 { | ||
96 | labelValues = append(labelValues, m.extraLabelValue...) | ||
97 | } | ||
98 | |||
99 | ch <- prometheus.MustNewConstMetric( | ||
100 | desc, | ||
101 | prometheus.GaugeValue, | ||
102 | m.value, | ||
103 | labelValues..., | ||
104 | ) | ||
105 | } | ||
106 | } | ||
107 | |||
108 | // getMetrics returns metrics for the given Btrfs statistics. | ||
109 | func (c *btrfsCollector) getMetrics(s *btrfs.Stats) []btrfsMetric { | ||
110 | metrics := []btrfsMetric{ | ||
111 | { | ||
112 | name: "info", | ||
113 | desc: "Filesystem information", | ||
114 | value: 1, | ||
115 | extraLabel: []string{"label"}, | ||
116 | extraLabelValue: []string{s.Label}, | ||
117 | }, | ||
118 | { | ||
119 | name: "global_rsv_size_bytes", | ||
120 | desc: "Size of global reserve.", | ||
121 | value: float64(s.Allocation.GlobalRsvSize), | ||
122 | }, | ||
123 | } | ||
124 | |||
125 | // Information about devices. | ||
126 | for n, dev := range s.Devices { | ||
127 | metrics = append(metrics, btrfsMetric{ | ||
128 | name: "device_size_bytes", | ||
129 | desc: "Size of a device that is part of the filesystem.", | ||
130 | value: float64(dev.Size), | ||
131 | extraLabel: []string{"device"}, | ||
132 | extraLabelValue: []string{n}, | ||
133 | }) | ||
134 | } | ||
135 | |||
136 | // Information about data, metadata and system data. | ||
137 | metrics = append(metrics, c.getAllocationStats("data", s.Allocation.Data)...) | ||
138 | metrics = append(metrics, c.getAllocationStats("metadata", s.Allocation.Metadata)...) | ||
139 | metrics = append(metrics, c.getAllocationStats("system", s.Allocation.System)...) | ||
140 | |||
141 | return metrics | ||
142 | } | ||
143 | |||
144 | // getAllocationStats returns allocation metrics for the given Btrfs Allocation statistics. | ||
145 | func (c *btrfsCollector) getAllocationStats(a string, s *btrfs.AllocationStats) []btrfsMetric { | ||
146 | metrics := []btrfsMetric{ | ||
147 | { | ||
148 | name: "reserved_bytes", | ||
149 | desc: "Amount of space reserved for a data type", | ||
150 | value: float64(s.ReservedBytes), | ||
151 | extraLabel: []string{"block_group_type"}, | ||
152 | extraLabelValue: []string{a}, | ||
153 | }, | ||
154 | } | ||
155 | |||
156 | // Add all layout statistics. | ||
157 | for layout, stats := range s.Layouts { | ||
158 | metrics = append(metrics, c.getLayoutStats(a, layout, stats)...) | ||
159 | } | ||
160 | |||
161 | return metrics | ||
162 | } | ||
163 | |||
164 | // getLayoutStats returns metrics for a data layout. | ||
165 | func (c *btrfsCollector) getLayoutStats(a, l string, s *btrfs.LayoutUsage) []btrfsMetric { | ||
166 | return []btrfsMetric{ | ||
167 | { | ||
168 | name: "used_bytes", | ||
169 | desc: "Amount of used space by a layout/data type", | ||
170 | value: float64(s.UsedBytes), | ||
171 | extraLabel: []string{"block_group_type", "mode"}, | ||
172 | extraLabelValue: []string{a, l}, | ||
173 | }, | ||
174 | { | ||
175 | name: "size_bytes", | ||
176 | desc: "Amount of space allocated for a layout/data type", | ||
177 | value: float64(s.TotalBytes), | ||
178 | extraLabel: []string{"block_group_type", "mode"}, | ||
179 | extraLabelValue: []string{a, l}, | ||
180 | }, | ||
181 | { | ||
182 | name: "allocation_ratio", | ||
183 | desc: "Data allocation ratio for a layout/data type", | ||
184 | value: s.Ratio, | ||
185 | extraLabel: []string{"block_group_type", "mode"}, | ||
186 | extraLabelValue: []string{a, l}, | ||
187 | }, | ||
188 | } | ||
189 | } | ||