From 022bee08f70daff14f5bd39f0851298cdb88d9c1 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 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Örnfeldt Philip (66140321) --- README.md | 5 ++ pkg/probe/probe.go | 1 + pkg/probe/system_interface_transceivers.go | 56 +++++++++++++++++++ .../system_interface_transceivers_test.go | 31 ++++++++++ .../testdata/interface-transceivers.jsonnet | 42 ++++++++++++++ 5 files changed, 135 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 2b843beb..3541066d 100755 --- a/README.md +++ b/README.md @@ -43,6 +43,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_ @@ -89,6 +91,8 @@ Per-VDOM: * `fortigate_interface_receive_bytes_total` * `fortigate_interface_transmit_errors_total` * `fortigate_interface_receive_errors_total` + * _System/Interface/Transceivers_ + * `fortigate_inteface_transceivers` * _System/SDNConnector_ * `fortigate_system_sdn_connector_status` * `fortigate_system_sdn_connector_last_update_seconds` @@ -415,6 +419,7 @@ To improve security, limit permissions to required ones only (least privilege pr |System/Fortimanager/Status | sysgrp.cfg |api/v2/monitor/system/fortimanager/status | |System/HAStatistics | sysgrp.cfg |api/v2/monitor/system/ha-statistics
api/v2/cmdb/system/ha | |System/Interface | netgrp.cfg |api/v2/monitor/system/interface/select | +|System/Interface/Transceivers| *any* |api/v2/monitor/system/interface/transceivers | |System/LinkMonitor | sysgrp.cfg |api/v2/monitor/system/link-monitor | |System/Resource/Usage | sysgrp.cfg |api/v2/monitor/system/resource/usage | |System/SensorInfo | sysgrp.cfg |api/v2/monitor/system/sensor-info | diff --git a/pkg/probe/probe.go b/pkg/probe/probe.go index 88d76fe6..4e9e5fc0 100644 --- a/pkg/probe/probe.go +++ b/pkg/probe/probe.go @@ -144,6 +144,7 @@ func (p *ProbeCollector) Probe(ctx context.Context, target map[string]string, hc {"System/Fortimanager/Status", probeSystemFortimanagerStatus}, {"System/HAStatistics", probeSystemHAStatistics}, {"System/Interface", probeSystemInterface}, + {"System/Interface/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..e44f32a8 --- /dev/null +++ b/pkg/probe/system_interface_transceivers.go @@ -0,0 +1,56 @@ +// Copyright 2025 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package probe + +import ( + "log" + + "github.com/prometheus-community/fortigate_exporter/pkg/http" + "github.com/prometheus/client_golang/prometheus" +) + +func probeSystemInterfaceTransceivers(c http.FortiHTTP, meta *TargetMetadata) ([]prometheus.Metric, bool) { + var ( + interfaceTransceivers = prometheus.NewDesc( + "fortigate_inteface_transceivers", + "Interface transceivers information", + []string{"interface", "type", "vendor", "vendorpartnumber", "vendorserialnumber"}, nil, + ) + ) + + type SystemInterfaceTransceiversResult struct { + Interface string `json:"interface"` + Type string `json:"type"` + Vendor string `json:"vendor"` + VendorPartNumber string `json:"vendor_part_number"` + VendorSerialNumber string `json:"vendor_serial_number"` + } + + type SystemInterfaceTransceivers struct { + Results []SystemInterfaceTransceiversResult `json:"results"` + } + + var res SystemInterfaceTransceivers + if err := c.Get("api/v2/monitor/system/interface/transceivers", "scope=global", &res); err != nil { + log.Printf("Warning: %v", err) + return nil, false + } + + m := []prometheus.Metric{} + for _, r := range res.Results { + m = append(m, prometheus.MustNewConstMetric(interfaceTransceivers, prometheus.GaugeValue, 1.0, r.Interface, r.Type, r.Vendor, r.VendorPartNumber, r.VendorSerialNumber)) + } + + return m, true +} \ No newline at end of file diff --git a/pkg/probe/system_interface_transceivers_test.go b/pkg/probe/system_interface_transceivers_test.go new file mode 100755 index 00000000..548beb08 --- /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="FTL",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers{description="",name="ha2",partnumber="FTL",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 + fortigate_interface_transceivers{description="",name="port33",partnumber="FTL",type="QSFP/QSFP+",vendor="FORTINET"} 1 + fortigate_interface_transceivers{description="",name="port34",partnumber="FTL",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..aae513c9 --- /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":"FTL", + "vendor_serial_number":"U00000", + "interface":"port33" + }, + { + "type":"QSFP\/QSFP+", + "vendor":"FORTINET", + "vendor_part_number":"FTL", + "vendor_serial_number":"U00000", + "interface":"port34" + }, + { + "type":"SFP\/SFP+\/SFP28", + "vendor":"FORTINET", + "vendor_part_number":"FTL", + "vendor_serial_number":"U00000", + "interface":"ha1" + }, + { + "type":"SFP\/SFP+\/SFP28", + "vendor":"FORTINET", + "vendor_part_number":"FTL", + "vendor_serial_number":"U00000", + "interface":"ha2" + } + ], + "vdom":"root", + "path":"system", + "name":"interface", + "action":"transceivers", + "status":"success", + "serial":"F2", + "version":"v7.4.5", + "build":2702 +} From c7c8a446fd5a8505a1ff859cc97af19bcdc4a5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96rnfeldt=20Philip=20=2866140321=29?= Date: Mon, 15 Sep 2025 16:52:05 +0200 Subject: [PATCH 2/3] Correct test data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Örnfeldt Philip (66140321) --- pkg/probe/system_interface_transceivers_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/probe/system_interface_transceivers_test.go b/pkg/probe/system_interface_transceivers_test.go index 548beb08..d0e30f32 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="FTL",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 - fortigate_interface_transceivers{description="",name="ha2",partnumber="FTL",type="SFP/SFP+/SFP28",vendor="FORTINET"} 1 - fortigate_interface_transceivers{description="",name="port33",partnumber="FTL",type="QSFP/QSFP+",vendor="FORTINET"} 1 - fortigate_interface_transceivers{description="",name="port34",partnumber="FTL",type="QSFP/QSFP+",vendor="FORTINET"} 1 + # HELP fortigate_inteface_transceivers Interface transceivers information + # TYPE fortigate_inteface_transceivers gauge + fortigate_inteface_transceivers{interface="ha1",type="SFP/SFP+/SFP28",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + fortigate_inteface_transceivers{interface="ha2",type="SFP/SFP+/SFP28",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + fortigate_inteface_transceivers{interface="port33",type="QSFP/QSFP+",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + fortigate_inteface_transceivers{interface="port34",type="QSFP/QSFP+",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 ` if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil { From b523dfbc08250bfeeb43077f714b08972f3f51ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96rnfeldt=20Philip=20=2866140321=29?= Date: Tue, 4 Nov 2025 14:07:49 +0100 Subject: [PATCH 3/3] New test file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Örnfeldt Philip (66140321) --- pkg/probe/system_interface_transceivers_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/probe/system_interface_transceivers_test.go b/pkg/probe/system_interface_transceivers_test.go index d0e30f32..52e28db7 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_inteface_transceivers Interface transceivers information - # TYPE fortigate_inteface_transceivers gauge - fortigate_inteface_transceivers{interface="ha1",type="SFP/SFP+/SFP28",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 - fortigate_inteface_transceivers{interface="ha2",type="SFP/SFP+/SFP28",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 - fortigate_inteface_transceivers{interface="port33",type="QSFP/QSFP+",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 - fortigate_inteface_transceivers{interface="port34",type="QSFP/QSFP+",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + # HELP fortigate_inteface_transceivers_info Interface transceivers information + # TYPE fortigate_inteface_transceivers_info gauge + fortigate_inteface_transceivers_info{interface="ha1",type="SFP/SFP+/SFP28",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + fortigate_inteface_transceivers_info{interface="ha2",type="SFP/SFP+/SFP28",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + fortigate_inteface_transceivers_info{interface="port33",type="QSFP/QSFP+",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 + fortigate_inteface_transceivers_info{interface="port34",type="QSFP/QSFP+",vendor="FORTINET",vendorpartnumber="FTL",vendorserialnumber="U00000"} 1 ` if err := testutil.GatherAndCompare(r, strings.NewReader(em)); err != nil {