From 00b93a0daa7bf1c95cd1733f350cb769afd93c2b Mon Sep 17 00:00:00 2001 From: Joel Norberg Date: Mon, 14 Oct 2024 09:08:59 +0200 Subject: [PATCH 1/3] [feat] Interface transceivers metrics support --- README.md | 2 + pkg/probe/probe.go | 1 + pkg/probe/system_interface_transceivers.go | 41 ++++++++++++++++++ .../system_interface_transceivers_test.go | 31 ++++++++++++++ .../testdata/interface-transceivers.jsonnet | 42 +++++++++++++++++++ 5 files changed, 117 insertions(+) create mode 100644 pkg/probe/system_interface_transceivers.go create mode 100755 pkg/probe/system_interface_transceivers_test.go create mode 100644 pkg/probe/testdata/interface-transceivers.jsonnet diff --git a/README.md b/README.md index 82a0118b..79338a6a 100755 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ Global: * `fortigate_sensor_voltage_volts` * _System/Status_ * `fortigate_version_info` + * _System/Transceivers_ + * `fortigate_interface_transceivers` * _System/Time/Clock_ * `fortigate_time_seconds` * _System/Resource/Usage_ diff --git a/pkg/probe/probe.go b/pkg/probe/probe.go index c79a7f6f..557497fd 100644 --- a/pkg/probe/probe.go +++ b/pkg/probe/probe.go @@ -131,6 +131,7 @@ func (p *ProbeCollector) Probe(ctx context.Context, target map[string]string, hc {"System/Fortimanager/Status", probeSystemFortimanagerStatus}, {"System/HAStatistics", probeSystemHAStatistics}, {"System/Interface", probeSystemInterface}, + {"System/Transceivers", probeSystemInterfaceTransceivers}, {"System/LinkMonitor", probeSystemLinkMonitor}, {"System/Resource/Usage", probeSystemResourceUsage}, {"System/SDNConnector", probeSystemSDNConnector}, diff --git a/pkg/probe/system_interface_transceivers.go b/pkg/probe/system_interface_transceivers.go new file mode 100644 index 00000000..15846ed6 --- /dev/null +++ b/pkg/probe/system_interface_transceivers.go @@ -0,0 +1,41 @@ +package probe + +import ( + "log" + + "github.com/bluecmd/fortigate_exporter/pkg/http" + "github.com/prometheus/client_golang/prometheus" +) + +func probeSystemInterfaceTransceivers(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) { + var ( + mVersion = prometheus.NewDesc( + "fortigate_interface_transceivers", + "List of transceivers being used by the FortiGate", + []string{"name", "type", "vendor", "partnumber", "description"}, nil, + ) + ) + + type ifResult struct { + Description string + Interface string + Type string + Vendor string + VendorPartNr string `json:"vendor_part_number"` + } + type ifResponse struct { + Results []ifResult + } + var r ifResponse + + if err := c.Get("api/v2/monitor/system/interface/transceivers", "scope=global", &r); err != nil { + log.Printf("Error: %v", err) + return nil, false + } + + m := []prometheus.Metric{} + for _, result := range r.Results { + m = append(m, prometheus.MustNewConstMetric(mVersion, prometheus.GaugeValue, 1.0, result.Interface, result.Type, result.Vendor, result.VendorPartNr, result.Description)) + } + return m, true +} diff --git a/pkg/probe/system_interface_transceivers_test.go b/pkg/probe/system_interface_transceivers_test.go new file mode 100755 index 00000000..73ef7c96 --- /dev/null +++ b/pkg/probe/system_interface_transceivers_test.go @@ -0,0 +1,31 @@ +package probe + +import ( + "strings" + "testing" + + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/testutil" +) + +func TestSystemInterfaceTransceivers(t *testing.T) { + c := newFakeClient() + c.prepare("api/v2/monitor/system/interface/transceivers", "testdata/interface-transceivers.jsonnet") + r := prometheus.NewPedanticRegistry() + if !testProbe(probeSystemInterfaceTransceivers, c, r) { + t.Errorf("probeSystemInterfaceTransceivers() returned non-success") + } + + em := ` + # HELP fortigate_interface_transceivers List of transceivers being used by the FortiGate + # TYPE fortigate_interface_transceivers gauge + fortigate_interface_transceivers{description="",name="ha1",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers{description="",name="ha2",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers{description="",name="port33",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 + fortigate_interface_transceivers{description="",name="port34",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 + ` + + if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil { + t.Fatalf("metric compare: err %v", err) + } +} diff --git a/pkg/probe/testdata/interface-transceivers.jsonnet b/pkg/probe/testdata/interface-transceivers.jsonnet new file mode 100644 index 00000000..317c7871 --- /dev/null +++ b/pkg/probe/testdata/interface-transceivers.jsonnet @@ -0,0 +1,42 @@ +# api/v2/monitor/system/interface/transceivers?scope=global +{ + "http_method":"GET", + "results":[ + { + "type":"QSFP\/QSFP+", + "vendor":"FORTINET", + "vendor_part_number":"FTL410QE4CFTN", + "vendor_serial_number":"U00000", + "interface":"port33" + }, + { + "type":"QSFP\/QSFP+", + "vendor":"FORTINET", + "vendor_part_number":"FTL410QE4CFTN", + "vendor_serial_number":"U00000", + "interface":"port34" + }, + { + "type":"SFP\/SFP+\/SFP28", + "vendor":"FORTINET", + "vendor_part_number":"FTLX8574D3BCLFTN", + "vendor_serial_number":"U00000", + "interface":"ha1" + }, + { + "type":"SFP\/SFP+\/SFP28", + "vendor":"FORTINET", + "vendor_part_number":"FTLX8574D3BCLFTN", + "vendor_serial_number":"U00000", + "interface":"ha2" + } + ], + "vdom":"root", + "path":"system", + "name":"interface", + "action":"transceivers", + "status":"success", + "serial":"F2K60FTK00000000", + "version":"v7.4.5", + "build":2702 +} From e70f441aed6c08a2827be5e16724022a77fc37fb Mon Sep 17 00:00:00 2001 From: Joel Norberg Date: Tue, 15 Oct 2024 10:50:19 +0200 Subject: [PATCH 2/3] [fix] rename of metric to include _info --- pkg/probe/system_interface_transceivers.go | 2 +- pkg/probe/system_interface_transceivers_test.go | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/probe/system_interface_transceivers.go b/pkg/probe/system_interface_transceivers.go index 15846ed6..59989c20 100644 --- a/pkg/probe/system_interface_transceivers.go +++ b/pkg/probe/system_interface_transceivers.go @@ -10,7 +10,7 @@ import ( func probeSystemInterfaceTransceivers(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) { var ( mVersion = prometheus.NewDesc( - "fortigate_interface_transceivers", + "fortigate_interface_transceivers_info", "List of transceivers being used by the FortiGate", []string{"name", "type", "vendor", "partnumber", "description"}, nil, ) diff --git a/pkg/probe/system_interface_transceivers_test.go b/pkg/probe/system_interface_transceivers_test.go index 73ef7c96..17dc8cca 100755 --- a/pkg/probe/system_interface_transceivers_test.go +++ b/pkg/probe/system_interface_transceivers_test.go @@ -17,12 +17,12 @@ func TestSystemInterfaceTransceivers(t *testing.T) { } em := ` - # HELP fortigate_interface_transceivers List of transceivers being used by the FortiGate - # TYPE fortigate_interface_transceivers gauge - fortigate_interface_transceivers{description="",name="ha1",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 - fortigate_interface_transceivers{description="",name="ha2",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 - fortigate_interface_transceivers{description="",name="port33",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 - fortigate_interface_transceivers{description="",name="port34",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 + # HELP fortigate_interface_transceivers_info List of transceivers being used by the FortiGate + # TYPE fortigate_interface_transceivers_info gauge + fortigate_interface_transceivers_info{description="",name="ha1",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="ha2",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="port33",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="port34",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 ` if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil { From 481157760965fd628fd64cb459abedb71629f961 Mon Sep 17 00:00:00 2001 From: Joel Norberg Date: Tue, 15 Oct 2024 14:00:11 +0200 Subject: [PATCH 3/3] [fix] includes vendor part serialnumber --- pkg/probe/system_interface_transceivers.go | 15 ++++++++------- pkg/probe/system_interface_transceivers_test.go | 8 ++++---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/pkg/probe/system_interface_transceivers.go b/pkg/probe/system_interface_transceivers.go index 59989c20..da00f446 100644 --- a/pkg/probe/system_interface_transceivers.go +++ b/pkg/probe/system_interface_transceivers.go @@ -12,16 +12,17 @@ func probeSystemInterfaceTransceivers(c http.FortiHTTP, meta *TargetMetadata) ([ mVersion = prometheus.NewDesc( "fortigate_interface_transceivers_info", "List of transceivers being used by the FortiGate", - []string{"name", "type", "vendor", "partnumber", "description"}, nil, + []string{"name", "type", "vendor", "partnumber", "serialnumber", "description"}, nil, ) ) type ifResult struct { - Description string - Interface string - Type string - Vendor string - VendorPartNr string `json:"vendor_part_number"` + Description string + Interface string + Type string + Vendor string + VendorPartNr string `json:"vendor_part_number"` + VendorSerialNr string `json:"vendor_serial_number"` } type ifResponse struct { Results []ifResult @@ -35,7 +36,7 @@ func probeSystemInterfaceTransceivers(c http.FortiHTTP, meta *TargetMetadata) ([ m := []prometheus.Metric{} for _, result := range r.Results { - m = append(m, prometheus.MustNewConstMetric(mVersion, prometheus.GaugeValue, 1.0, result.Interface, result.Type, result.Vendor, result.VendorPartNr, result.Description)) + m = append(m, prometheus.MustNewConstMetric(mVersion, prometheus.GaugeValue, 1.0, result.Interface, result.Type, result.Vendor, result.VendorPartNr, result.VendorSerialNr, result.Description)) } return m, true } diff --git a/pkg/probe/system_interface_transceivers_test.go b/pkg/probe/system_interface_transceivers_test.go index 17dc8cca..bd9941e4 100755 --- a/pkg/probe/system_interface_transceivers_test.go +++ b/pkg/probe/system_interface_transceivers_test.go @@ -19,10 +19,10 @@ func TestSystemInterfaceTransceivers(t *testing.T) { em := ` # HELP fortigate_interface_transceivers_info List of transceivers being used by the FortiGate # TYPE fortigate_interface_transceivers_info gauge - fortigate_interface_transceivers_info{description="",name="ha1",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 - fortigate_interface_transceivers_info{description="",name="ha2",partnumber="FTLX8574D3BCLFTN",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 - fortigate_interface_transceivers_info{description="",name="port33",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 - fortigate_interface_transceivers_info{description="",name="port34",partnumber="FTL410QE4CFTN",type="QSFP/QSFP+",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="ha1",partnumber="FTLX8574D3BCLFTN",serialnumber="U00000",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="ha2",partnumber="FTLX8574D3BCLFTN",serialnumber="U00000",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="port33",partnumber="FTL410QE4CFTN",serialnumber="U00000",type="QSFP/QSFP+",vendor="FORTINET"} 1 + fortigate_interface_transceivers_info{description="",name="port34",partnumber="FTL410QE4CFTN",serialnumber="U00000",type="QSFP/QSFP+",vendor="FORTINET"} 1 ` if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {