diff --git a/cmd/ris-mirror/rismirror/metrics/ris_mirror_metrics.go b/cmd/ris-mirror/rismirror/metrics/ris_mirror_metrics.go index 5b81d2870972404931fd655be19054aa54f30a4b..3d8948cb7c22582a52d60c687886b20d3396e746 100644 --- a/cmd/ris-mirror/rismirror/metrics/ris_mirror_metrics.go +++ b/cmd/ris-mirror/rismirror/metrics/ris_mirror_metrics.go @@ -3,6 +3,7 @@ package metrics import ( "net" + mlrib_metrics "github.com/bio-routing/bio-rd/routingtable/mergedlocrib/metrics" vrf_metrics "github.com/bio-routing/bio-rd/routingtable/vrf/metrics" ) @@ -13,12 +14,15 @@ type RISMirrorMetrics struct { // RISMirrorRouterMetrics contains a routers RIS mirror metrics type RISMirrorRouterMetrics struct { - // Routers IP Address - Address net.IP - - // SysName of the monitored router - SysName string + Address net.IP + SysName string + VRFMetrics []*vrf_metrics.VRFMetrics + InternalVRFMetrics []*InternalVRFMetrics +} - // VRFMetrics represent per VRF metrics - VRFMetrics []*vrf_metrics.VRFMetrics +// InternalVRFMetrics represents internal VRF metrics (_vrf) +type InternalVRFMetrics struct { + RD uint64 + MergedLocRIBMetricsIPv4Unicast *mlrib_metrics.MergedLocRIBMetrics + MergedLocRIBMetricsIPv6Unicast *mlrib_metrics.MergedLocRIBMetrics } diff --git a/cmd/ris-mirror/rismirror/rismirror.go b/cmd/ris-mirror/rismirror/rismirror.go index 897b8e073b9ffa1280d106038c74610847d62fcb..3fed598fbbeb48ae89ff6ceee9f2d90a91285766 100644 --- a/cmd/ris-mirror/rismirror/rismirror.go +++ b/cmd/ris-mirror/rismirror/rismirror.go @@ -58,6 +58,7 @@ func (rism *RISMirror) GetRouters() []server.RouterInterface { return res } +// Metrics gets a RISMirrors metrics func (rism *RISMirror) Metrics() *metrics.RISMirrorMetrics { res := &metrics.RISMirrorMetrics{ Routers: make([]*metrics.RISMirrorRouterMetrics, 0), @@ -68,9 +69,18 @@ func (rism *RISMirror) Metrics() *metrics.RISMirrorMetrics { for _, r := range rism.routers { rm := &metrics.RISMirrorRouterMetrics{ - Address: r.Address(), - SysName: r.Name(), - VRFMetrics: vrf.Metrics(r.(*Router).vrfRegistry), + Address: r.Address(), + SysName: r.Name(), + VRFMetrics: vrf.Metrics(r.(*Router).vrfRegistry), + InternalVRFMetrics: make([]*metrics.InternalVRFMetrics, 0), + } + + for rd, v := range r.(*Router).vrfs { + rm.InternalVRFMetrics = append(rm.InternalVRFMetrics, &metrics.InternalVRFMetrics{ + RD: rd, + MergedLocRIBMetricsIPv4Unicast: v.ipv4Unicast.Metrics(), + MergedLocRIBMetricsIPv6Unicast: v.ipv6Unicast.Metrics(), + }) } res.Routers = append(res.Routers, rm) diff --git a/cmd/ris-mirror/rismirror/router.go b/cmd/ris-mirror/rismirror/router.go index 38a6fec83cd98a1c1e80510ae13d8ab981cdc9a1..eb8cb8061c19994160ee33dec07af0523ae4356c 100644 --- a/cmd/ris-mirror/rismirror/router.go +++ b/cmd/ris-mirror/rismirror/router.go @@ -60,11 +60,13 @@ func (r *Router) addVRF(rd uint64, sources []*grpc.ClientConn) { } func (r *Router) connectVRF(rd uint64, src *grpc.ClientConn, afi uint8) { - risclient.New(&risclient.Request{ + rc := risclient.New(&risclient.Request{ Router: r.name, VRFRD: rd, AFI: apiAFI(afi), }, src, r.vrfs[rd].getRIB(afi)) + + rc.Start() } func apiAFI(afi uint8) api.ObserveRIBRequest_AFISAFI { diff --git a/metrics/ris-mirror/adapter/prom/ris_mirror_prom_adapter.go b/metrics/ris-mirror/adapter/prom/ris_mirror_prom_adapter.go index 405a2e1e3a7e8469c1bb41660ff8d1c64e5836db..da40d8df8274eec72abdbaa2c15dc669fa020ea6 100644 --- a/metrics/ris-mirror/adapter/prom/ris_mirror_prom_adapter.go +++ b/metrics/ris-mirror/adapter/prom/ris_mirror_prom_adapter.go @@ -1,8 +1,12 @@ package prom import ( + "fmt" + "github.com/bio-routing/bio-rd/cmd/ris-mirror/rismirror" "github.com/bio-routing/bio-rd/cmd/ris-mirror/rismirror/metrics" + "github.com/bio-routing/bio-rd/protocols/bgp/packet" + "github.com/bio-routing/bio-rd/routingtable/vrf" "github.com/prometheus/client_golang/prometheus" vrf_prom "github.com/bio-routing/bio-rd/metrics/vrf/adapter/prom" @@ -12,6 +16,17 @@ const ( prefix = "bio_rismirror_" ) +var ( + mergedLocalRIBRouteCount *prometheus.Desc + mergedLocalRIBSingleSourceRouteCount *prometheus.Desc +) + +func init() { + labels := []string{"sys_name", "agent_address", "vrf", "afi", "rib"} + mergedLocalRIBRouteCount = prometheus.NewDesc(prefix+"merged_locrib_route_count", "Number of unique routes", labels, nil) + mergedLocalRIBSingleSourceRouteCount = prometheus.NewDesc(prefix+"merged_locrib_single_source_route_count", "Number of routes seen from single source", labels, nil) +} + // NewCollector creates a new collector instance for the given RIS mirror server func NewCollector(risMirror *rismirror.RISMirror) prometheus.Collector { return &risCollector{ @@ -26,6 +41,9 @@ type risCollector struct { // Describe conforms to the prometheus collector interface func (c *risCollector) Describe(ch chan<- *prometheus.Desc) { + ch <- mergedLocalRIBRouteCount + ch <- mergedLocalRIBSingleSourceRouteCount + vrf_prom.DescribeRouter(ch) } @@ -40,4 +58,32 @@ func (c *risCollector) collectForRouter(ch chan<- prometheus.Metric, rtr *metric for _, vrfMetric := range rtr.VRFMetrics { vrf_prom.CollectForVRFRouter(ch, rtr.SysName, rtr.Address.String(), vrfMetric) } + + for _, x := range rtr.InternalVRFMetrics { + c.collectMergedLocRIBMetrics(ch, rtr, x) + } +} + +func (c *risCollector) collectMergedLocRIBMetrics(ch chan<- prometheus.Metric, rtr *metrics.RISMirrorRouterMetrics, v *metrics.InternalVRFMetrics) { + ch <- prometheus.MustNewConstMetric(mergedLocalRIBRouteCount, prometheus.GaugeValue, float64(v.MergedLocRIBMetricsIPv4Unicast.UniqueRouteCount), + getMergedLocRIBMetricsLabels(rtr, v, packet.IPv4AFI)...) + + ch <- prometheus.MustNewConstMetric(mergedLocalRIBRouteCount, prometheus.GaugeValue, float64(v.MergedLocRIBMetricsIPv6Unicast.UniqueRouteCount), + getMergedLocRIBMetricsLabels(rtr, v, packet.IPv6AFI)...) + + ch <- prometheus.MustNewConstMetric(mergedLocalRIBSingleSourceRouteCount, prometheus.GaugeValue, float64(v.MergedLocRIBMetricsIPv4Unicast.RoutesWithSingleSourceCount), + getMergedLocRIBMetricsLabels(rtr, v, packet.IPv4AFI)...) + + ch <- prometheus.MustNewConstMetric(mergedLocalRIBSingleSourceRouteCount, prometheus.GaugeValue, float64(v.MergedLocRIBMetricsIPv6Unicast.RoutesWithSingleSourceCount), + getMergedLocRIBMetricsLabels(rtr, v, packet.IPv6AFI)...) +} + +func getMergedLocRIBMetricsLabels(rtr *metrics.RISMirrorRouterMetrics, v *metrics.InternalVRFMetrics, afi uint8) []string { + ret := []string{rtr.SysName, rtr.Address.String(), vrf.RouteDistinguisherHumanReadable(v.RD), fmt.Sprintf("%d", afi)} + + if afi == packet.IPv4AFI { + return append(ret, v.MergedLocRIBMetricsIPv4Unicast.RIBName) + } + + return append(ret, v.MergedLocRIBMetricsIPv6Unicast.RIBName) } diff --git a/routingtable/mergedlocrib/mergedlocrib.go b/routingtable/mergedlocrib/mergedlocrib.go index efcc9023a363b54f5a9a3b8205063849d15eb5d7..94d431ed9dabd063e0f1e6e5052f778a448c24fb 100644 --- a/routingtable/mergedlocrib/mergedlocrib.go +++ b/routingtable/mergedlocrib/mergedlocrib.go @@ -7,6 +7,7 @@ import ( "github.com/bio-routing/bio-rd/route" routeapi "github.com/bio-routing/bio-rd/route/api" "github.com/bio-routing/bio-rd/routingtable/locRIB" + "github.com/bio-routing/bio-rd/routingtable/mergedlocrib/metrics" "github.com/golang/protobuf/proto" "github.com/pkg/errors" ) @@ -14,7 +15,7 @@ import ( // MergedLocRIB provides an deduplicated routing table type MergedLocRIB struct { routes map[[20]byte]*routeContainer - routesMu sync.Mutex + routesMu sync.RWMutex locRIB *locRIB.LocRIB } @@ -104,3 +105,27 @@ func hashRoute(route *routeapi.Route) ([20]byte, error) { return res, nil } + +// Metrics gets the metrics +func (rtm *MergedLocRIB) Metrics() *metrics.MergedLocRIBMetrics { + rtm.routesMu.RLock() + defer rtm.routesMu.RUnlock() + + return &metrics.MergedLocRIBMetrics{ + RIBName: rtm.locRIB.Name(), + UniqueRouteCount: uint64(len(rtm.routes)), + RoutesWithSingleSourceCount: rtm._getRoutesWithSingleSourceCount(), + } +} + +func (rtm *MergedLocRIB) _getRoutesWithSingleSourceCount() uint64 { + n := uint64(0) + + for _, r := range rtm.routes { + if len(r.sources) == 1 { + n++ + } + } + + return n +}