From f65453d24fb7758f604c9752e95c0a3a50517c2a Mon Sep 17 00:00:00 2001 From: Jakob Gastinger Date: Wed, 20 Dec 2023 17:23:21 +0100 Subject: [PATCH] now scrapes interface information to include underlying interfaces for each subscriber --- pkg/features/subscriber/collector.go | 57 ++++++++++++++++++++++++++-- pkg/features/subscriber/rpc.go | 22 ++++++++--- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/pkg/features/subscriber/collector.go b/pkg/features/subscriber/collector.go index c8c104b2..10c5a868 100644 --- a/pkg/features/subscriber/collector.go +++ b/pkg/features/subscriber/collector.go @@ -3,6 +3,10 @@ package subscriber import ( + "errors" + "fmt" + "strings" + "github.com/czerwonk/junos_exporter/pkg/collector" "github.com/prometheus/client_golang/prometheus" ) @@ -12,7 +16,7 @@ const prefix string = "junos_subscriber_info" var subscriberInfo *prometheus.Desc func init() { - l := []string{"target", "interface", "agent_circuit_id", "agent_remote_id"} + l := []string{"target", "interface", "agent_circuit_id", "agent_remote_id", "underlying_ifd"} subscriberInfo = prometheus.NewDesc(prefix+"", "Subscriber Detail", l, nil) } @@ -33,16 +37,61 @@ func (*subcsribers_information) Describe(ch chan<- *prometheus.Desc) { // Collect collects metrics from JunOS func (c *subcsribers_information) Collect(client collector.Client, ch chan<- prometheus.Metric, labelValues []string) error { + var x = subcsribers_information{} - err := client.RunCommandAndParse("show subscribers client-type dhcp detail", &x) + err := client.RunCommandAndParse("show subscribers client-type dhcp detail", &x) //TODO: see if client-type dhcp can be left out + if err != nil { + return err + } + + logicalInterfaceMap, err := getLogicalInterfaceInformation(client) if err != nil { return err } for _, subscriber := range x.SubscribersInformation.Subscriber { - labels := append(labelValues, subscriber.Interface, subscriber.AgentCircuitId, subscriber.AgentRemoteId) + underlying_interface, err := findUnderlyingInterface(client, subscriber.UnderlyingInterface, logicalInterfaceMap, 2) + if err != nil { + fmt.Println(err) + } + + labels := append(labelValues, subscriber.Interface, subscriber.AgentCircuitId, subscriber.AgentRemoteId, underlying_interface) ch <- prometheus.MustNewConstMetric(subscriberInfo, prometheus.CounterValue, 1, labels...) } - return nil } + +func getLogicalInterfaceInformation(client collector.Client) (map[string]string, error) { + + var interfaceInformation = &InterfaceInformation{} + var interfaceMap = make(map[string]string) + + err := client.RunCommandAndParse("show interfaces demux0 brief", interfaceInformation) + if err != nil { + return nil, err + } + + for _, logicalInterface := range interfaceInformation.LogicalInterfaces { + interfaceMap[logicalInterface.Name] = logicalInterface.DemuxUnderlyingIfName + } + + return interfaceMap, nil +} + +func findUnderlyingInterface(client collector.Client, ifName string, logicalIfMap map[string]string, maxDepth int) (string, error) { + + if !(strings.HasPrefix(ifName, "demux")) { + return ifName, nil + } + + if maxDepth < 0 { + return "", errors.New("no underlying interface found, max treshold reached") + } + + logicalIfName, exists := logicalIfMap[ifName] + if !exists { + return "", errors.New("no underlying interface found") + } + + return findUnderlyingInterface(client, logicalIfName, logicalIfMap, maxDepth-1) +} diff --git a/pkg/features/subscriber/rpc.go b/pkg/features/subscriber/rpc.go index 8fb028b1..3b8f359e 100644 --- a/pkg/features/subscriber/rpc.go +++ b/pkg/features/subscriber/rpc.go @@ -2,13 +2,23 @@ package subscriber type subcsribers_information struct { SubscribersInformation struct { - Subscriber []subscriber `xml:"subscriber"` + Subscriber []Subscriber `xml:"subscriber"` } `xml:"subscribers-information"` } -type subscriber struct { - AccessType string `xml:"access-type"` - Interface string `xml:"interface"` - AgentCircuitId string `xml:"agent-circuit-id"` - AgentRemoteId string `xml:"agent-remote-id"` +type Subscriber struct { + AccessType string `xml:"access-type"` + Interface string `xml:"interface"` + AgentCircuitId string `xml:"agent-circuit-id"` + AgentRemoteId string `xml:"agent-remote-id"` + UnderlyingInterface string `xml:"underlying-interface"` +} + +type InterfaceInformation struct { + LogicalInterfaces []LogicalInterface `xml:"interface-information>physical-interface>logical-interface"` +} + +type LogicalInterface struct { + Name string `xml:"name"` + DemuxUnderlyingIfName string `xml:"demux-information>demux-interface>demux-underlying-interface-name"` }