aboutsummaryrefslogtreecommitdiff
path: root/cmd/six_monitor/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/six_monitor/main.go')
-rw-r--r--cmd/six_monitor/main.go250
1 files changed, 250 insertions, 0 deletions
diff --git a/cmd/six_monitor/main.go b/cmd/six_monitor/main.go
new file mode 100644
index 0000000..cd41d8f
--- /dev/null
+++ b/cmd/six_monitor/main.go
@@ -0,0 +1,250 @@
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (C) 2020 Michael Crute <mike@crute.us>. All rights reserved.
3//
4// Use of this source code is governed by a license that can be found in the
5// LICENSE file.
6
7package main
8
9import (
10 "flag"
11 "fmt"
12 "log"
13 "net/http"
14 _ "net/http/pprof"
15 "os"
16 "strconv"
17
18 "github.com/prometheus/client_golang/prometheus"
19 "github.com/prometheus/client_golang/prometheus/promhttp"
20 "github.com/prometheus/common/version"
21
22 "code.crute.me/pomonaconsulting/six_monitoring/six"
23)
24
25const (
26 namespace = "sixstatus"
27 exporter = "six_status_exporter"
28)
29
30var (
31 up = prometheus.NewDesc(
32 prometheus.BuildFQName(namespace, "", "up"),
33 "Was the SIX query successful?",
34 nil, nil,
35 )
36 rsPrefixCount = prometheus.NewDesc(
37 prometheus.BuildFQName(namespace, "route_server", "prefix_count"),
38 "Number of prefixes advertised to a route server.",
39 []string{"ipversion", "mtu", "server"}, nil,
40 )
41 rsErrorCount = prometheus.NewDesc(
42 prometheus.BuildFQName(namespace, "route_server", "error_count"),
43 "Number of errors reported by a route server.",
44 []string{"ipversion", "mtu", "server"}, nil,
45 )
46 rsTransitErrorCount = prometheus.NewDesc(
47 prometheus.BuildFQName(namespace, "route_server", "transit_error_count"),
48 "Number of transit errors reported by a route server.",
49 []string{"ipversion", "mtu", "server"}, nil,
50 )
51 irrPrefixCount = prometheus.NewDesc(
52 prometheus.BuildFQName(namespace, "irr", "prefix_count"),
53 "Number of prefixes resolved from IRR records.",
54 []string{"ipversion"}, nil,
55 )
56 irrASNCount = prometheus.NewDesc(
57 prometheus.BuildFQName(namespace, "irr", "asn_count"),
58 "Number of ASNs resolved from IRR records.",
59 []string{"ipversion"}, nil,
60 )
61 irrAsSetPrefixCount = prometheus.NewDesc(
62 prometheus.BuildFQName(namespace, "irr", "as_set_prefix_count"),
63 "Number of prefixes in the AS-SET resolved from IRR records.",
64 []string{"ipversion"}, nil,
65 )
66 pdbPrefixCount = prometheus.NewDesc(
67 prometheus.BuildFQName(namespace, "peeringdb", "prefix_count"),
68 "Number of prefixes configured in PeeringDB.",
69 []string{"ipversion"}, nil,
70 )
71 roaCount = prometheus.NewDesc(
72 prometheus.BuildFQName(namespace, "", "roa_count"),
73 "Number of resolved ROA records.",
74 nil, nil,
75 )
76)
77
78type SIXCollector struct {
79 ASN int
80}
81
82var _ prometheus.Collector = (*SIXCollector)(nil)
83
84func (c *SIXCollector) Describe(ch chan<- *prometheus.Desc) {
85 ch <- up
86 ch <- rsPrefixCount
87 ch <- rsErrorCount
88 ch <- rsTransitErrorCount
89 ch <- irrPrefixCount
90 ch <- irrASNCount
91 ch <- irrAsSetPrefixCount
92 ch <- pdbPrefixCount
93 ch <- roaCount
94}
95
96func routeServerMetrics(rs *six.RouteServer, ch chan<- prometheus.Metric) {
97 ch <- prometheus.MustNewConstMetric(
98 rsPrefixCount, prometheus.GaugeValue, float64(rs.IPv4.Prefixes),
99 "4", "1500", string(strconv.Itoa(rs.Number)),
100 )
101 ch <- prometheus.MustNewConstMetric(
102 rsErrorCount, prometheus.GaugeValue, float64(rs.IPv4.Errors),
103 "4", "1500", string(strconv.Itoa(rs.Number)),
104 )
105 ch <- prometheus.MustNewConstMetric(
106 rsTransitErrorCount, prometheus.GaugeValue, float64(rs.IPv4.TransitErrors),
107 "4", "1500", string(strconv.Itoa(rs.Number)),
108 )
109 ch <- prometheus.MustNewConstMetric(
110 rsPrefixCount, prometheus.GaugeValue, float64(rs.IPv6.Prefixes),
111 "6", "1500", string(strconv.Itoa(rs.Number)),
112 )
113 ch <- prometheus.MustNewConstMetric(
114 rsErrorCount, prometheus.GaugeValue, float64(rs.IPv6.Errors),
115 "6", "1500", string(strconv.Itoa(rs.Number)),
116 )
117 ch <- prometheus.MustNewConstMetric(
118 rsTransitErrorCount, prometheus.GaugeValue, float64(rs.IPv6.TransitErrors),
119 "6", "1500", string(strconv.Itoa(rs.Number)),
120 )
121 ch <- prometheus.MustNewConstMetric(
122 rsPrefixCount, prometheus.GaugeValue, float64(rs.IPv4Jumbo.Prefixes),
123 "4", "9000", string(strconv.Itoa(rs.Number)),
124 )
125 ch <- prometheus.MustNewConstMetric(
126 rsErrorCount, prometheus.GaugeValue, float64(rs.IPv4Jumbo.Errors),
127 "4", "9000", string(strconv.Itoa(rs.Number)),
128 )
129 ch <- prometheus.MustNewConstMetric(
130 rsTransitErrorCount, prometheus.GaugeValue, float64(rs.IPv4Jumbo.TransitErrors),
131 "4", "9000", string(strconv.Itoa(rs.Number)),
132 )
133 ch <- prometheus.MustNewConstMetric(
134 rsPrefixCount, prometheus.GaugeValue, float64(rs.IPv6Jumbo.Prefixes),
135 "6", "9000", string(strconv.Itoa(rs.Number)),
136 )
137 ch <- prometheus.MustNewConstMetric(
138 rsErrorCount, prometheus.GaugeValue, float64(rs.IPv6Jumbo.Errors),
139 "6", "9000", string(strconv.Itoa(rs.Number)),
140 )
141 ch <- prometheus.MustNewConstMetric(
142 rsTransitErrorCount, prometheus.GaugeValue, float64(rs.IPv6Jumbo.TransitErrors),
143 "6", "9000", string(strconv.Itoa(rs.Number)),
144 )
145}
146
147func (c *SIXCollector) Collect(ch chan<- prometheus.Metric) {
148 sp, err := six.FetchParseSIXCSV()
149 if err != nil {
150 log.Printf("error: Fetching and parsing CSV: %s", err)
151 ch <- prometheus.MustNewConstMetric(up, prometheus.GaugeValue, 0)
152 return
153 }
154
155 ps, ok := sp.GetParticipantByASN(c.ASN)
156 if !ok {
157 log.Printf("error: No participant for ASN: %d", c.ASN)
158 ch <- prometheus.MustNewConstMetric(up, prometheus.GaugeValue, 0)
159 return
160 }
161
162 p := ps[0]
163
164 ch <- prometheus.MustNewConstMetric(up, prometheus.GaugeValue, 1)
165
166 // ipversion, mtu, server
167
168 if p.RouteServer2 != nil {
169 routeServerMetrics(p.RouteServer2, ch)
170 }
171
172 if p.RouteServer3 != nil {
173 routeServerMetrics(p.RouteServer3, ch)
174 }
175
176 ch <- prometheus.MustNewConstMetric(
177 irrPrefixCount, prometheus.GaugeValue, float64(p.IRRv4.PrefixCount),
178 "4",
179 )
180 ch <- prometheus.MustNewConstMetric(
181 irrASNCount, prometheus.GaugeValue, float64(p.IRRv4.ASNCount),
182 "4",
183 )
184 ch <- prometheus.MustNewConstMetric(
185 irrAsSetPrefixCount, prometheus.GaugeValue, float64(p.IRRv4.ASSetCount),
186 "4",
187 )
188 ch <- prometheus.MustNewConstMetric(
189 pdbPrefixCount, prometheus.GaugeValue, float64(p.PeeringDBPrefixCountv4),
190 "4",
191 )
192 ch <- prometheus.MustNewConstMetric(
193 irrPrefixCount, prometheus.GaugeValue, float64(p.IRRv6.PrefixCount),
194 "6",
195 )
196 ch <- prometheus.MustNewConstMetric(
197 irrASNCount, prometheus.GaugeValue, float64(p.IRRv6.ASNCount),
198 "6",
199 )
200 ch <- prometheus.MustNewConstMetric(
201 irrAsSetPrefixCount, prometheus.GaugeValue, float64(p.IRRv6.ASSetCount),
202 "6",
203 )
204 ch <- prometheus.MustNewConstMetric(
205 pdbPrefixCount, prometheus.GaugeValue, float64(p.PeeringDBPrefixCountv6),
206 "6",
207 )
208
209 ch <- prometheus.MustNewConstMetric(roaCount, prometheus.GaugeValue, float64(p.ROACount))
210}
211
212func main() {
213 var (
214 showVersion = flag.Bool("version", false, "Print version information.")
215 listenAddress = flag.String("web.listen-address", ":9119", "Address to listen on for web interface and telemetry.")
216 )
217 flag.Parse()
218
219 if len(os.Args) != 2 {
220 fmt.Fprintf(os.Stdout, "usage: %s <ASN>\n", os.Args[0])
221 os.Exit(1)
222 }
223
224 asn, err := strconv.Atoi(os.Args[1])
225 if err != nil {
226 fmt.Fprintln(os.Stdout, "invalid ASN, must be numeric")
227 fmt.Fprintf(os.Stdout, "usage: %s <ASN>\n", os.Args[0])
228 os.Exit(1)
229 }
230
231 if *showVersion {
232 fmt.Fprintln(os.Stdout, version.Print(exporter))
233 os.Exit(0)
234 }
235 log.Println("Starting", exporter, version.Info())
236 log.Println("Build context", version.BuildContext())
237
238 prometheus.MustRegister(version.NewCollector(exporter), &SIXCollector{asn})
239
240 log.Println("Starting Server: ", *listenAddress)
241 http.Handle("/metrics", promhttp.Handler())
242 http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
243 w.Write([]byte(`<html>
244 <head><title>SIX Status Exporter</title></head><body>
245 <h1>SIX Status Exporter</h1>
246 <p><a href="/metrics">Metrics</a></p>
247 </body></html>`))
248 })
249 log.Fatal(http.ListenAndServe(*listenAddress, nil))
250}