VOL-2948: Added PON and NNI information to metrics

Change-Id: I8928dc6a2bb2920d79596fdde0c916817ab27b59
diff --git a/VERSION b/VERSION
index 79a6144..59aa62c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.4.4
+2.4.5
diff --git a/internal/pkg/core/device_handler.go b/internal/pkg/core/device_handler.go
index 51c2548..878c6db 100644
--- a/internal/pkg/core/device_handler.go
+++ b/internal/pkg/core/device_handler.go
@@ -309,6 +309,19 @@
 			"device-id": dh.device.Id,
 			"port-type": portType}, err)
 	}
+	go dh.updateLocalDevice()
+	return nil
+}
+
+func (dh *DeviceHandler) updateLocalDevice() error {
+	dh.lockDevice.Lock()
+	defer dh.lockDevice.Unlock()
+	device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
+	if err != nil || device == nil {
+		logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
+		return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
+	}
+	dh.device = device
 	return nil
 }
 
@@ -689,6 +702,7 @@
 			olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
 		}
 	}()
+	go dh.updateLocalDevice()
 	return nil
 }
 
@@ -765,29 +779,36 @@
 func startCollector(dh *DeviceHandler) {
 	logger.Debugf("starting-collector")
 	context := make(map[string]string)
+	freq := dh.metrics.ToPmConfigs().DefaultFreq
 	for {
 		select {
 		case <-dh.stopCollector:
 			logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.deviceID})
 			return
-		default:
-			freq := dh.metrics.ToPmConfigs().DefaultFreq
-			time.Sleep(time.Duration(freq) * time.Second)
+		case <-time.After(time.Duration(freq) * time.Second):
 			context["oltid"] = dh.deviceID
 			context["devicetype"] = dh.deviceType
-			// NNI Stats
-			cmnni := dh.portStats.collectNNIMetrics(uint32(0))
-			logger.Debugf("Collect-NNI-Metrics %v", cmnni)
-			go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
-			logger.Debugf("publish-nni-metrics")
-			// PON Stats
-			NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
-			for i := uint32(0); i < NumPonPORTS; i++ {
-				if val, ok := dh.activePorts.Load(i); ok && val == true {
-					cmpon := dh.portStats.collectPONMetrics(i)
-					logger.Debugf("Collect-PON-Metrics %v", cmpon)
-					go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
-					logger.Debugf("publish-pon-metrics")
+			ports := make([]*voltha.Port, len(dh.device.Ports))
+			copy(ports, dh.device.Ports)
+
+			for _, port := range ports {
+				// NNI Stats
+				if port.Type == voltha.Port_ETHERNET_NNI {
+					intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
+					cmnni := dh.portStats.collectNNIMetrics(intfID)
+					logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
+					go dh.portStats.publishMetrics(cmnni, port, context, dh.deviceID)
+					logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
+				}
+				// PON Stats
+				if port.Type == voltha.Port_PON_OLT {
+					intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
+					if val, ok := dh.activePorts.Load(intfID); ok && val == true {
+						cmpon := dh.portStats.collectPONMetrics(intfID)
+						logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
+						go dh.portStats.publishMetrics(cmpon, port, context, dh.deviceID)
+					}
+					logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
 				}
 			}
 		}
diff --git a/internal/pkg/core/device_handler_test.go b/internal/pkg/core/device_handler_test.go
index 9fd8127..b2f870c 100644
--- a/internal/pkg/core/device_handler_test.go
+++ b/internal/pkg/core/device_handler_test.go
@@ -1161,24 +1161,34 @@
 		dh *DeviceHandler
 	}
 	dh := newMockDeviceHandler()
+	ports := []*voltha.Port{
+		{PortNo: 1, Label: "pon", Type: voltha.Port_PON_OLT},
+		{PortNo: 1048577, Label: "nni", Type: voltha.Port_ETHERNET_NNI},
+		{PortNo: 1048578, Label: "nni", Type: voltha.Port_ETHERNET_NNI},
+	}
+	dh.device.Ports = ports
 	dh.portStats.NorthBoundPort = make(map[uint32]*NniPort)
-	dh.portStats.NorthBoundPort[0] = &NniPort{Name: "OLT-1"}
+	dh.portStats.NorthBoundPort[1] = &NniPort{Name: "OLT-1"}
+	dh.portStats.NorthBoundPort[2] = &NniPort{Name: "OLT-1"}
 	dh.portStats.SouthBoundPort = make(map[uint32]*PonPort)
 	dh.portStats.Device = dh
 	for i := 0; i < 16; i++ {
 		dh.portStats.SouthBoundPort[uint32(i)] = &PonPort{DeviceID: "OLT-1"}
 	}
+	dh1 := newMockDeviceHandler()
+	dh1.device.Ports = []*voltha.Port{}
 	tests := []struct {
 		name string
 		args args
 	}{
 		// TODO: Add test cases.
 		{"StartCollector-1", args{dh}},
+		{"StartCollector-2", args{dh1}},
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			go func() {
-				time.Sleep(5 * time.Second) // simulated wait time to stop startCollector
+				time.Sleep(1 * time.Second) // simulated wait time to stop startCollector
 				tt.args.dh.stopCollector <- true
 			}()
 			startCollector(tt.args.dh)
diff --git a/internal/pkg/core/statsmanager.go b/internal/pkg/core/statsmanager.go
index a71c435..c5c44db 100755
--- a/internal/pkg/core/statsmanager.go
+++ b/internal/pkg/core/statsmanager.go
@@ -23,6 +23,7 @@
 	"github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
 	"github.com/opencord/voltha-protos/v3/go/openolt"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
+	"strconv"
 	"sync"
 	"time"
 )
@@ -349,14 +350,17 @@
 }
 
 // publishMatrics will publish the pon port metrics
-func (StatMgr OpenOltStatisticsMgr) publishMetrics(portType string, val map[string]float32, portnum uint32, context map[string]string, devID string) {
-	logger.Debugf("Post-%v %v", portType, val)
+func (StatMgr OpenOltStatisticsMgr) publishMetrics(val map[string]float32,
+	port *voltha.Port, context map[string]string, devID string) {
+	logger.Debugw("publish-metrics", log.Fields{"port": port.Label, "metrics": val})
 
 	var metricInfo voltha.MetricInformation
 	var ke voltha.KpiEvent2
 	var volthaEventSubCatgry voltha.EventSubCategory_Types
+	context["portlabel"] = port.Label
+	context["portno"] = strconv.Itoa(int(port.PortNo))
 
-	if portType == "NNIStats" {
+	if port.Type == voltha.Port_ETHERNET_NNI {
 		volthaEventSubCatgry = voltha.EventSubCategory_NNI
 	} else {
 		volthaEventSubCatgry = voltha.EventSubCategory_PON
@@ -364,7 +368,7 @@
 
 	raisedTs := time.Now().UnixNano()
 	mmd := voltha.MetricMetaData{
-		Title:    portType,
+		Title:    port.Type.String(),
 		Ts:       float64(raisedTs),
 		Context:  context,
 		DeviceId: devID,
@@ -380,7 +384,6 @@
 	if err := StatMgr.Device.EventProxy.SendKpiEvent("STATS_EVENT", &ke, voltha.EventCategory_EQUIPMENT, volthaEventSubCatgry, raisedTs); err != nil {
 		logger.Errorw("Failed to send Pon stats", log.Fields{"err": err})
 	}
-
 }
 
 // PortStatisticsIndication handles the port statistics indication
diff --git a/internal/pkg/core/statsmanager_test.go b/internal/pkg/core/statsmanager_test.go
index b4be735..499fda9 100644
--- a/internal/pkg/core/statsmanager_test.go
+++ b/internal/pkg/core/statsmanager_test.go
@@ -18,6 +18,7 @@
 package core
 
 import (
+	"fmt"
 	"github.com/opencord/voltha-protos/v3/go/openolt"
 	"github.com/opencord/voltha-protos/v3/go/voltha"
 	"reflect"
@@ -70,9 +71,9 @@
 		SouthBoundPort map[uint32]*PonPort
 	}
 	type args struct {
-		portType string
+		portType voltha.Port_PortType
 		val      map[string]float32
-		portnum  uint32
+		port     *voltha.Port
 		context  map[string]string
 	}
 	ctx := map[string]string{}
@@ -144,10 +145,9 @@
 				SouthBoundPort: nil,
 			},
 			args: args{
-				portType: "NNIStats",
-				val:      nval,
-				portnum:  0,
-				context:  ctx,
+				val:     nval,
+				port:    &voltha.Port{PortNo: 0, Label: fmt.Sprintf("%s%d", "nni-", 0), Type: voltha.Port_ETHERNET_NNI},
+				context: ctx,
 			},
 		},
 		{
@@ -158,10 +158,9 @@
 				SouthBoundPort: ponmap,
 			},
 			args: args{
-				portType: "PONStats",
-				val:      pval,
-				portnum:  0,
-				context:  ctx,
+				val:     pval,
+				port:    &voltha.Port{PortNo: 1, Label: fmt.Sprintf("%s%d", "pon-", 1), Type: voltha.Port_PON_OLT},
+				context: ctx,
 			},
 		},
 		// TODO: Add test cases.
@@ -173,8 +172,7 @@
 				NorthBoundPort: tt.fields.NorthBoundPort,
 				SouthBoundPort: tt.fields.SouthBoundPort,
 			}
-			StatMgr.publishMetrics(tt.args.portType, tt.args.val, tt.args.portnum, tt.args.context, "onu1")
-
+			StatMgr.publishMetrics(tt.args.val, tt.args.port, tt.args.context, "onu1")
 		})
 	}
 }