aboutsummaryrefslogtreecommitdiff
path: root/collector/netclass_linux.go
diff options
context:
space:
mode:
authorJan Klat <jenik@klatys.cz>2018-07-16 15:08:18 +0200
committerJohannes 'fish' Ziemke <github@freigeist.org>2018-07-16 15:08:18 +0200
commitc4102f117584f92e18e9612d9a9eecd0815e89bd (patch)
tree06e8fbb27352e471bfece0c5a7e9543745f2c3cb /collector/netclass_linux.go
parent09b4305090a6af1e69c528539fba63fc5ff781c6 (diff)
downloadprometheus_node_collector-c4102f117584f92e18e9612d9a9eecd0815e89bd.tar.bz2
prometheus_node_collector-c4102f117584f92e18e9612d9a9eecd0815e89bd.tar.xz
prometheus_node_collector-c4102f117584f92e18e9612d9a9eecd0815e89bd.zip
Add sys/class/net parsing from procfs and expose its metrics (#851)
* add sys/class/net parsing from procfs and expose its metrics Signed-off-by: Jan Klat <jenik@klatys.cz> * change code to use int pointers per procfs change, move netclass to separate collector, change metric naming Signed-off-by: Jan Klat <jenik@klatys.cz> * bump year in licence, remove redundant newline, correct fixtures Signed-off-by: Jan Klat <jenik@klatys.cz> * fix style Signed-off-by: Jan Klat <jenik@klatys.cz> * change carrier changes to counter type Signed-off-by: Jan Klat <jenik@klatys.cz> * fix e2e output Signed-off-by: Jan Klat <jenik@klatys.cz> * add fixtures Signed-off-by: Jan Klat <jenik@klatys.cz> * update vendor, use fixtures correctly Signed-off-by: Jan Klat <jenik@klatys.cz> * change fixtures (device in /sys/class/net should be symlinked) Signed-off-by: Jan Klat <jenik@klatys.cz> * correct fixtures for 64k page, updated readme Signed-off-by: Jan Klat <jenik@klatys.cz>
Diffstat (limited to 'collector/netclass_linux.go')
-rw-r--r--collector/netclass_linux.go173
1 files changed, 173 insertions, 0 deletions
diff --git a/collector/netclass_linux.go b/collector/netclass_linux.go
new file mode 100644
index 0000000..a71f302
--- /dev/null
+++ b/collector/netclass_linux.go
@@ -0,0 +1,173 @@
1// Copyright 2018 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 !nonetclass
15// +build linux
16
17package collector
18
19import (
20 "fmt"
21 "regexp"
22
23 "github.com/prometheus/client_golang/prometheus"
24 "github.com/prometheus/procfs/sysfs"
25 "gopkg.in/alecthomas/kingpin.v2"
26)
27
28var (
29 netclassIgnoredDevices = kingpin.Flag("collector.netclass.ignored-devices", "Regexp of net devices to ignore for netclass collector.").Default("^$").String()
30)
31
32type netClassCollector struct {
33 subsystem string
34 ignoredDevicesPattern *regexp.Regexp
35 metricDescs map[string]*prometheus.Desc
36}
37
38func init() {
39 registerCollector("netclass", defaultEnabled, NewNetClassCollector)
40}
41
42// NewNetClassCollector returns a new Collector exposing network class stats.
43func NewNetClassCollector() (Collector, error) {
44 pattern := regexp.MustCompile(*netclassIgnoredDevices)
45 return &netClassCollector{
46 subsystem: "network",
47 ignoredDevicesPattern: pattern,
48 metricDescs: map[string]*prometheus.Desc{},
49 }, nil
50}
51
52func (c *netClassCollector) Update(ch chan<- prometheus.Metric) error {
53 netClass, err := getNetClassInfo(c.ignoredDevicesPattern)
54 if err != nil {
55 return fmt.Errorf("could not get net class info: %s", err)
56 }
57 for _, ifaceInfo := range netClass {
58 upDesc := prometheus.NewDesc(
59 prometheus.BuildFQName(namespace, c.subsystem, "up"),
60 "Valid operstate for interface.",
61 []string{"interface", "address", "broadcast", "duplex", "operstate", "ifalias"},
62 nil,
63 )
64 upValue := 0.0
65 if ifaceInfo.OperState == "up" {
66 upValue = 1.0
67 }
68
69 ch <- prometheus.MustNewConstMetric(upDesc, prometheus.GaugeValue, upValue, ifaceInfo.Name, ifaceInfo.Address, ifaceInfo.Broadcast, ifaceInfo.Duplex, ifaceInfo.OperState, ifaceInfo.IfAlias)
70
71 if ifaceInfo.AddrAssignType != nil {
72 pushMetric(ch, c.subsystem, "address_assign_type", *ifaceInfo.AddrAssignType, ifaceInfo.Name, prometheus.GaugeValue)
73 }
74
75 if ifaceInfo.Carrier != nil {
76 pushMetric(ch, c.subsystem, "carrier", *ifaceInfo.Carrier, ifaceInfo.Name, prometheus.GaugeValue)
77 }
78
79 if ifaceInfo.CarrierChanges != nil {
80 pushMetric(ch, c.subsystem, "carrier_changes_total", *ifaceInfo.CarrierChanges, ifaceInfo.Name, prometheus.CounterValue)
81 }
82
83 if ifaceInfo.CarrierUpCount != nil {
84 pushMetric(ch, c.subsystem, "carrier_up_changes_total", *ifaceInfo.CarrierUpCount, ifaceInfo.Name, prometheus.CounterValue)
85 }
86
87 if ifaceInfo.CarrierDownCount != nil {
88 pushMetric(ch, c.subsystem, "carrier_down_changes_total", *ifaceInfo.CarrierDownCount, ifaceInfo.Name, prometheus.CounterValue)
89 }
90
91 if ifaceInfo.DevID != nil {
92 pushMetric(ch, c.subsystem, "device_id", *ifaceInfo.DevID, ifaceInfo.Name, prometheus.GaugeValue)
93 }
94
95 if ifaceInfo.Dormant != nil {
96 pushMetric(ch, c.subsystem, "dormant", *ifaceInfo.Dormant, ifaceInfo.Name, prometheus.GaugeValue)
97 }
98
99 if ifaceInfo.Flags != nil {
100 pushMetric(ch, c.subsystem, "flags", *ifaceInfo.Flags, ifaceInfo.Name, prometheus.GaugeValue)
101 }
102
103 if ifaceInfo.IfIndex != nil {
104 pushMetric(ch, c.subsystem, "iface_id", *ifaceInfo.IfIndex, ifaceInfo.Name, prometheus.GaugeValue)
105 }
106
107 if ifaceInfo.IfLink != nil {
108 pushMetric(ch, c.subsystem, "iface_link", *ifaceInfo.IfLink, ifaceInfo.Name, prometheus.GaugeValue)
109 }
110
111 if ifaceInfo.LinkMode != nil {
112 pushMetric(ch, c.subsystem, "iface_link_mode", *ifaceInfo.LinkMode, ifaceInfo.Name, prometheus.GaugeValue)
113 }
114
115 if ifaceInfo.MTU != nil {
116 pushMetric(ch, c.subsystem, "mtu_bytes", *ifaceInfo.MTU, ifaceInfo.Name, prometheus.GaugeValue)
117 }
118
119 if ifaceInfo.NameAssignType != nil {
120 pushMetric(ch, c.subsystem, "name_assign_type", *ifaceInfo.NameAssignType, ifaceInfo.Name, prometheus.GaugeValue)
121 }
122
123 if ifaceInfo.NetDevGroup != nil {
124 pushMetric(ch, c.subsystem, "net_dev_group", *ifaceInfo.NetDevGroup, ifaceInfo.Name, prometheus.GaugeValue)
125 }
126
127 if ifaceInfo.Speed != nil {
128 speedBytes := int64(*ifaceInfo.Speed / 8 * 1000 * 1000)
129 pushMetric(ch, c.subsystem, "speed_bytes", speedBytes, ifaceInfo.Name, prometheus.GaugeValue)
130 }
131
132 if ifaceInfo.TxQueueLen != nil {
133 pushMetric(ch, c.subsystem, "transmit_queue_length", *ifaceInfo.TxQueueLen, ifaceInfo.Name, prometheus.GaugeValue)
134 }
135
136 if ifaceInfo.Type != nil {
137 pushMetric(ch, c.subsystem, "protocol_type", *ifaceInfo.Type, ifaceInfo.Name, prometheus.GaugeValue)
138 }
139 }
140
141 return nil
142}
143
144func pushMetric(ch chan<- prometheus.Metric, subsystem string, name string, value int64, ifaceName string, valueType prometheus.ValueType) {
145 fieldDesc := prometheus.NewDesc(
146 prometheus.BuildFQName(namespace, subsystem, name),
147 fmt.Sprintf("%s value of /sys/class/net/<iface>.", name),
148 []string{"interface"},
149 nil,
150 )
151
152 ch <- prometheus.MustNewConstMetric(fieldDesc, valueType, float64(value), ifaceName)
153}
154
155func getNetClassInfo(ignore *regexp.Regexp) (sysfs.NetClass, error) {
156 fs, err := sysfs.NewFS(*sysPath)
157 if err != nil {
158 return nil, err
159 }
160 netClass, err := fs.NewNetClass()
161
162 if err != nil {
163 return netClass, fmt.Errorf("error obtaining net class info: %s", err)
164 }
165
166 for device := range netClass {
167 if ignore.MatchString(device) {
168 delete(netClass, device)
169 }
170 }
171
172 return netClass, nil
173}