Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scrape more transceiver data #222

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e6ecd5a
Merge pull request #11 from anexia/scrape_license_information
fstolba Dec 9, 2022
70115c5
Update anx-ci.yml
fstolba May 23, 2023
5cc4b01
implement structs for show chassis hardware xml
Jun 7, 2023
8ef44f8
make new gauge for interface_transceiver (show chassis hardware)
Jun 14, 2023
26314b3
only include transceiver if it is an actual transceiver (didnt check …
Jul 5, 2023
73be159
combined "show chassis hardware" with "interface diagnostics optics"
Jul 5, 2023
d45951c
add show interfaces media info as datatype
Jul 6, 2023
d5b43f3
add show chassis pic port info
Jul 19, 2023
67e336a
fix bug, change transceiver metric so that it uses show interface med…
Jul 19, 2023
30e8b04
rename variable to be meaningful
Jul 26, 2023
40b58b4
implement structs for show chassis hardware xml
Jun 7, 2023
5dfe899
make new gauge for interface_transceiver (show chassis hardware)
Jun 14, 2023
22789f5
only include transceiver if it is an actual transceiver (didnt check …
Jul 5, 2023
59c20de
combined "show chassis hardware" with "interface diagnostics optics"
Jul 5, 2023
51dd177
add show interfaces media info as datatype
Jul 6, 2023
1c7c4d4
add show chassis pic port info
Jul 19, 2023
be5b3e4
fix bug, change transceiver metric so that it uses show interface med…
Jul 19, 2023
7bc9fd2
rename variable to be meaningful
Jul 26, 2023
126b541
Merge branch 'netdev-517/add-interface-type,-product-and-serial-numbe…
Jul 26, 2023
45988e6
make new gauge for interface_transceiver (show chassis hardware)
Jun 14, 2023
6dad166
Merge branch 'netdev-517/add-interface-type,-product-and-serial-numbe…
Jul 26, 2023
a373d46
Merge branch 'anx-prod' into netdev-517/add-interface-type,-product-a…
Aug 3, 2023
a443450
delete anx-ci.yml
Aug 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 137 additions & 5 deletions pkg/features/interfacediagnostics/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package interfacediagnostics

import (
"encoding/xml"
"fmt"
"log"
"math"
"strconv"
Expand Down Expand Up @@ -63,6 +64,8 @@ type interfaceDiagnosticsCollector struct {

rxSignalAvgOpticalPowerDesc *prometheus.Desc
rxSignalAvgOpticalPowerDbmDesc *prometheus.Desc

transceiverDesc *prometheus.Desc
}

// NewCollector creates a new collector
Expand Down Expand Up @@ -128,6 +131,9 @@ func (c *interfaceDiagnosticsCollector) init() {
c.laserRxOpticalPowerLowAlarmThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_alarm_threshold_dbm", "Laser rx power low alarm threshold_dbm in dBm", l, nil)
c.laserRxOpticalPowerHighWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_high_warn_threshold_dbm", "Laser rx power high warn threshold_dbm in dBm", l, nil)
c.laserRxOpticalPowerLowWarnThresholdDbmDesc = prometheus.NewDesc(prefix+"laser_rx_low_warn_threshold_dbm", "Laser rx power low warn threshold_dbm in dBm", l, nil)

transceiver_labels := []string{"target", "name", "serial_number", "description", "speed", "fiber_type", "vendor_name", "vendor_part_number", "wavelength"}
c.transceiverDesc = prometheus.NewDesc("junos_interface_transceiver", "Transceiver Info", transceiver_labels, nil)
}

// Describe describes the metrics
Expand Down Expand Up @@ -172,6 +178,8 @@ func (c *interfaceDiagnosticsCollector) Describe(ch chan<- *prometheus.Desc) {

ch <- c.rxSignalAvgOpticalPowerDesc
ch <- c.rxSignalAvgOpticalPowerDbmDesc

ch <- c.transceiverDesc
}

// Collect collects metrics from JunOS
Expand All @@ -187,11 +195,16 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan
if err != nil {
return err
}

diagnostics = append(diagnostics, diagnosticsSatellite...)
}

diagnostics_dict := make(map[string]*interfaceDiagnostics)

for _, d := range diagnostics {

index := strings.Split(d.Name, "-")[1]
diagnostics_dict[index] = d

l := append(labelValues, d.Name)
l = append(l, c.labels.ValuesForInterface(client.Device(), d.Name)...)

Expand Down Expand Up @@ -251,17 +264,126 @@ func (c *interfaceDiagnosticsCollector) Collect(client collector.Client, ch chan
}
}

err = createTransceiverMetrics(c, client, diagnostics_dict, ch, labelValues)
if err != nil {
return err
}
return nil
}

func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client collector.Client) ([]*interfaceDiagnostics, error) {
var x = result{}
err := client.RunCommandAndParse("show interfaces diagnostics optics", &x)
func (c *interfaceDiagnosticsCollector) interfaceMediaInfo(client collector.Client) (map[string]*physicalInterface, error) {
var x = interfacesMediaStruct{}
err := client.RunCommandAndParse("show interfaces media", &x)
if err != nil {
return nil, err
}

return interfaceDiagnosticsFromRPCResult(x), nil
return interfaceMediaInfoFromRPCResult(&x.InterfaceInformation.PhysicalInterface), nil
}

func interfaceMediaInfoFromRPCResult(interfaceMediaList *[]physicalInterface) map[string]*physicalInterface {

interfaceMediaDict := make(map[string]*physicalInterface)

for _, i := range *interfaceMediaList {
if strings.HasPrefix(i.Name, "xe") || strings.HasPrefix(i.Name, "ge") || strings.HasPrefix(i.Name, "et") {
iface := i
slotIndex := iface.Name[3:]
interfaceMediaDict[slotIndex] = &iface
}
}
return interfaceMediaDict
}

func (c *interfaceDiagnosticsCollector) chassisHardwareInfos(client collector.Client) ([]*transceiverInformation, error) {
var x = chassisHardware{}
err := client.RunCommandAndParse("show chassis hardware", &x)
if err != nil {
return nil, err
}

return c.transceiverInfoFromRPCResult(client, x)
}

func (c *interfaceDiagnosticsCollector) transceiverInfoFromRPCResult(client collector.Client, chassisHardware chassisHardware) ([]*transceiverInformation, error) {
transceiverList := make([]*transceiverInformation, 0)

var chassisModules = chassisHardware.ChassisInventory.Chassis.ChassisModule
for _, module := range chassisModules {
if strings.Split(module.Name, " ")[0] != "FPC" {
continue
}
for _, subModule := range module.ChassisSubModule {
if strings.Split(subModule.Name, " ")[0] != "PIC" {
continue
}
fpc := strings.Split(module.Name, " ")[1]
pic := strings.Split(subModule.Name, " ")[1]

picPortsInformation, err := c.getPicPortsFromRPCResult(client, fpc, pic)
if err != nil {
return nil, err
}

for port, subSubModule := range subModule.ChassisSubSubModule {
port_name := strings.Split(subSubModule.Name, " ")[1]
subSubModule_pointer := subSubModule
id := fpc + "/" + pic + "/" + port_name
transceiver := transceiverInformation{
Name: id,
ChassisHardwareInfo: &subSubModule_pointer,
PicPort: &picPortsInformation[port],
}
transceiverList = append(transceiverList, &transceiver)
}
}
}
return transceiverList, nil
}

func (c *interfaceDiagnosticsCollector) getPicPortsFromRPCResult(client collector.Client, fpc string, pic string) ([]picPort, error) {
var x = fPCInformationStruct{}
command := fmt.Sprintf("show chassis pic fpc-slot %s pic-slot %s", fpc, pic)
err := client.RunCommandAndParse(command, &x)
if err != nil {
return nil, err
}

return x.FPCInformation.FPC.PicDetail.PicPortInfoList, nil
}

func createTransceiverMetrics(c *interfaceDiagnosticsCollector, client collector.Client, diagnostics_dict map[string]*interfaceDiagnostics, ch chan<- prometheus.Metric, labelValues []string) error {

ifMediaDict, err := c.interfaceMediaInfo(client)
if err != nil {
return err
}

transceiverInfo, err := c.chassisHardwareInfos(client)
if err != nil {
return err
}

for _, t := range transceiverInfo {
chassisInfo := t.ChassisHardwareInfo
port_speed := "0"
oper_status := 0.0

if media, hit := ifMediaDict[t.Name]; hit {
if media.OperStatus == "up" {
oper_status = 1.0
}
t.Name = media.Name
port_speed = media.Speed
} else {
t.Name = "slot-" + t.Name
}

transceiver_labels := append(labelValues, t.Name, chassisInfo.SerialNumber, chassisInfo.Description, port_speed, t.PicPort.FiberMode, strings.TrimSpace(t.PicPort.SFPVendorName), strings.TrimSpace(t.PicPort.SFPVendorPno), t.PicPort.Wavelength)

ch <- prometheus.MustNewConstMetric(c.transceiverDesc, prometheus.GaugeValue, oper_status, transceiver_labels...)
}
return nil
}

func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client collector.Client) ([]*interfaceDiagnostics, error) {
Expand Down Expand Up @@ -321,6 +443,16 @@ func (c *interfaceDiagnosticsCollector) interfaceDiagnosticsSatellite(client col
return interfaceDiagnosticsFromRPCResult(x), nil
}

func (c *interfaceDiagnosticsCollector) interfaceDiagnostics(client collector.Client) ([]*interfaceDiagnostics, error) {
var x = result{}
err := client.RunCommandAndParse("show interfaces diagnostics optics", &x)
if err != nil {
return nil, err
}

return interfaceDiagnosticsFromRPCResult(x), nil
}

func interfaceDiagnosticsFromRPCResult(res result) []*interfaceDiagnostics {
diagnostics := make([]*interfaceDiagnostics, 0)

Expand Down
7 changes: 7 additions & 0 deletions pkg/features/interfacediagnostics/interface_stats.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package interfacediagnostics

type transceiverInformation struct {
Name string
ChassisHardwareInfo *chassisSubSubModule
PicPort *picPort
}
120 changes: 120 additions & 0 deletions pkg/features/interfacediagnostics/rpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,126 @@

package interfacediagnostics

type fPCInformationStruct struct {
FPCInformation fPCInformation `xml:"fpc-information"`
}
type fPCInformation struct {
FPC fPC `xml:"fpc"`
}

type fPC struct {
PicDetail picDetail `xml:"pic-detail"`
}

type picDetail struct {
Slot int `xml:"slot"`
PicSlot int `xml:"pic-slot"`
PicType string `xml:"pic-type"`
State string `xml:"state"`
PicVersion string `xml:"pic-version"`
UpTime string `xml:"up-time"`
PicPortInfoList []picPort `xml:"port-information>port"`
}

type picPort struct {
PortNumber int `xml:"port-number"`
CableType string `xml:"cable-type"`
FiberMode string `xml:"fiber-mode"`
SFPVendorName string `xml:"sfp-vendor-name"`
SFPVendorPno string `xml:"sfp-vendor-pno"`
Wavelength string `xml:"wavelength"`
SFPVendorFwVer string `xml:"sfp-vendor-fw-ver"`
SFPJnprVer string `xml:"sfp-jnpr-ver"`
}

type interfacesMediaStruct struct {
InterfaceInformation struct {
PhysicalInterface []physicalInterface `xml:"physical-interface"`
} `xml:"interface-information"`
}

type physicalInterface struct {
Name string `xml:"name"`
AdminStatus string `xml:"admin-status"`
OperStatus string `xml:"oper-status"`
LocalIndex string `xml:"local-index"`
SnmpIndex string `xml:"snmp-index"`
IfType string `xml:"if-type"`
LinkLevelType string `xml:"link-level-type"`
Mtu string `xml:"mtu"`
Speed string `xml:"speed"`
LinkType string `xml:"link-type"`
InterfaceFlapped struct {
Seconds uint64 `xml:"seconds,attr"`
Value string `xml:",chardata"`
} `xml:"interface-flapped"`
IfDeviceFlags ifDeviceFlags `xml:"if-device-flags"`
Stats trafficStat `xml:"traffic-statistics"`
}

type trafficStat struct {
InputBytes uint64 `xml:"input-bytes"`
InputPackets uint64 `xml:"input-packets"`
OutputBytes uint64 `xml:"output-bytes"`
OutputPackets uint64 `xml:"output-packets"`
IPv6Traffic ipv6Stat `xml:"ipv6-transit-statistics"`
}
type ipv6Stat struct {
InputBytes uint64 `xml:"input-bytes"`
InputPackets uint64 `xml:"input-packets"`
OutputBytes uint64 `xml:"output-bytes"`
OutputPackets uint64 `xml:"output-packets"`
}

type ifDeviceFlags struct {
Present bool `xml:"ifdf-present"`
Running bool `xml:"ifdf-running"`
Loopback bool `xml:"ifdf-loopback"`
Down bool `xml:"ifdf-down"`
}

type chassisHardware struct {
ChassisInventory chassisInventory `xml:"chassis-inventory"`
}

type chassisInventory struct {
Chassis chassis `xml:"chassis"`
}

type chassis struct {
Name string `xml:"name"`
SerialNumber string `xml:"serial-number"`
Description string `xml:"description"`
ChassisModule []chassisModule `xml:"chassis-module"`
}

type chassisModule struct {
Name string `xml:"name"`
PartNumber string `xml:"part-number"`
SerialNumber string `xml:"serial-number"`
Description string `xml:"description"`
CleiCode string `xml:"clei-code"`
ModelNumber string `xml:"model-number"`
ChassisSubModule []chassisSubModule `xml:"chassis-sub-module"`
}

type chassisSubModule struct {
Name string `xml:"name"`
PartNumber string `xml:"part-number"`
SerialNumber string `xml:"serial-number"`
Description string `xml:"description"`
CleiCode string `xml:"clei-code"`
ModelNumber string `xml:"model-number"`
ChassisSubSubModule []chassisSubSubModule `xml:"chassis-sub-sub-module"`
}
type chassisSubSubModule struct {
Name string `xml:"name"`
Version string `xml:"version"`
PartNumber string `xml:"part-number"`
SerialNumber string `xml:"serial-number"`
Description string `xml:"description"`
}

type result struct {
Information struct {
Diagnostics []phyDiagInterface `xml:"physical-interface"`
Expand Down