Skip to content

Commit 3392081

Browse files
authored
KRT qeueue length feature (#279)
1 parent dba86bc commit 3392081

File tree

6 files changed

+240
-0
lines changed

6 files changed

+240
-0
lines changed

collectors.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/czerwonk/junos_exporter/pkg/features/interfaces"
2525
"github.com/czerwonk/junos_exporter/pkg/features/ipsec"
2626
"github.com/czerwonk/junos_exporter/pkg/features/isis"
27+
"github.com/czerwonk/junos_exporter/pkg/features/krt"
2728
"github.com/czerwonk/junos_exporter/pkg/features/l2circuit"
2829
"github.com/czerwonk/junos_exporter/pkg/features/l2vpn"
2930
"github.com/czerwonk/junos_exporter/pkg/features/lacp"
@@ -126,6 +127,7 @@ func (c *collectors) initCollectorsForDevices(device *connector.Device, descRe *
126127
c.addCollectorIfEnabledForDevice(device, "arp", f.ARP, arp.NewCollector)
127128
c.addCollectorIfEnabledForDevice(device, "poe", f.Poe, poe.NewCollector)
128129
c.addCollectorIfEnabledForDevice(device, "ddosprotection", f.DDOSProtection, ddosprotection.NewCollector)
130+
c.addCollectorIfEnabledForDevice(device, "krt", f.KRT, krt.NewCollector)
129131
}
130132

131133
func (c *collectors) addCollectorIfEnabledForDevice(device *connector.Device, key string, enabled bool, newCollector func() collector.RPCCollector) {

internal/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ type FeatureConfig struct {
101101
ARP bool `yaml:"arp,omitempty"`
102102
Poe bool `yaml:"poe,omitempty"`
103103
DDOSProtection bool `yaml:"ddos_protection,omitempty"`
104+
KRT bool `yaml:"krt,omitempty"`
104105
}
105106

106107
// New creates a new config

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ var (
8888
macsecEnabled = flag.Bool("macsec.enabled", true, "Scrape MACSec metrics")
8989
arpEnabled = flag.Bool("arps.enabled", true, "Scrape ARP metrics")
9090
poeEnabled = flag.Bool("poe.enabled", true, "Scrape PoE metrics")
91+
krtEnabled = flag.Bool("krt.enabled", false, "Scrape KRT queue metrics")
9192
cfg *config.Config
9293
devices []*connector.Device
9394
connManager *connector.SSHConnectionManager
@@ -262,6 +263,7 @@ func loadConfigFromFlags() *config.Config {
262263
f.MACSec = *macsecEnabled
263264
f.ARP = *arpEnabled
264265
f.Poe = *poeEnabled
266+
f.KRT = *krtEnabled
265267
return c
266268
}
267269

pkg/features/krt/collector.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package krt
2+
3+
import (
4+
"github.com/pkg/errors"
5+
"github.com/prometheus/client_golang/prometheus"
6+
7+
"github.com/czerwonk/junos_exporter/pkg/collector"
8+
)
9+
10+
const prefix string = "junos_krt"
11+
12+
var (
13+
queueLengthDesc *prometheus.Desc
14+
)
15+
16+
func init() {
17+
l := []string{"target", "krtq_type"}
18+
queueLengthDesc = prometheus.NewDesc(prefix+"krt_queue_length", "KRT queue length", l, nil)
19+
}
20+
21+
type krtCollector struct{}
22+
23+
func NewCollector() collector.RPCCollector { return &krtCollector{} }
24+
25+
func (c *krtCollector) Name() string { return "krt" }
26+
27+
func (c *krtCollector) Describe(ch chan<- *prometheus.Desc) {
28+
ch <- queueLengthDesc
29+
}
30+
31+
func (c *krtCollector) Collect(client collector.Client, ch chan<- prometheus.Metric, labelValues []string) error {
32+
var k resultKRT
33+
err := client.RunCommandAndParse("show krt queue", &k)
34+
if err != nil {
35+
return errors.Wrap(err, "failed to run command 'show krt queue'")
36+
}
37+
c.collectKRT(k, ch, labelValues)
38+
return nil
39+
}
40+
41+
func (c *krtCollector) collectKRT(k resultKRT, ch chan<- prometheus.Metric, labelValues []string) {
42+
for _, q := range k.KrtQueueInformation.KrtQueue {
43+
labels := append(labelValues, q.KrtqType)
44+
ch <- prometheus.MustNewConstMetric(queueLengthDesc, prometheus.GaugeValue, q.KrtqQueueLength, labels...)
45+
}
46+
}

pkg/features/krt/rpc.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package krt
2+
3+
import "encoding/xml"
4+
5+
type resultKRT struct {
6+
XMLName xml.Name `xml:"rpc-reply"`
7+
Text string `xml:",chardata"`
8+
Junos string `xml:"junos,attr"`
9+
KrtQueueInformation struct {
10+
Text string `xml:",chardata"`
11+
Xmlns string `xml:"xmlns,attr"`
12+
KrtQueue []struct {
13+
Text string `xml:",chardata"`
14+
KrtqType string `xml:"krtq-type"`
15+
KrtqQueueLength float64 `xml:"krtq-queue-length"`
16+
} `xml:"krt-queue"`
17+
} `xml:"krt-queue-information"`
18+
Cli struct {
19+
Text string `xml:",chardata"`
20+
Banner string `xml:"banner"`
21+
} `xml:"cli"`
22+
}

pkg/features/krt/rpc_test.go

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
package krt
2+
3+
import (
4+
"encoding/xml"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
)
9+
10+
func TestParseXML(t *testing.T) {
11+
resultsData := `
12+
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/23.4R2-S3.9/junos">
13+
<krt-queue-information xmlns="http://xml.juniper.net/junos/23.4R0/junos-routing">
14+
<krt-queue>
15+
<krtq-type>Routing table add queue</krtq-type>
16+
<krtq-queue-length>1</krtq-queue-length>
17+
</krt-queue>
18+
<krt-queue>
19+
<krtq-type>Interface add/delete/change queue</krtq-type>
20+
<krtq-queue-length>11</krtq-queue-length>
21+
</krt-queue>
22+
<krt-queue>
23+
<krtq-type>Top-priority deletion queue</krtq-type>
24+
<krtq-queue-length>111</krtq-queue-length>
25+
</krt-queue>
26+
<krt-queue>
27+
<krtq-type>Top-priority change queue</krtq-type>
28+
<krtq-queue-length>1111</krtq-queue-length>
29+
</krt-queue>
30+
<krt-queue>
31+
<krtq-type>Top-priority add queue</krtq-type>
32+
<krtq-queue-length>11111</krtq-queue-length>
33+
</krt-queue>
34+
<krt-queue>
35+
<krtq-type>high priority V4oV6 tcnh delete queue</krtq-type>
36+
<krtq-queue-length>111111</krtq-queue-length>
37+
</krt-queue>
38+
<krt-queue>
39+
<krtq-type>high prioriy anchor gencfg delete queue</krtq-type>
40+
<krtq-queue-length>2</krtq-queue-length>
41+
</krt-queue>
42+
<krt-queue>
43+
<krtq-type>High-priority multicast add/change</krtq-type>
44+
<krtq-queue-length>22</krtq-queue-length>
45+
</krt-queue>
46+
<krt-queue>
47+
<krtq-type>Indirect next hop top priority add/change</krtq-type>
48+
<krtq-queue-length>222</krtq-queue-length>
49+
</krt-queue>
50+
<krt-queue>
51+
<krtq-type>Indirect next hop add/change</krtq-type>
52+
<krtq-queue-length>2222</krtq-queue-length>
53+
</krt-queue>
54+
<krt-queue>
55+
<krtq-type>high prioriy anchor gencfg add-change queue</krtq-type>
56+
<krtq-queue-length>22222</krtq-queue-length>
57+
</krt-queue>
58+
<krt-queue>
59+
<krtq-type>MPLS add queue</krtq-type>
60+
<krtq-queue-length>222222</krtq-queue-length>
61+
</krt-queue>
62+
<krt-queue>
63+
<krtq-type>Indirect next hop delete</krtq-type>
64+
<krtq-queue-length>0</krtq-queue-length>
65+
</krt-queue>
66+
<krt-queue>
67+
<krtq-type>High-priority deletion queue</krtq-type>
68+
<krtq-queue-length>0</krtq-queue-length>
69+
</krt-queue>
70+
<krt-queue>
71+
<krtq-type>MPLS change queue</krtq-type>
72+
<krtq-queue-length>0</krtq-queue-length>
73+
</krt-queue>
74+
<krt-queue>
75+
<krtq-type>High-priority change queue</krtq-type>
76+
<krtq-queue-length>0</krtq-queue-length>
77+
</krt-queue>
78+
<krt-queue>
79+
<krtq-type>High-priority add queue</krtq-type>
80+
<krtq-queue-length>0</krtq-queue-length>
81+
</krt-queue>
82+
<krt-queue>
83+
<krtq-type>Normal-priority indirect next hop queue</krtq-type>
84+
<krtq-queue-length>0</krtq-queue-length>
85+
</krt-queue>
86+
<krt-queue>
87+
<krtq-type>Normal-priority deletion queue</krtq-type>
88+
<krtq-queue-length>0</krtq-queue-length>
89+
</krt-queue>
90+
<krt-queue>
91+
<krtq-type>Normal-priority composite next hop deletion queue</krtq-type>
92+
<krtq-queue-length>0</krtq-queue-length>
93+
</krt-queue>
94+
<krt-queue>
95+
<krtq-type>Low prioriy Statistics-id-group deletion queue</krtq-type>
96+
<krtq-queue-length>0</krtq-queue-length>
97+
</krt-queue>
98+
<krt-queue>
99+
<krtq-type>Normal-priority change queue</krtq-type>
100+
<krtq-queue-length>0</krtq-queue-length>
101+
</krt-queue>
102+
<krt-queue>
103+
<krtq-type>Normal-priority add queue</krtq-type>
104+
<krtq-queue-length>0</krtq-queue-length>
105+
</krt-queue>
106+
<krt-queue>
107+
<krtq-type>Least-priority delete queue</krtq-type>
108+
<krtq-queue-length>0</krtq-queue-length>
109+
</krt-queue>
110+
<krt-queue>
111+
<krtq-type>Least-priority change queue</krtq-type>
112+
<krtq-queue-length>0</krtq-queue-length>
113+
</krt-queue>
114+
<krt-queue>
115+
<krtq-type>Least-priority add queue</krtq-type>
116+
<krtq-queue-length>0</krtq-queue-length>
117+
</krt-queue>
118+
<krt-queue>
119+
<krtq-type>Normal-priority pfe table nexthop queue</krtq-type>
120+
<krtq-queue-length>0</krtq-queue-length>
121+
</krt-queue>
122+
<krt-queue>
123+
<krtq-type>EVPN gencfg queue</krtq-type>
124+
<krtq-queue-length>0</krtq-queue-length>
125+
</krt-queue>
126+
<krt-queue>
127+
<krtq-type>Normal-priority gmp queue</krtq-type>
128+
<krtq-queue-length>0</krtq-queue-length>
129+
</krt-queue>
130+
<krt-queue>
131+
<krtq-type>Routing table delete queue</krtq-type>
132+
<krtq-queue-length>0</krtq-queue-length>
133+
</krt-queue>
134+
<krt-queue>
135+
<krtq-type>Low priority route retry queue</krtq-type>
136+
<krtq-queue-length>0</krtq-queue-length>
137+
</krt-queue>
138+
<krt-queue>
139+
<krtq-type>Priority queue dependency management system</krtq-type>
140+
<krtq-queue-length>0</krtq-queue-length>
141+
</krt-queue>
142+
</krt-queue-information>
143+
<cli>
144+
<banner></banner>
145+
</cli>
146+
</rpc-reply>`
147+
148+
var results resultKRT
149+
150+
// Parse the XML data for krt queue
151+
err := xml.Unmarshal([]byte(resultsData), &results)
152+
assert.NoError(t, err)
153+
// check the values pf queue length
154+
assert.Equal(t, float64(1), results.KrtQueueInformation.KrtQueue[0].KrtqQueueLength)
155+
assert.Equal(t, float64(11), results.KrtQueueInformation.KrtQueue[1].KrtqQueueLength)
156+
assert.Equal(t, float64(111), results.KrtQueueInformation.KrtQueue[2].KrtqQueueLength)
157+
assert.Equal(t, float64(1111), results.KrtQueueInformation.KrtQueue[3].KrtqQueueLength)
158+
assert.Equal(t, float64(11111), results.KrtQueueInformation.KrtQueue[4].KrtqQueueLength)
159+
assert.Equal(t, float64(111111), results.KrtQueueInformation.KrtQueue[5].KrtqQueueLength)
160+
assert.Equal(t, float64(2), results.KrtQueueInformation.KrtQueue[6].KrtqQueueLength)
161+
assert.Equal(t, float64(22), results.KrtQueueInformation.KrtQueue[7].KrtqQueueLength)
162+
assert.Equal(t, float64(222), results.KrtQueueInformation.KrtQueue[8].KrtqQueueLength)
163+
assert.Equal(t, float64(2222), results.KrtQueueInformation.KrtQueue[9].KrtqQueueLength)
164+
assert.Equal(t, float64(22222), results.KrtQueueInformation.KrtQueue[10].KrtqQueueLength)
165+
assert.Equal(t, float64(222222), results.KrtQueueInformation.KrtQueue[11].KrtqQueueLength)
166+
assert.Equal(t, float64(0), results.KrtQueueInformation.KrtQueue[12].KrtqQueueLength)
167+
}

0 commit comments

Comments
 (0)