diff --git a/cmd/ris-mirror/main.go b/cmd/ris-mirror/main.go
index f61e50e65f4884b1e5a27a2d71e38efc613b57ca..d7ff7ceee7d6b126e5db804811d8461bb71a62dc 100644
--- a/cmd/ris-mirror/main.go
+++ b/cmd/ris-mirror/main.go
@@ -8,14 +8,15 @@ import (
 
 	"github.com/bio-routing/bio-rd/cmd/ris-mirror/config"
 	"github.com/bio-routing/bio-rd/cmd/ris-mirror/rismirror"
+	pb "github.com/bio-routing/bio-rd/cmd/ris/api"
 	"github.com/bio-routing/bio-rd/cmd/ris/risserver"
+	prom_ris_mirror "github.com/bio-routing/bio-rd/metrics/ris-mirror/adapter/prom"
 	"github.com/bio-routing/bio-rd/routingtable/vrf"
 	"github.com/bio-routing/bio-rd/util/servicewrapper"
+	"github.com/prometheus/client_golang/prometheus"
 	log "github.com/sirupsen/logrus"
 	"google.golang.org/grpc"
 	"google.golang.org/grpc/keepalive"
-
-	pb "github.com/bio-routing/bio-rd/cmd/ris/api"
 )
 
 var (
@@ -36,6 +37,7 @@ func main() {
 
 	risInstances := connectAllRISInstances(cfg.GetRISInstances())
 	m := rismirror.New()
+	prometheus.MustRegister(prom_ris_mirror.NewCollector(m))
 
 	for _, rcfg := range cfg.RIBConfigs {
 		for _, vrfHumanReadable := range rcfg.VRFs {
diff --git a/cmd/ris-mirror/rismirror/mirror.go b/cmd/ris-mirror/rismirror/mirror.go
index a40d4dd8b57eb05944b8c35f113663b1cc07adb0..dcdca7399117b0abc24f9ff1c43af388fb0adc5a 100644
--- a/cmd/ris-mirror/rismirror/mirror.go
+++ b/cmd/ris-mirror/rismirror/mirror.go
@@ -7,6 +7,8 @@ import (
 
 	"github.com/bio-routing/bio-rd/cmd/ris-mirror/rtmirror"
 	"github.com/bio-routing/bio-rd/protocols/bgp/server"
+	"github.com/bio-routing/bio-rd/protocols/ris/metrics"
+	"github.com/bio-routing/bio-rd/routingtable/vrf"
 	"google.golang.org/grpc"
 )
 
@@ -22,7 +24,7 @@ func New() *RISMirror {
 	}
 }
 
-func (rism *RISMirror) AddTarget(rtrName string, address net.IP, vrf uint64, sources []*grpc.ClientConn) {
+func (rism *RISMirror) AddTarget(rtrName string, address net.IP, vrfRD uint64, sources []*grpc.ClientConn) {
 	rism.routersMu.Lock()
 	defer rism.routersMu.Unlock()
 
@@ -30,12 +32,16 @@ func (rism *RISMirror) AddTarget(rtrName string, address net.IP, vrf uint64, sou
 		rism.routers[rtrName] = newRouter(rtrName, address)
 	}
 
-	v := rism.routers[rtrName].(*Router).vrfRegistry.CreateVRFIfNotExists(fmt.Sprintf("%d", vrf), vrf)
+	v := rism.routers[rtrName].(*Router).vrfRegistry.GetVRFByRD(vrfRD)
+	if v == nil {
+		v = rism.routers[rtrName].(*Router).vrfRegistry.CreateVRFIfNotExists(fmt.Sprintf("%d", vrfRD), vrfRD)
+		rtm := rtmirror.New(rtmirror.Config{
+			Router: rtrName,
+			VRF:    v,
+		})
 
-	rtmirror.New(sources, rtmirror.Config{
-		Router: rtrName,
-		VRF:    v,
-	})
+		rism.routers[rtrName].(*Router).rtMirrors[vrfRD] = rtm
+	}
 }
 
 // GetRouter gets a router
@@ -60,3 +66,25 @@ func (rism *RISMirror) GetRouters() []server.RouterInterface {
 
 	return res
 }
+
+func (rism *RISMirror) Metrics() *metrics.RISMirrorMetrics {
+	res := &metrics.RISMirrorMetrics{
+		Routers: make([]*metrics.RISMirrorRouterMetrics, 0),
+	}
+
+	rism.routersMu.Lock()
+	defer rism.routersMu.Unlock()
+
+	for _, r := range rism.routers {
+		rm := &metrics.RISMirrorRouterMetrics{
+			Address:    r.Address(),
+			SysName:    r.Name(),
+			VRFMetrics: vrf.Metrics(r.(*Router).vrfRegistry),
+			// TODO: RISUpstreamStatus: Fill In,
+		}
+
+		res.Routers = append(res.Routers, rm)
+	}
+
+	return res
+}
diff --git a/cmd/ris-mirror/rismirror/router.go b/cmd/ris-mirror/rismirror/router.go
index 4f1ded5c42f69ad71859c5e76ecc97235ddbfff4..c8b4913fa2a8496d59ce2af6591d3f23b4428507 100644
--- a/cmd/ris-mirror/rismirror/router.go
+++ b/cmd/ris-mirror/rismirror/router.go
@@ -3,6 +3,7 @@ package rismirror
 import (
 	"net"
 
+	"github.com/bio-routing/bio-rd/cmd/ris-mirror/rtmirror"
 	"github.com/bio-routing/bio-rd/routingtable/vrf"
 )
 
@@ -11,6 +12,9 @@ type Router struct {
 	name        string
 	address     net.IP
 	vrfRegistry *vrf.VRFRegistry
+
+	// rtMirrors contains RTMirrors organized by VRF route distinguisher
+	rtMirrors map[uint64]*rtmirror.RTMirror
 }
 
 func newRouter(name string, address net.IP) *Router {
@@ -18,6 +22,7 @@ func newRouter(name string, address net.IP) *Router {
 		name:        name,
 		address:     address,
 		vrfRegistry: vrf.NewVRFRegistry(),
+		rtMirrors:   make(map[uint64]*rtmirror.RTMirror),
 	}
 }
 
diff --git a/cmd/ris-mirror/rtmirror/routecontainer.go b/cmd/ris-mirror/rtmirror/routecontainer.go
index 866db553d613c42392e13b627da100ec0af46a77..281bfabb5b78f2fea0f5e3933ecfe99e6e3bcca5 100644
--- a/cmd/ris-mirror/rtmirror/routecontainer.go
+++ b/cmd/ris-mirror/rtmirror/routecontainer.go
@@ -2,27 +2,26 @@ package rtmirror
 
 import (
 	routeapi "github.com/bio-routing/bio-rd/route/api"
-	"google.golang.org/grpc"
 )
 
 // routeContainer groups a route with one ore multiple source the route was received from
 type routeContainer struct {
 	route   *routeapi.Route
-	sources []*grpc.ClientConn
+	sources []interface{}
 }
 
-func newRouteContainer(route *routeapi.Route, source *grpc.ClientConn) *routeContainer {
+func newRouteContainer(route *routeapi.Route, source interface{}) *routeContainer {
 	return &routeContainer{
 		route:   route,
-		sources: []*grpc.ClientConn{source},
+		sources: []interface{}{source},
 	}
 }
 
-func (rc *routeContainer) addSource(cc *grpc.ClientConn) {
+func (rc *routeContainer) addSource(cc interface{}) {
 	rc.sources = append(rc.sources, cc)
 }
 
-func (rc *routeContainer) removeSource(cc *grpc.ClientConn) {
+func (rc *routeContainer) removeSource(cc interface{}) {
 	i := rc.getSourceIndex(cc)
 	if i < 0 {
 		return
@@ -32,7 +31,7 @@ func (rc *routeContainer) removeSource(cc *grpc.ClientConn) {
 	rc.sources = rc.sources[:len(rc.sources)-1]
 }
 
-func (rc *routeContainer) getSourceIndex(cc *grpc.ClientConn) int {
+func (rc *routeContainer) getSourceIndex(cc interface{}) int {
 	for i := range rc.sources {
 		if rc.sources[i] == cc {
 			return i
diff --git a/cmd/ris-mirror/rtmirror/rtmirror.go b/cmd/ris-mirror/rtmirror/rtmirror.go
index 55ee1463738d7020725da27630013e0a103e0ec2..fcf1a6400eea84cb4861e41e01d96869c7bee4b5 100644
--- a/cmd/ris-mirror/rtmirror/rtmirror.go
+++ b/cmd/ris-mirror/rtmirror/rtmirror.go
@@ -1,118 +1,33 @@
 package rtmirror
 
 import (
-	"context"
 	"crypto/sha1"
-	"io"
 	"sync"
 
-	risapi "github.com/bio-routing/bio-rd/cmd/ris/api"
-	bnet "github.com/bio-routing/bio-rd/net"
 	"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/vrf"
+	"github.com/bio-routing/bio-rd/routingtable"
 	"github.com/golang/protobuf/proto"
 	"github.com/pkg/errors"
-	"google.golang.org/grpc"
-
-	log "github.com/sirupsen/logrus"
 )
 
-// RTMirror provides an deduplicated mirror of a router/vrf/afi routing table from a multiple RIS instances
+// RTMirror provides an deduplicated routing table
 type RTMirror struct {
-	cfg         Config
-	vrf         *vrf.VRF
-	routes      map[[20]byte]*routeContainer
-	routesMu    sync.Mutex
-	grpcClients []*grpc.ClientConn
-	stop        chan struct{}
-	wg          sync.WaitGroup
-}
-
-// Config is a route mirror config
-type Config struct {
-	Router string
-	VRF    *vrf.VRF
+	routes   map[[20]byte]*routeContainer
+	routesMu sync.Mutex
+	rt       *routingtable.RoutingTable
 }
 
 // New creates a new RTMirror and starts it
-func New(clientConns []*grpc.ClientConn, cfg Config) *RTMirror {
-	rtm := &RTMirror{
-		cfg:         cfg,
-		routes:      make(map[[20]byte]*routeContainer),
-		vrf:         cfg.VRF,
-		grpcClients: clientConns,
-		stop:        make(chan struct{}),
-	}
-
-	afis := []risapi.ObserveRIBRequest_AFISAFI{
-		risapi.ObserveRIBRequest_IPv4Unicast,
-		risapi.ObserveRIBRequest_IPv6Unicast,
-	}
-
-	for _, afi := range afis {
-		for _, ris := range rtm.grpcClients {
-			rtm.wg.Add(1)
-			go rtm.client(ris, afi)
-		}
-	}
-
-	return rtm
-}
-
-func (rtm *RTMirror) addRIS(addr string) error {
-	cc, err := grpc.Dial(addr, grpc.WithInsecure())
-	if err != nil {
-		return errors.Wrap(err, "grpc dial failed")
-	}
-
-	rtm.grpcClients = append(rtm.grpcClients, cc)
-
-	return nil
-}
-
-// Dispose stops the RTMirror
-func (rtm *RTMirror) Dispose() {
-	close(rtm.stop)
-
-	for _, cc := range rtm.grpcClients {
-		cc.Close()
+func New(rt *routingtable.RoutingTable) *RTMirror {
+	return &RTMirror{
+		routes: make(map[[20]byte]*routeContainer),
+		rt:     rt,
 	}
-
-	rtm.wg.Wait()
 }
 
-func (rtm *RTMirror) client(cc *grpc.ClientConn, afi risapi.ObserveRIBRequest_AFISAFI) {
-	defer rtm.wg.Done()
-
-	risc := risapi.NewRoutingInformationServiceClient(cc)
-
-	for {
-		if rtm.stopped() {
-			return
-		}
-
-		orc, err := risc.ObserveRIB(context.Background(), &risapi.ObserveRIBRequest{
-			Router:  rtm.cfg.Router,
-			VrfId:   rtm.cfg.VRF.RD(),
-			Afisafi: afi,
-		}, grpc.WaitForReady(true))
-		if err != nil {
-			log.WithError(err).Error("ObserveRIB call failed")
-			continue
-		}
-
-		err = rtm.clientServiceLoop(cc, orc)
-		if err != nil {
-			log.WithError(err).Error("client service loop failed")
-		}
-
-		rtm.dropRoutesFromRIS(cc)
-	}
-}
-
-func (rtm *RTMirror) dropRoutesFromRIS(cc *grpc.ClientConn) {
+// DropRIS drops all routes learned from a RIS
+func (rtm *RTMirror) DropRIS(cc interface{}) {
 	rtm.routesMu.Lock()
 	defer rtm.routesMu.Unlock()
 
@@ -121,44 +36,11 @@ func (rtm *RTMirror) dropRoutesFromRIS(cc *grpc.ClientConn) {
 	}
 }
 
-func (rtm *RTMirror) stopped() bool {
-	select {
-	case <-rtm.stop:
-		return true
-	default:
-		return false
-	}
-}
-
-func (rtm *RTMirror) clientServiceLoop(cc *grpc.ClientConn, orc risapi.RoutingInformationService_ObserveRIBClient) error {
-	for {
-		if rtm.stopped() {
-			return nil
-		}
-
-		u, err := orc.Recv()
-		if err != nil {
-			if err == io.EOF {
-				return nil
-			}
-
-			return errors.Wrap(err, "recv failed")
-		}
-
-		if u.Advertisement {
-			rtm.addRoute(cc, u.Route)
-			continue
-		}
-
-		rtm.delRoute(cc, u.Route)
-	}
-}
-
-func (rtm *RTMirror) addRoute(cc *grpc.ClientConn, r *routeapi.Route) {
+// AddRoute adds a route
+func (rtm *RTMirror) AddRoute(cc interface{}, r *routeapi.Route) error {
 	h, err := hashRoute(r)
 	if err != nil {
-		log.WithError(err).Error("Hashing failed")
-		return
+		return errors.Wrap(err, "Hashing failed")
 	}
 
 	rtm.routesMu.Lock()
@@ -166,59 +48,45 @@ func (rtm *RTMirror) addRoute(cc *grpc.ClientConn, r *routeapi.Route) {
 
 	if _, exists := rtm.routes[h]; !exists {
 		s := route.RouteFromProtoRoute(r, true)
-		rib := rtm.getRIB(s.Prefix().Addr())
-
 		rtm.routes[h] = newRouteContainer(r, cc)
-		rib.AddPath(s.Prefix(), s.Paths()[0])
-		return
+		rtm.rt.AddPath(s.Prefix(), s.Paths()[0])
+		return nil
 	}
 
 	rtm.routes[h].addSource(cc)
+	return nil
 }
 
-func (rtm *RTMirror) getRIB(addr *bnet.IP) *locRIB.LocRIB {
-	if addr.IsIPv4() {
-		return rtm.vrf.IPv4UnicastRIB()
-	}
-
-	return rtm.vrf.IPv6UnicastRIB()
-}
-
-func (rtm *RTMirror) delRoute(cc *grpc.ClientConn, r *routeapi.Route) {
+// RemoveRoute deletes a route
+func (rtm *RTMirror) RemoveRoute(cc interface{}, r *routeapi.Route) error {
 	h, err := hashRoute(r)
 	if err != nil {
-		log.WithError(err).Error("Hashing failed")
-		return
+		return errors.Wrap(err, "Hashing failed")
 	}
 
 	rtm.routesMu.Lock()
 	defer rtm.routesMu.Unlock()
 
 	if _, exists := rtm.routes[h]; !exists {
-		return
+		return nil
 	}
 
 	rtm._delRoute(h, cc, r)
+	return nil
 }
 
-func (rtm *RTMirror) _delRoute(h [20]byte, cc *grpc.ClientConn, r *routeapi.Route) {
-	rtm.routes[h].removeSource(cc)
+func (rtm *RTMirror) _delRoute(h [20]byte, src interface{}, r *routeapi.Route) {
+	rtm.routes[h].removeSource(src)
 
 	if rtm.routes[h].srcCount() > 0 {
 		return
 	}
 
 	s := route.RouteFromProtoRoute(r, true)
-	rib := rtm.getRIB(s.Prefix().Addr())
-	rib.RemovePath(s.Prefix(), s.Paths()[0])
+	rtm.rt.RemovePath(s.Prefix(), s.Paths()[0])
 	delete(rtm.routes, h)
 }
 
-// GetVRF exposes the mirrors VRF
-func (rtm *RTMirror) GetVRF() *vrf.VRF {
-	return rtm.vrf
-}
-
 func hashRoute(route *routeapi.Route) ([20]byte, error) {
 	m, err := proto.Marshal(route)
 	if err != nil {
diff --git a/cmd/ris-mirror/rtmirror/rtmirror_test.go b/cmd/ris-mirror/rtmirror/rtmirror_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..4280f12ac52f1ce2ce67228acc1e04f9ce51289a
--- /dev/null
+++ b/cmd/ris-mirror/rtmirror/rtmirror_test.go
@@ -0,0 +1,226 @@
+package rtmirror
+
+import (
+	"testing"
+
+	"github.com/bio-routing/bio-rd/route"
+	routeapi "github.com/bio-routing/bio-rd/route/api"
+	"github.com/bio-routing/bio-rd/routingtable"
+	"github.com/stretchr/testify/assert"
+
+	bnet "github.com/bio-routing/bio-rd/net"
+)
+
+type srcRouteTuple struct {
+	src   interface{}
+	route *routeapi.Route
+}
+
+func TestRTMirror(t *testing.T) {
+	tests := []struct {
+		name                string
+		add                 []*srcRouteTuple
+		expectedAfterAdd    []*route.Route
+		remove              []*srcRouteTuple
+		expectedAfterRemove []*route.Route
+	}{
+		{
+			name: "Test #1: Single source",
+			add: []*srcRouteTuple{
+				{
+					src: "a",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedAfterAdd: []*route.Route{
+				route.NewRoute(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).Ptr(), &route.Path{
+					Type: route.StaticPathType,
+					StaticPath: &route.StaticPath{
+						NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).Ptr(),
+					},
+				}),
+			},
+			remove: []*srcRouteTuple{
+				{
+					src: "a",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedAfterRemove: []*route.Route{},
+		},
+		{
+			name: "Test #2: Multiple source, single delete",
+			add: []*srcRouteTuple{
+				{
+					src: "a",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+				{
+					src: "b",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedAfterAdd: []*route.Route{
+				route.NewRoute(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).Ptr(), &route.Path{
+					Type: route.StaticPathType,
+					StaticPath: &route.StaticPath{
+						NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).Ptr(),
+					},
+				}),
+			},
+			remove: []*srcRouteTuple{
+				{
+					src: "a",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedAfterRemove: []*route.Route{
+				route.NewRoute(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).Ptr(), &route.Path{
+					Type: route.StaticPathType,
+					StaticPath: &route.StaticPath{
+						NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).Ptr(),
+					},
+				}),
+			},
+		},
+		{
+			name: "Test #3: Multiple source, double delete",
+			add: []*srcRouteTuple{
+				{
+					src: "a",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+				{
+					src: "b",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedAfterAdd: []*route.Route{
+				route.NewRoute(bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).Ptr(), &route.Path{
+					Type: route.StaticPathType,
+					StaticPath: &route.StaticPath{
+						NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).Ptr(),
+					},
+				}),
+			},
+			remove: []*srcRouteTuple{
+				{
+					src: "a",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+				{
+					src: "b",
+					route: &routeapi.Route{
+						Pfx: bnet.NewPfx(bnet.IPv4FromOctets(10, 0, 0, 0), 8).ToProto(),
+						Paths: []*routeapi.Path{
+							{
+								Type: routeapi.Path_Static,
+								StaticPath: &routeapi.StaticPath{
+									NextHop: bnet.IPv4FromOctets(1, 1, 1, 1).ToProto(),
+								},
+							},
+						},
+					},
+				},
+			},
+			expectedAfterRemove: []*route.Route{},
+		},
+	}
+
+	for _, test := range tests {
+		rt := routingtable.NewRoutingTable()
+		rtm := New(rt)
+
+		for _, a := range test.add {
+			rtm.AddRoute(a.src, a.route)
+		}
+
+		assert.Equal(t, test.expectedAfterAdd, rt.Dump(), test.name)
+
+		/*for _, r := range test.add {
+			rtm.RemoveRoute(r.src, r.route)
+		}
+
+		assert.Equal(t, test.expectedAfterAdd, rt.Dump(), test.name)*/
+	}
+}
diff --git a/metrics/vrf/adapter/prom/vrf_prom_adapter.go b/metrics/vrf/adapter/prom/vrf_prom_adapter.go
index d55e706ec5856d8d5d907dd89e3c3919701466f6..0342801880d18a2cd21abf9c6c786ba13f6383e3 100644
--- a/metrics/vrf/adapter/prom/vrf_prom_adapter.go
+++ b/metrics/vrf/adapter/prom/vrf_prom_adapter.go
@@ -18,7 +18,7 @@ var (
 )
 
 func init() {
-	labels := []string{"vrf", "rib", "afi", "safi"}
+	labels := []string{"vrf_name", "vrf_rd", "rib", "afi", "safi"}
 	routeCountDesc = prometheus.NewDesc(prefix+"route_count", "Number of routes in the RIB", labels, nil)
 	routeCountDescRouter = prometheus.NewDesc(prefix+"route_count", "Number of routes in the RIB", append([]string{"sys_name", "agent_address"}, labels...), nil)
 }
@@ -55,7 +55,7 @@ func (c *vrfCollector) Collect(ch chan<- prometheus.Metric) {
 func (c *vrfCollector) collectForVRF(ch chan<- prometheus.Metric, v *metrics.VRFMetrics) {
 	for _, rib := range v.RIBs {
 		ch <- prometheus.MustNewConstMetric(routeCountDesc, prometheus.GaugeValue, float64(rib.RouteCount),
-			v.Name, rib.Name, strconv.Itoa(int(rib.AFI)), strconv.Itoa(int(rib.SAFI)))
+			v.Name, vrf.RouteDistinguisherHumanReadable(v.RD), rib.Name, strconv.Itoa(int(rib.AFI)), strconv.Itoa(int(rib.SAFI)))
 	}
 }
 
@@ -63,6 +63,6 @@ func (c *vrfCollector) collectForVRF(ch chan<- prometheus.Metric, v *metrics.VRF
 func CollectForVRFRouter(ch chan<- prometheus.Metric, sysName string, agentAddress string, v *metrics.VRFMetrics) {
 	for _, rib := range v.RIBs {
 		ch <- prometheus.MustNewConstMetric(routeCountDescRouter, prometheus.GaugeValue, float64(rib.RouteCount),
-			sysName, agentAddress, v.Name, rib.Name, strconv.Itoa(int(rib.AFI)), strconv.Itoa(int(rib.SAFI)))
+			sysName, agentAddress, v.Name, vrf.RouteDistinguisherHumanReadable(v.RD), rib.Name, strconv.Itoa(int(rib.AFI)), strconv.Itoa(int(rib.SAFI)))
 	}
 }
diff --git a/route/path.go b/route/path.go
index 4d36544331c35493e8f41b2d3843e8a4d4b56a68..3a7d5165a234d392666bee792d2b18291af3d4b3 100644
--- a/route/path.go
+++ b/route/path.go
@@ -151,7 +151,7 @@ func (p *Path) String() string {
 	case FIBPathType:
 		return p.FIBPath.String()
 	default:
-		return "Unknown paty type. Probably not implemented yet"
+		return fmt.Sprintf("Unknown path type. Probably not implemented yet (%d)", p.Type)
 	}
 }
 
diff --git a/route/route.go b/route/route.go
index fd92772e652f2986e73a25366493331488663652..5c2b08ab2cdd671f10fd024d5a45db82285a71b7 100644
--- a/route/route.go
+++ b/route/route.go
@@ -279,6 +279,9 @@ func RouteFromProtoRoute(ar *api.Route, dedup bool) *Route {
 		case api.Path_BGP:
 			p.Type = BGPPathType
 			p.BGPPath = BGPPathFromProtoBGPPath(ar.Paths[i].BgpPath, dedup)
+		case api.Path_Static:
+			p.Type = StaticPathType
+			p.StaticPath = StaticPathFromProtoStaticPath(ar.Paths[i].StaticPath, dedup)
 		}
 
 		r.paths = append(r.paths, p)
diff --git a/route/static.go b/route/static.go
index a4285223ea111944842da2eed544bf108eace7ac..b056fd34e9d096102e2c0512ca755525f3381ad6 100644
--- a/route/static.go
+++ b/route/static.go
@@ -58,3 +58,10 @@ func (s *StaticPath) ToProto() *api.StaticPath {
 		NextHop: s.NextHop.ToProto(),
 	}
 }
+
+// StaticPathFromProtoStaticPath converts a proto StaticPath to StaticPath
+func StaticPathFromProtoStaticPath(pb *api.StaticPath, dedup bool) *StaticPath {
+	return &StaticPath{
+		NextHop: bnet.IPFromProtoIP(pb.NextHop),
+	}
+}
diff --git a/routingtable/vrf/metrics.go b/routingtable/vrf/metrics.go
index 5e4dd53e867982c39deb9f80583524b4b9314eb9..f28cb379b19d91daca70dfc6f106780fd24f0906 100644
--- a/routingtable/vrf/metrics.go
+++ b/routingtable/vrf/metrics.go
@@ -21,6 +21,7 @@ func Metrics(r *VRFRegistry) []*metrics.VRFMetrics {
 func MetricsForVRF(v *VRF) *metrics.VRFMetrics {
 	m := &metrics.VRFMetrics{
 		Name: v.Name(),
+		RD:   v.RD(),
 		RIBs: make([]*metrics.RIBMetrics, 0),
 	}
 
diff --git a/routingtable/vrf/metrics/vrf_metrics.go b/routingtable/vrf/metrics/vrf_metrics.go
index 3c5ba2c0e37c293bb2467c86594f1e6222df05e2..088a665b154c41efae1ced26a6c701542568cc1c 100644
--- a/routingtable/vrf/metrics/vrf_metrics.go
+++ b/routingtable/vrf/metrics/vrf_metrics.go
@@ -5,6 +5,9 @@ type VRFMetrics struct {
 	// Name of the VRF
 	Name string
 
+	// RD is the route distinguisher
+	RD uint64
+
 	// RIBs returns the RIB specific metrics
 	RIBs []*RIBMetrics
 }