Skip to content

Commit ae13628

Browse files
authored
feat: Add support for managed switches (#215)
* feat: Add support for managed switches * fix: update to go 1.18
1 parent 4f2d9be commit ae13628

File tree

5 files changed

+2475
-1
lines changed

5 files changed

+2475
-1
lines changed

Diff for: README.md

+32-1
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,37 @@ Per-VDOM, managed access point and interface:
215215
* `fortigate_wifi_managed_ap_interface_rx_dropped_packets_total`
216216
* `fortigate_wifi_managed_ap_interface_tx_dropped_packets_total`
217217

218+
Per-VDOM, managed switch and interface:
219+
* _Switch/ManagedSwitch_
220+
* `fortigate_managed_switch_collisions_total`
221+
* `fortigate_managed_switch_crc_alignments_total`
222+
* `fortigate_managed_switch_fragments_total`
223+
* `fortigate_managed_switch_info`
224+
* `fortigate_managed_switch_jabbers_total`
225+
* `fortigate_managed_switch_l3_packets_total`
226+
* `fortigate_managed_switch_max_poe_budget_watt`
227+
* `fortigate_managed_switch_port_info`
228+
* `fortigate_managed_switch_port_power_status`
229+
* `fortigate_managed_switch_port_power_watt`
230+
* `fortigate_managed_switch_port_status`
231+
* `fortigate_managed_switch_rx_bcast_packets_total`
232+
* `fortigate_managed_switch_rx_bytes_total`
233+
* `fortigate_managed_switch_rx_drops_total`
234+
* `fortigate_managed_switch_rx_errors_total`
235+
* `fortigate_managed_switch_rx_mcast_packets_total`
236+
* `fortigate_managed_switch_rx_oversize_total`
237+
* `fortigate_managed_switch_rx_packets_total`
238+
* `fortigate_managed_switch_rx_ucast_packets_total`
239+
* `fortigate_managed_switch_tx_bcast_packets_total`
240+
* `fortigate_managed_switch_tx_bytes_total`
241+
* `fortigate_managed_switch_tx_drops_total`
242+
* `fortigate_managed_switch_tx_errors_total`
243+
* `fortigate_managed_switch_tx_mcast_packets_total`
244+
* `fortigate_managed_switch_tx_oversize_total`
245+
* `fortigate_managed_switch_tx_packets_total`
246+
* `fortigate_managed_switch_tx_ucast_packets_total`
247+
* `fortigate_managed_switch_under_size_total`
248+
218249
## Usage
219250

220251
Example:
@@ -342,7 +373,7 @@ To improve security, limit permissions to required ones only (least privilege pr
342373
|Wifi/APStatus | wifi |api/v2/monitor/wifi/ap_status |
343374
|Wifi/Clients | wifi |api/v2/monitor/wifi/client |
344375
|Wifi/ManagedAP | wifi |api/v2/monitor/wifi/managed_ap |
345-
376+
|Switch/ManagedSwitch | switch |api/v2/monitor/switch-controller/managed-switch|
346377
If you omit to grant some of these permissions you will receive log messages warning about
347378
403 errors and relevant metrics will be unavailable, but other metrics will still work.
348379
If you do not need some probes to be run, do not grant permission for them and use `include/exclude` feature (see `Usage` section).

Diff for: pkg/probe/managed_switch.go

+274
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
package probe
2+
3+
import (
4+
"log"
5+
"strconv"
6+
7+
"github.com/bluecmd/fortigate_exporter/pkg/http"
8+
"github.com/prometheus/client_golang/prometheus"
9+
)
10+
11+
func probeManagedSwitch(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) {
12+
var (
13+
managedSwitchInfo = prometheus.NewDesc(
14+
"fortigate_managed_switch_info",
15+
"Infos about a managed switch",
16+
[]string{"vdom", "switch_name", "os_version", "serial", "state", "status"}, nil,
17+
)
18+
managedSwitchMaxPoeBudget = prometheus.NewDesc(
19+
"fortigate_managed_switch_max_poe_budget_watt",
20+
"Max poe budget watt",
21+
[]string{"vdom", "switch_name"}, nil,
22+
)
23+
portInfo = prometheus.NewDesc(
24+
"fortigate_managed_switch_port_info",
25+
"Infos about a switch port",
26+
[]string{"vdom", "switch_name", "port", "vlan", "duplex", "status", "poe_status", "poe_capable"}, nil,
27+
)
28+
29+
portStatus = prometheus.NewDesc(
30+
"fortigate_managed_switch_port_status",
31+
"Port status up=1 down=0",
32+
[]string{"vdom", "switch_name", "port"}, nil,
33+
)
34+
portPower = prometheus.NewDesc(
35+
"fortigate_managed_switch_port_power_watt",
36+
"Port power in watt",
37+
[]string{"vdom", "switch_name", "port"}, nil,
38+
)
39+
portPowerStatus = prometheus.NewDesc(
40+
"fortigate_managed_switch_port_power_status",
41+
"Port power status",
42+
[]string{"vdom", "switch_name", "port"}, nil,
43+
)
44+
45+
// Port stats
46+
portRxBytes = prometheus.NewDesc(
47+
"fortigate_managed_switch_rx_bytes_total",
48+
"Total number of received bytes",
49+
[]string{"vdom", "switch_name", "port"}, nil,
50+
)
51+
52+
portRxPackets = prometheus.NewDesc(
53+
"fortigate_managed_switch_rx_packets_total",
54+
"Total number of received packets",
55+
[]string{"vdom", "switch_name", "port"}, nil,
56+
)
57+
58+
portRxUcast = prometheus.NewDesc(
59+
"fortigate_managed_switch_rx_ucast_packets_total",
60+
"Total number of received unicast packets",
61+
[]string{"vdom", "switch_name", "port"}, nil,
62+
)
63+
64+
portRxMcast = prometheus.NewDesc(
65+
"fortigate_managed_switch_rx_mcast_packets_total",
66+
"Total number of received multicast packets",
67+
[]string{"vdom", "switch_name", "port"}, nil,
68+
)
69+
portRxBcast = prometheus.NewDesc(
70+
"fortigate_managed_switch_rx_bcast_packets_total",
71+
"Total number of received broadcast packets",
72+
[]string{"vdom", "switch_name", "port"}, nil,
73+
)
74+
portRxErrors = prometheus.NewDesc(
75+
"fortigate_managed_switch_rx_errors_total",
76+
"Total number of received errors",
77+
[]string{"vdom", "switch_name", "port"}, nil,
78+
)
79+
portRxDrops = prometheus.NewDesc(
80+
"fortigate_managed_switch_rx_drops_total",
81+
"Total number of received drops",
82+
[]string{"vdom", "switch_name", "port"}, nil,
83+
)
84+
portRxOversize = prometheus.NewDesc(
85+
"fortigate_managed_switch_rx_oversize_total",
86+
"Total number of received oversize",
87+
[]string{"vdom", "switch_name", "port"}, nil,
88+
)
89+
90+
portTxBytes = prometheus.NewDesc(
91+
"fortigate_managed_switch_tx_bytes_total",
92+
"Total number of transmitted bytes",
93+
[]string{"vdom", "switch_name", "port"}, nil,
94+
)
95+
portTxPackets = prometheus.NewDesc(
96+
"fortigate_managed_switch_tx_packets_total",
97+
"Total number of transmitted packets",
98+
[]string{"vdom", "switch_name", "port"}, nil,
99+
)
100+
101+
portTxUcast = prometheus.NewDesc(
102+
"fortigate_managed_switch_tx_ucast_packets_total",
103+
"Total number of transmitted unicast packets",
104+
[]string{"vdom", "switch_name", "port"}, nil,
105+
)
106+
107+
portTxMcast = prometheus.NewDesc(
108+
"fortigate_managed_switch_tx_mcast_packets_total",
109+
"Total number of transmitted multicast packets",
110+
[]string{"vdom", "switch_name", "port"}, nil,
111+
)
112+
portTxBcast = prometheus.NewDesc(
113+
"fortigate_managed_switch_tx_bcast_packets_total",
114+
"Total number of transmitted broadcast packets",
115+
[]string{"vdom", "switch_name", "port"}, nil,
116+
)
117+
portTxErrors = prometheus.NewDesc(
118+
"fortigate_managed_switch_tx_errors_total",
119+
"Total number of transmitted errors",
120+
[]string{"vdom", "switch_name", "port"}, nil,
121+
)
122+
portTxDrops = prometheus.NewDesc(
123+
"fortigate_managed_switch_tx_drops_total",
124+
"Total number of transmitted drops",
125+
[]string{"vdom", "switch_name", "port"}, nil,
126+
)
127+
portTxOversize = prometheus.NewDesc(
128+
"fortigate_managed_switch_tx_oversize_total",
129+
"Total number of transmitted oversize",
130+
[]string{"vdom", "switch_name", "port"}, nil,
131+
)
132+
133+
portUndersize = prometheus.NewDesc(
134+
"fortigate_managed_switch_under_size_total",
135+
"Total number of under size",
136+
[]string{"vdom", "switch_name", "port"}, nil,
137+
)
138+
portFragments = prometheus.NewDesc(
139+
"fortigate_managed_switch_fragments_total",
140+
"Total number of fragments",
141+
[]string{"vdom", "switch_name", "port"}, nil,
142+
)
143+
portJabbers = prometheus.NewDesc(
144+
"fortigate_managed_switch_jabbers_total",
145+
"Total number of jabbers",
146+
[]string{"vdom", "switch_name", "port"}, nil,
147+
)
148+
portCollisions = prometheus.NewDesc(
149+
"fortigate_managed_switch_collisions_total",
150+
"Total number of collisions",
151+
[]string{"vdom", "switch_name", "port"}, nil,
152+
)
153+
portCrcAlignments = prometheus.NewDesc(
154+
"fortigate_managed_switch_crc_alignments_total",
155+
"Total number of crc alignments",
156+
[]string{"vdom", "switch_name", "port"}, nil,
157+
)
158+
portL3Packets = prometheus.NewDesc(
159+
"fortigate_managed_switch_l3_packets_total",
160+
"Total number of l3 packets",
161+
[]string{"vdom", "switch_name", "port"}, nil,
162+
)
163+
164+
// Port
165+
166+
)
167+
168+
type Port struct {
169+
Interface string `json:"interface"`
170+
Status string `json:"status"`
171+
Duplex string `json:"duplex"`
172+
Speed float64 `json:"speed"`
173+
PortPower float64 `json:"port_power"`
174+
PowerStatus float64 `json:"power_status"`
175+
Vlan string `json:"vlan"`
176+
PoeCapable bool `json:"poe_capable"`
177+
PoeStatus string `json:"poe_status"`
178+
}
179+
type PortStat struct {
180+
BytesRx float64 `json:"rx-bytes"`
181+
BytesTx float64 `json:"tx-bytes"`
182+
PacketsRx float64 `json:"rx-packets"`
183+
PacketsTx float64 `json:"tx-packets"`
184+
ErrorsRx float64 `json:"rx-errors"`
185+
ErrorsTx float64 `json:"tx-errors"`
186+
DroppedRx float64 `json:"rx-drops"`
187+
DroppedTx float64 `json:"tx-drops"`
188+
UcastRx float64 `json:"rx-ucast"`
189+
UcastTx float64 `json:"tx-ucast"`
190+
McastRx float64 `json:"rx-mcast"`
191+
McastTx float64 `json:"tx-mcast"`
192+
BcastRx float64 `json:"rx-bcast"`
193+
BcastTx float64 `json:"tx-bcast"`
194+
OversizeRx float64 `json:"rx-oversize"`
195+
OversizeTx float64 `json:"tx-oversize"`
196+
Collisions float64 `json:"collisions"`
197+
CrcAlignments float64 `json:"crc-alignments"`
198+
L3Packets float64 `json:"l3packets"`
199+
Fragments float64 `json:"fragments"`
200+
Undersize float64 `json:"undersize"`
201+
Jabbers float64 `json:"jabbers"`
202+
}
203+
204+
type Results struct {
205+
Name string `json:"name"`
206+
VDOM string `json:"vdom"`
207+
Serial string `json:"serial"`
208+
OSVersion string `json:"os_version"`
209+
State string `json:"state"`
210+
Status string `json:"status"`
211+
ConnectingFrom string `json:"connecting_from"`
212+
JoinTimeRaw float64 `json:"join_time_raw"`
213+
MaxPoeBudget float64 `json:"max_poe_budget"`
214+
Ports []Port `json:"ports"`
215+
PortStats map[string]PortStat `json:"port_stats"`
216+
}
217+
218+
type managedResponse []struct {
219+
Results []Results `json:"results"`
220+
}
221+
222+
// Consider implementing pagination to remove this limit of 1000 entries
223+
var response managedResponse
224+
if err := c.Get("api/v2/monitor/switch-controller/managed-switch", "vdom=*&start=0&poe=true&port_stats=true&transceiver=true&count=1000", &response); err != nil {
225+
log.Printf("Error: %v", err)
226+
return nil, false
227+
}
228+
229+
var m []prometheus.Metric
230+
for _, rs := range response {
231+
for _, result := range rs.Results {
232+
m = append(m, prometheus.MustNewConstMetric(managedSwitchInfo, prometheus.CounterValue, 1, result.VDOM, result.Name, result.OSVersion, result.Serial, result.State, result.Status))
233+
m = append(m, prometheus.MustNewConstMetric(managedSwitchMaxPoeBudget, prometheus.CounterValue, result.MaxPoeBudget, result.VDOM, result.Name))
234+
for _, port := range result.Ports {
235+
if port.Status == "up" {
236+
m = append(m, prometheus.MustNewConstMetric(portStatus, prometheus.GaugeValue, 1, result.VDOM, result.Name, port.Interface))
237+
} else {
238+
m = append(m, prometheus.MustNewConstMetric(portStatus, prometheus.GaugeValue, 0, result.VDOM, result.Name, port.Interface))
239+
}
240+
m = append(m, prometheus.MustNewConstMetric(portInfo, prometheus.GaugeValue, 1, result.VDOM, result.Name, port.Interface, port.Vlan, port.Duplex, port.Status, port.PoeStatus, strconv.FormatBool(port.PoeCapable)))
241+
m = append(m, prometheus.MustNewConstMetric(portPower, prometheus.GaugeValue, port.PortPower, result.VDOM, result.Name, port.Interface))
242+
m = append(m, prometheus.MustNewConstMetric(portPowerStatus, prometheus.GaugeValue, port.PowerStatus, result.VDOM, result.Name, port.Interface))
243+
244+
}
245+
for portName, port := range result.PortStats {
246+
m = append(m, prometheus.MustNewConstMetric(portRxBytes, prometheus.CounterValue, port.BytesRx, result.VDOM, result.Name, portName))
247+
m = append(m, prometheus.MustNewConstMetric(portTxBytes, prometheus.CounterValue, port.BytesTx, result.VDOM, result.Name, portName))
248+
m = append(m, prometheus.MustNewConstMetric(portRxPackets, prometheus.CounterValue, port.PacketsRx, result.VDOM, result.Name, portName))
249+
m = append(m, prometheus.MustNewConstMetric(portTxPackets, prometheus.CounterValue, port.PacketsTx, result.VDOM, result.Name, portName))
250+
m = append(m, prometheus.MustNewConstMetric(portRxUcast, prometheus.CounterValue, port.UcastRx, result.VDOM, result.Name, portName))
251+
m = append(m, prometheus.MustNewConstMetric(portTxUcast, prometheus.CounterValue, port.UcastTx, result.VDOM, result.Name, portName))
252+
m = append(m, prometheus.MustNewConstMetric(portRxMcast, prometheus.CounterValue, port.McastRx, result.VDOM, result.Name, portName))
253+
m = append(m, prometheus.MustNewConstMetric(portTxMcast, prometheus.CounterValue, port.McastTx, result.VDOM, result.Name, portName))
254+
m = append(m, prometheus.MustNewConstMetric(portRxBcast, prometheus.CounterValue, port.BcastRx, result.VDOM, result.Name, portName))
255+
m = append(m, prometheus.MustNewConstMetric(portTxBcast, prometheus.CounterValue, port.BcastTx, result.VDOM, result.Name, portName))
256+
m = append(m, prometheus.MustNewConstMetric(portRxErrors, prometheus.CounterValue, port.ErrorsRx, result.VDOM, result.Name, portName))
257+
m = append(m, prometheus.MustNewConstMetric(portTxErrors, prometheus.CounterValue, port.ErrorsTx, result.VDOM, result.Name, portName))
258+
m = append(m, prometheus.MustNewConstMetric(portRxDrops, prometheus.CounterValue, port.DroppedRx, result.VDOM, result.Name, portName))
259+
m = append(m, prometheus.MustNewConstMetric(portTxDrops, prometheus.CounterValue, port.DroppedTx, result.VDOM, result.Name, portName))
260+
m = append(m, prometheus.MustNewConstMetric(portRxOversize, prometheus.CounterValue, port.OversizeRx, result.VDOM, result.Name, portName))
261+
m = append(m, prometheus.MustNewConstMetric(portTxOversize, prometheus.CounterValue, port.OversizeTx, result.VDOM, result.Name, portName))
262+
263+
m = append(m, prometheus.MustNewConstMetric(portUndersize, prometheus.CounterValue, port.Undersize, result.VDOM, result.Name, portName))
264+
m = append(m, prometheus.MustNewConstMetric(portFragments, prometheus.CounterValue, port.Fragments, result.VDOM, result.Name, portName))
265+
m = append(m, prometheus.MustNewConstMetric(portJabbers, prometheus.CounterValue, port.Jabbers, result.VDOM, result.Name, portName))
266+
m = append(m, prometheus.MustNewConstMetric(portCollisions, prometheus.CounterValue, port.Collisions, result.VDOM, result.Name, portName))
267+
m = append(m, prometheus.MustNewConstMetric(portCrcAlignments, prometheus.CounterValue, port.CrcAlignments, result.VDOM, result.Name, portName))
268+
m = append(m, prometheus.MustNewConstMetric(portL3Packets, prometheus.CounterValue, port.L3Packets, result.VDOM, result.Name, portName))
269+
}
270+
}
271+
}
272+
273+
return m, true
274+
}

0 commit comments

Comments
 (0)