VOL-2293, VOL-2456 improve error handling

Change-Id: I4be5f12719a31b40363758cd47cc02968f180c75
diff --git a/adaptercore/device_handler.go b/adaptercore/device_handler.go
index 6be5be7..9683d31 100644
--- a/adaptercore/device_handler.go
+++ b/adaptercore/device_handler.go
@@ -20,7 +20,6 @@
 import (
 	"context"
 	"encoding/hex"
-	"errors"
 	"fmt"
 	"io"
 	"net"
@@ -181,15 +180,13 @@
 		if ips, err = net.LookupHost(host); err == nil {
 			log.Debugw("dns-result-ips", log.Fields{"ips": ips})
 			if addr = net.ParseIP(ips[0]); addr == nil {
-				log.Errorw("unable-to-parse-ip", log.Fields{"ip": ips[0]})
-				return "", errors.New("unable-to-parse-ip")
+				return "", NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil).Log()
 			}
 			genmac = macifyIP(addr)
 			log.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
 			return genmac, nil
 		}
-		log.Errorw("cannot-resolve-hostname-to-ip", log.Fields{"host": host})
-		return "", err
+		return "", NewErrAdapter("cannot-resolve-hostname-to-ip", nil, err).Log()
 	}
 
 	genmac = macifyIP(addr)
@@ -212,20 +209,19 @@
 }
 
 //GetportLabel returns the label for the NNI and the PON port based on port number and port type
-func GetportLabel(portNum uint32, portType voltha.Port_PortType) string {
+func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
 
-	if portType == voltha.Port_ETHERNET_NNI {
-		return fmt.Sprintf("nni-%d", portNum)
-	} else if portType == voltha.Port_PON_OLT {
-		return fmt.Sprintf("pon-%d", portNum)
-	} else if portType == voltha.Port_ETHERNET_UNI {
-		log.Errorw("local UNI management not supported", log.Fields{})
-		return ""
+	switch portType {
+	case voltha.Port_ETHERNET_NNI:
+		return fmt.Sprintf("nni-%d", portNum), nil
+	case voltha.Port_PON_OLT:
+		return fmt.Sprintf("pon-%d", portNum), nil
 	}
-	return ""
+
+	return "", NewErrInvalidValue(log.Fields{"port-type": portType}, nil).Log()
 }
 
-func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) {
+func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
 	var operStatus common.OperStatus_Types
 	if state == "up" {
 		operStatus = voltha.OperStatus_ACTIVE
@@ -236,26 +232,28 @@
 		dh.activePorts.Store(intfID, false)
 	}
 	portNum := IntfIDToPortNo(intfID, portType)
-	label := GetportLabel(portNum, portType)
-	if len(label) == 0 {
-		log.Errorw("Invalid-port-label", log.Fields{"portNum": portNum, "portType": portType})
-		return
+	label, err := GetportLabel(portNum, portType)
+	if err != nil {
+		return NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, nil).Log()
 	}
 
 	device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
 	if err != nil || device == nil {
-		log.Errorw("Failed-to-fetch-device", log.Fields{"err": err})
-		return
+		return NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 	if device.Ports != nil {
 		for _, dPort := range device.Ports {
 			if dPort.Type == portType && dPort.PortNo == portNum {
 				log.Debug("port-already-exists-updating-oper-status-of-port")
 				if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
-					log.Errorw("failed-to-update-port-state", log.Fields{"err": err})
-					return
+					return NewErrAdapter("failed-to-update-port-state", log.Fields{
+						"device-id":   dh.device.Id,
+						"port-type":   portType,
+						"port-number": portNum,
+						"oper-status": operStatus}, err).Log()
+
 				}
-				return
+				return nil
 			}
 		}
 	}
@@ -269,30 +267,28 @@
 	log.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
 	// Synchronous call to update device - this method is run in its own go routine
 	if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
-		log.Errorw("Error-creating-port", log.Fields{"deviceID": dh.device.Id, "portType": portType, "error": err})
-		return
+		return NewErrAdapter("Error-creating-port", log.Fields{
+			"device-id": dh.device.Id,
+			"port-type": portType}, err).Log()
 	}
-	return
+	return nil
 }
 
 // readIndications to read the indications from the OLT device
-func (dh *DeviceHandler) readIndications(ctx context.Context) {
-	defer log.Errorw("Indications ended", log.Fields{})
+func (dh *DeviceHandler) readIndications(ctx context.Context) error {
+	defer log.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
 	indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
 	if err != nil {
-		log.Errorw("Failed to read indications", log.Fields{"err": err})
-		return
+		return NewErrCommunication("fail-to-read-indications", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 	if indications == nil {
-		log.Errorw("Indications is nil", log.Fields{})
-		return
+		return NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
 	}
 	/* get device state */
 	device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
 	if err != nil || device == nil {
 		/*TODO: needs to handle error scenarios */
-		log.Errorw("Failed to fetch device info", log.Fields{"err": err})
-		return
+		return NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 	// When the device is in DISABLED and Adapter container restarts, we need to
 	// rebuild the locally maintained admin state.
@@ -325,8 +321,7 @@
 			time.Sleep(indicationBackoff.NextBackOff())
 			indications, err = dh.Client.EnableIndication(ctx, new(oop.Empty))
 			if err != nil {
-				log.Errorw("Failed to read indications", log.Fields{"err": err})
-				return
+				return NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
 			}
 			continue
 		}
@@ -338,7 +333,7 @@
 			}
 			dh.transitionMap.Handle(ctx, DeviceDownInd)
 			dh.transitionMap.Handle(ctx, DeviceInit)
-			break
+			return NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
 		}
 		// Reset backoff if we have a successful receive
 		indicationBackoff.Reset()
@@ -354,9 +349,10 @@
 		dh.handleIndication(ctx, indication)
 
 	}
+	return nil
 }
 
-func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) {
+func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
 	raisedTs := time.Now().UnixNano()
 	if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
 		dh.transitionMap.Handle(ctx, DeviceUpInd)
@@ -364,27 +360,48 @@
 		dh.transitionMap.Handle(ctx, DeviceDownInd)
 	}
 	// Send or clear Alarm
-	dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs)
+	if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
+		return NewErrAdapter("failed-indication", log.Fields{
+			"device_id":  dh.deviceID,
+			"indication": oltIndication,
+			"timestamp":  raisedTs}, err).Log()
+	}
+	return nil
 }
 
+// nolint: gocyclo
 func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
 	raisedTs := time.Now().UnixNano()
 	switch indication.Data.(type) {
 	case *oop.Indication_OltInd:
-		dh.handleOltIndication(ctx, indication.GetOltInd())
+		if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
+			NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
+		}
 	case *oop.Indication_IntfInd:
 		intfInd := indication.GetIntfInd()
-		go dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState())
+		go func() {
+			if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
+				NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
+			}
+		}()
 		log.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
 	case *oop.Indication_IntfOperInd:
 		intfOperInd := indication.GetIntfOperInd()
 		if intfOperInd.GetType() == "nni" {
-			go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState())
+			go func() {
+				if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
+					NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
+				}
+			}()
 			dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
 		} else if intfOperInd.GetType() == "pon" {
 			// TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
 			// Handle pon port update
-			go dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState())
+			go func() {
+				if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
+					NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
+				}
+			}()
 			go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
 		}
 		log.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
@@ -392,19 +409,35 @@
 		onuDiscInd := indication.GetOnuDiscInd()
 		log.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
 		sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
-		go dh.onuDiscIndication(ctx, onuDiscInd, sn)
+		go func() {
+			if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
+				NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
+			}
+		}()
 	case *oop.Indication_OnuInd:
 		onuInd := indication.GetOnuInd()
 		log.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
-		go dh.onuIndication(onuInd)
+		go func() {
+			if err := dh.onuIndication(onuInd); err != nil {
+				NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
+			}
+		}()
 	case *oop.Indication_OmciInd:
 		omciInd := indication.GetOmciInd()
 		log.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
-		go dh.omciIndication(omciInd)
+		go func() {
+			if err := dh.omciIndication(omciInd); err != nil {
+				NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
+			}
+		}()
 	case *oop.Indication_PktInd:
 		pktInd := indication.GetPktInd()
 		log.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
-		go dh.handlePacketIndication(ctx, pktInd)
+		go func() {
+			if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
+				NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
+			}
+		}()
 	case *oop.Indication_PortStats:
 		portStats := indication.GetPortStats()
 		go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
@@ -423,8 +456,7 @@
 	// Synchronous call to update device state - this method is run in its own go routine
 	if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
 		voltha.OperStatus_ACTIVE); err != nil {
-		log.Errorw("Failed to update device with OLT UP indication", log.Fields{"deviceID": dh.device.Id, "error": err})
-		return err
+		return NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 	return nil
 }
@@ -438,15 +470,13 @@
 	device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
 	if err != nil || device == nil {
 		/*TODO: needs to handle error scenarios */
-		log.Errorw("Failed to fetch device device", log.Fields{"err": err})
-		return errors.New("failed to fetch device device")
+		return NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 
 	cloned := proto.Clone(device).(*voltha.Device)
 	// Update the all ports state on that device to disable
-	if er := dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); er != nil {
-		log.Errorw("updating-ports-failed", log.Fields{"deviceID": device.Id, "error": er})
-		return er
+	if err = dh.coreProxy.PortsStateUpdate(ctx, cloned.Id, voltha.OperStatus_UNKNOWN); err != nil {
+		return NewErrAdapter("port-update-failed", log.Fields{"device-id": device.Id}, err).Log()
 	}
 
 	//Update the device oper state and connection status
@@ -454,44 +484,45 @@
 	cloned.ConnectStatus = common.ConnectStatus_UNREACHABLE
 	dh.device = cloned
 
-	if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
-		log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": er})
-		return er
+	if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
+		return NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err).Log()
 	}
 
 	//get the child device for the parent device
 	onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
 	if err != nil {
-		log.Errorw("failed to get child devices information", log.Fields{"deviceID": dh.device.Id, "error": err})
-		return err
+		return NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 	for _, onuDevice := range onuDevices.Items {
 
 		// Update onu state as down in onu adapter
 		onuInd := oop.OnuIndication{}
 		onuInd.OperState = "down"
-		er := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
+		err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
 			"openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
-		if er != nil {
-			log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
-				"From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
+		if err != nil {
+			NewErrCommunication("inter-adapter-send-failed", log.Fields{
+				"source":        "openolt",
+				"onu-indicator": onuInd,
+				"device-type":   onuDevice.Type,
+				"device-id":     onuDevice.Id}, err).LogAt(log.ErrorLevel)
 			//Do not return here and continue to process other ONUs
 		}
 	}
 	/* Discovered ONUs entries need to be cleared , since after OLT
 	   is up, it starts sending discovery indications again*/
 	dh.discOnus = sync.Map{}
-	log.Debugw("do-state-down-end", log.Fields{"deviceID": device.Id})
+	log.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
 	return nil
 }
 
 // doStateInit dial the grpc before going to init state
 func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
 	var err error
-	dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock())
-	if err != nil {
-		log.Errorw("Failed to dial device", log.Fields{"DeviceId": dh.deviceID, "HostAndPort": dh.device.GetHostAndPort(), "err": err})
-		return err
+	if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
+		return NewErrCommunication("dial-failure", log.Fields{
+			"device-id":     dh.deviceID,
+			"host-and-port": dh.device.GetHostAndPort()}, err).Log()
 	}
 	return nil
 }
@@ -513,7 +544,7 @@
 		device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
 		if err != nil || device == nil {
 			/*TODO: needs to handle error scenarios */
-			log.Errorw("Failed to fetch device device", log.Fields{"err": err})
+			NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
 		}
 
 		cloned := proto.Clone(device).(*voltha.Device)
@@ -521,48 +552,47 @@
 		cloned.OperStatus = voltha.OperStatus_UNKNOWN
 		dh.device = cloned
 		if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
-			log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": er})
+			NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
 		}
 
 		// Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
 		_, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
 		if err != nil {
-			log.Errorw("Failed to disable olt ", log.Fields{"err": err})
+			NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
 		}
 
 		// Start reading indications
-		go dh.readIndications(ctx)
+		go func() {
+			if err := dh.readIndications(ctx); err != nil {
+				NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
+			}
+		}()
 		return nil
 	}
 
 	deviceInfo, err := dh.populateDeviceInfo()
 	if err != nil {
-		log.Errorw("Unable to populate Device Info", log.Fields{"err": err})
-		return err
+		return NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 
 	device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
 	if err != nil || device == nil {
 		/*TODO: needs to handle error scenarios */
-		log.Errorw("Failed to fetch device device", log.Fields{"err": err})
-		return err
+		return NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 	dh.populateActivePorts(device)
 	if err := dh.disableAdminDownPorts(device); err != nil {
-		log.Errorw("Error-on-updating-port-status", log.Fields{"device": device})
-		return err
+		return NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err).Log()
 	}
 
 	KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
 	// Instantiate resource manager
 	if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
-		log.Error("Error while instantiating resource manager")
-		return errors.New("instantiating resource manager failed")
+		return ErrResourceManagerInstantiating.Log()
 	}
 	// Instantiate flow manager
 	if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
-		log.Error("Error while instantiating flow manager")
-		return errors.New("instantiating flow manager failed")
+		return ErrResourceManagerInstantiating.Log()
 	}
 	/* TODO: Instantiate Alarm , stats , BW managers */
 	/* Instantiating Event Manager to handle Alarms and KPIs */
@@ -571,7 +601,11 @@
 	dh.portStats = NewOpenOltStatsMgr(dh)
 
 	// Start reading indications
-	go dh.readIndications(ctx)
+	go func() {
+		if err := dh.readIndications(ctx); err != nil {
+			NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
+		}
+	}()
 	return nil
 }
 
@@ -582,12 +616,10 @@
 	deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
 
 	if err != nil {
-		log.Errorw("Failed to fetch device info", log.Fields{"err": err})
-		return nil, err
+		return nil, NewErrPersistence("get", "device", 0, nil, err).Log()
 	}
 	if deviceInfo == nil {
-		log.Errorw("Device info is nil", log.Fields{})
-		return nil, errors.New("failed to get device info from OLT")
+		return nil, NewErrInvalidValue(log.Fields{"device": nil}, nil).Log()
 	}
 
 	log.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
@@ -603,7 +635,7 @@
 		host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
 		genmac, err := generateMacFromHost(host)
 		if err != nil {
-			return nil, err
+			return nil, NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err).Log()
 		}
 		log.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
 		dh.device.MacAddress = genmac
@@ -613,8 +645,7 @@
 
 	// Synchronous call to update device - this method is run in its own go routine
 	if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
-		log.Errorw("error-updating-device", log.Fields{"deviceID": dh.device.Id, "error": err})
-		return nil, err
+		return nil, NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 	}
 
 	return deviceInfo, nil
@@ -663,7 +694,7 @@
 
 	// Now, set the initial PM configuration for that device
 	if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
-		log.Errorw("error-updating-PMs", log.Fields{"deviceId": device.Id, "error": err})
+		NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
 	}
 
 	go startCollector(dh)
@@ -711,7 +742,7 @@
 	}, nil
 }
 
-func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) {
+func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
 	log.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
 	var deviceType string
 	var deviceID string
@@ -729,8 +760,9 @@
 
 		onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
 		if err != nil {
-			log.Errorw("onu not found", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "error": err})
-			return
+			return NewErrNotFound("onu", log.Fields{
+				"interface-id": omciInd.IntfId,
+				"onu-id":       omciInd.OnuId}, err).Log()
 		}
 		deviceType = onuDevice.Type
 		deviceID = onuDevice.Id
@@ -746,13 +778,16 @@
 	}
 
 	omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
-	if sendErr := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
+	if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
 		ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
-		deviceID, proxyDeviceID, ""); sendErr != nil {
-		log.Errorw("send omci request error", log.Fields{"fromAdapter": dh.deviceType, "toAdapter": deviceType, "onuID": deviceID, "proxyDeviceID": proxyDeviceID, "error": sendErr})
-		return
+		deviceID, proxyDeviceID, ""); err != nil {
+		return NewErrCommunication("omci-request", log.Fields{
+			"source":          dh.deviceType,
+			"destination":     deviceType,
+			"onu-id":          deviceID,
+			"proxy-device-id": proxyDeviceID}, err).Log()
 	}
-	return
+	return nil
 }
 
 //ProcessInterAdapterMessage sends the proxied messages to the target device
@@ -780,24 +815,32 @@
 		if omciMsg.GetProxyAddress() == nil {
 			onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
 			if err != nil {
-				log.Errorw("onu not found", log.Fields{"onuDeviceId": toDeviceID, "error": err})
-				return err
+				return NewErrNotFound("onu", log.Fields{
+					"device-id":     dh.device.Id,
+					"onu-device-id": toDeviceID}, err).Log()
 			}
 			log.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
-			dh.sendProxiedMessage(onuDevice, omciMsg)
-
+			if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
+				return NewErrCommunication("send-failed", log.Fields{
+					"device-id":     dh.device.Id,
+					"onu-device-id": toDeviceID}, err).Log()
+			}
 		} else {
 			log.Debugw("Proxy Address found in omci message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
-			dh.sendProxiedMessage(nil, omciMsg)
+			if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
+				return NewErrCommunication("send-failed", log.Fields{
+					"device-id":     dh.device.Id,
+					"onu-device-id": toDeviceID}, err).Log()
+			}
 		}
 
 	} else {
-		log.Errorw("inter-adapter-unhandled-type", log.Fields{"msgType": msg.Header.Type})
+		return NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil).Log()
 	}
 	return nil
 }
 
-func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) {
+func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
 	var intfID uint32
 	var onuID uint32
 	var connectStatus common.ConnectStatus_Types
@@ -812,7 +855,10 @@
 	}
 	if connectStatus != voltha.ConnectStatus_REACHABLE {
 		log.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
-		return
+
+		return NewErrCommunication("unreachable", log.Fields{
+			"interface-id": intfID,
+			"onu-id":       onuID}, nil).Log()
 	}
 
 	// TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
@@ -834,13 +880,16 @@
 
 	_, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
 	if err != nil {
-		log.Errorw("unable to send omci-msg-out", log.Fields{"IntfID": intfID, "OnuID": onuID, "Msg": omciMessage})
-		return
+		return NewErrCommunication("omci-send-failed", log.Fields{
+			"interface-id": intfID,
+			"onu-id":       onuID,
+			"message":      omciMessage}, err).Log()
 	}
 	log.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
+	return nil
 }
 
-func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) {
+func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
 	log.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
 	dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
 	// TODO: need resource manager
@@ -851,14 +900,15 @@
 		if st.Code() == codes.AlreadyExists {
 			log.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
 		} else {
-			log.Errorw("activate-onu-failed", log.Fields{"Onu": Onu, "err ": err})
+			return NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err).Log()
 		}
 	} else {
 		log.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
 	}
+	return nil
 }
 
-func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
+func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
 
 	channelID := onuDiscInd.GetIntfId()
 	parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
@@ -869,13 +919,12 @@
 	if sn != "" {
 		kwargs["serial_number"] = sn
 	} else {
-		log.Errorw("invalid-onu-serial-number", log.Fields{"sn": sn})
-		return
+		return NewErrInvalidValue(log.Fields{"serial-number": sn}, nil).Log()
 	}
 
 	if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
 		log.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
-		return
+		return nil
 	}
 
 	var onuID uint32
@@ -885,7 +934,7 @@
 	onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
 
 	if err != nil {
-		log.Errorw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
+		log.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
 		if e, ok := status.FromError(err); ok {
 			log.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
 			switch e.Code() {
@@ -895,7 +944,7 @@
 			case codes.DeadlineExceeded:
 				// if the call times out, cleanup and exit
 				dh.discOnus.Delete(sn)
-				return
+				return NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err).Log()
 			}
 		}
 	}
@@ -914,17 +963,19 @@
 		if err != nil {
 			// if we can't create an ID in resource manager,
 			// cleanup and exit
-			log.Warnw("resource-manage-get-onu-id-failed", log.Fields{"pon-intf-id": ponintfid, "err": err, "sn": sn})
 			dh.discOnus.Delete(sn)
-			return
+			return NewErrAdapter("resource-manage-get-onu-id-failed", log.Fields{
+				"pon-interface-id": ponintfid,
+				"serial-number":    sn}, err).Log()
 		}
 
 		if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
 			"", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
-			log.Warnw("core-proxy-child-device-detected-failed", log.Fields{"pon-intf-id": ponintfid, "err": err, "sn": sn})
 			dh.discOnus.Delete(sn)
 			dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
-			return
+			return NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
+				"pon-interface-id": ponintfid,
+				"serial-number":    sn}, err).Log()
 		}
 
 		log.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
@@ -943,119 +994,140 @@
 	dh.onus.Store(onuKey, onuDev)
 	log.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
 
-	err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED)
-	if err != nil {
-		log.Errorw("failed-to-update-device-state", log.Fields{"DeviceID": onuDevice.Id, "sn": sn, "err": err})
-		return
+	if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
+		return NewErrAdapter("failed-to-update-device-state", log.Fields{
+			"device-id":     onuDevice.Id,
+			"serial-number": sn}, err).Log()
 	}
 	log.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
 	//TODO: We put this sleep here to prevent the race between state update and onuIndication
 	//In onuIndication the operStatus of device is checked. If it is still not updated in KV store
 	//then the initialisation fails.
 	time.Sleep(1 * time.Second)
-	dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn)
-	return
+	if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
+		return NewErrAdapter("onu-activation-failed", log.Fields{
+			"device-id":     onuDevice.Id,
+			"serial-number": sn}, err).Log()
+	}
+	return nil
 }
 
-func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) {
+func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
 	serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
 
 	kwargs := make(map[string]interface{})
 	ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
 	var onuDevice *voltha.Device
+	var err error
 	foundInCache := false
 	log.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
 		"intfId": onuInd.GetIntfId()})
 	onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
 
+	errFields := log.Fields{"device-id": dh.device.Id}
+
 	if onuInCache, ok := dh.onus.Load(onuKey); ok {
 
 		//If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
 		foundInCache = true
-		onuDevice, _ = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
+		errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
+		onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
 	} else {
 		//If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
 		if serialNumber != "" {
 			kwargs["serial_number"] = serialNumber
+			errFields["serial-number"] = serialNumber
 		} else {
 			kwargs["onu_id"] = onuInd.OnuId
 			kwargs["parent_port_no"] = ponPort
+			errFields["onu-id"] = onuInd.OnuId
+			errFields["parent-port-no"] = ponPort
 		}
-		onuDevice, _ = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
+		onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
 	}
 
-	if onuDevice != nil {
-		if onuDevice.ParentPortNo != ponPort {
-			//log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": intfIDFromPortNo(onuDevice.ParentPortNo), "currentIntfId": onuInd.GetIntfId()})
-			log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{"previousIntfId": onuDevice.ParentPortNo, "currentIntfId": ponPort})
-		}
-
-		if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
-			log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{"expected_onu_id": onuDevice.ProxyAddress.OnuId, "received_onu_id": onuInd.OnuId})
-		}
-		if !foundInCache {
-			onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
-
-			dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
-
-		}
-		dh.updateOnuStates(onuDevice, onuInd, foundInCache)
-
-	} else {
-		log.Errorw("onu not found", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId})
-		return
+	if err != nil || onuDevice == nil {
+		return NewErrNotFound("onu-device", errFields, err).Log()
 	}
 
+	if onuDevice.ParentPortNo != ponPort {
+		log.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
+			"previousIntfId": onuDevice.ParentPortNo,
+			"currentIntfId":  ponPort})
+	}
+
+	if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
+		log.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
+			"expected_onu_id": onuDevice.ProxyAddress.OnuId,
+			"received_onu_id": onuInd.OnuId})
+	}
+	if !foundInCache {
+		onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
+
+		dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId))
+
+	}
+	if err := dh.updateOnuStates(onuDevice, onuInd, foundInCache); err != nil {
+		return NewErrCommunication("state-update-failed", errFields, err).Log()
+	}
+	return nil
 }
 
-func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) {
+func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication, foundInCache bool) error {
 	ctx := context.TODO()
 	log.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
 	dh.updateOnuAdminState(onuInd)
-	// operState
-	if onuInd.OperState == "down" {
+	switch onuInd.OperState {
+	case "down":
 		log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
 		// TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
 		err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
 			"openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
 		if err != nil {
-			log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
-				"From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
+			return NewErrCommunication("inter-adapter-send-failed", log.Fields{
+				"onu-indicator": onuInd,
+				"source":        "openolt",
+				"device-type":   onuDevice.Type,
+				"device-id":     onuDevice.Id}, err).Log()
 		}
-	} else if onuInd.OperState == "up" {
+	case "up":
 		// Ignore operstatus if device was found in cache
 		if !foundInCache && onuDevice.OperStatus != common.OperStatus_DISCOVERED {
 			log.Warnw("ignore-onu-indication", log.Fields{"intfID": onuInd.IntfId, "onuID": onuInd.OnuId, "operStatus": onuDevice.OperStatus, "msgOperStatus": onuInd.OperState})
-			return
+			return nil
 		}
 		log.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
 		// TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
 		err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
 			"openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
 		if err != nil {
-			log.Errorw("Failed to send inter-adapter-message", log.Fields{"OnuInd": onuInd,
-				"From Adapter": "openolt", "DevieType": onuDevice.Type, "DeviceID": onuDevice.Id})
-			return
+			return NewErrCommunication("inter-adapter-send-failed", log.Fields{
+				"onu-indicator": onuInd,
+				"source":        "openolt",
+				"device-type":   onuDevice.Type,
+				"device-id":     onuDevice.Id}, err).Log()
 		}
-	} else {
-		log.Warnw("Not-implemented-or-invalid-value-of-oper-state", log.Fields{"operState": onuInd.OperState})
+	default:
+		return NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil).Log()
 	}
+	return nil
 }
 
-func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) {
-	if onuInd.AdminState == "down" {
+func (dh *DeviceHandler) updateOnuAdminState(onuInd *oop.OnuIndication) error {
+	switch onuInd.AdminState {
+	case "down":
 		if onuInd.OperState != "down" {
 			log.Errorw("ONU-admin-state-down-and-oper-status-not-down", log.Fields{"operState": onuInd.OperState})
 			// Forcing the oper state change code to execute
 			onuInd.OperState = "down"
 		}
 		// Port and logical port update is taken care of by oper state block
-	} else if onuInd.AdminState == "up" {
+	case "up":
 		log.Debugln("received-onu-admin-state up")
-	} else {
-		log.Errorw("Invalid-or-not-implemented-admin-state", log.Fields{"received-admin-state": onuInd.AdminState})
+	default:
+		return NewErrInvalidValue(log.Fields{"admin-state": onuInd.AdminState}, nil).Log()
 	}
-	log.Debugln("admin-state-dealt-with")
+	return nil
 }
 
 func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
@@ -1079,42 +1151,45 @@
 
 //UpdateFlowsBulk upates the bulk flow
 func (dh *DeviceHandler) UpdateFlowsBulk() error {
-	return errors.New("unimplemented")
+	return ErrNotImplemented
 }
 
 //GetChildDevice returns the child device for given parent port and onu id
-func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) *voltha.Device {
+func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
 	log.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
 	kwargs := make(map[string]interface{})
 	kwargs["onu_id"] = onuID
 	kwargs["parent_port_no"] = parentPort
 	onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
 	if err != nil {
-		log.Errorw("onu not found", log.Fields{"intfID": parentPort, "onuID": onuID})
-		return nil
+		return nil, NewErrNotFound("onu", log.Fields{
+			"interface-id": parentPort,
+			"onu-id":       onuID}, err).Log()
 	}
 	log.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
-	return onuDevice
+	return onuDevice, nil
 }
 
 // SendPacketInToCore sends packet-in to core
 // For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
 // The adapter handling the device creates a device specific topic
-func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) {
+func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
 	log.Debugw("send-packet-in-to-core", log.Fields{
 		"port":   logicalPort,
 		"packet": hex.EncodeToString(packetPayload),
 	})
 	if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
-		log.Errorw("Error sending packetin to core", log.Fields{
-			"error":  err,
-			"packet": hex.EncodeToString(packetPayload),
-		})
-		return
+		return NewErrCommunication("packet-send-failed", log.Fields{
+			"source":       "adapter",
+			"destination":  "core",
+			"device-id":    dh.device.Id,
+			"logical-port": logicalPort,
+			"packet":       hex.EncodeToString(packetPayload)}, err).Log()
 	}
 	log.Debugw("Sent packet-in to core successfully", log.Fields{
 		"packet": hex.EncodeToString(packetPayload),
 	})
+	return nil
 }
 
 // AddUniPortToOnu adds the uni port to the onu device
@@ -1180,11 +1255,10 @@
 	if dh.Client != nil {
 		if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
 			if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
-				log.Errorw("failed-to-disable-olt ", log.Fields{"err": err, "deviceID": device.Id})
 				dh.lockDevice.Lock()
 				dh.adminState = "up"
 				dh.lockDevice.Unlock()
-				return err
+				return NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err).Log()
 			}
 		}
 	}
@@ -1247,11 +1321,10 @@
 
 	if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
 		if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
-			log.Errorw("Failed to reenable olt ", log.Fields{"err": err})
 			dh.lockDevice.Lock()
 			dh.adminState = "down"
 			dh.lockDevice.Unlock()
-			return err
+			return NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
 		}
 	}
 	log.Debug("olt-reenabled")
@@ -1260,16 +1333,17 @@
 	// Update the all ports state on that device to enable
 
 	if err := dh.disableAdminDownPorts(device); err != nil {
-		log.Errorw("Error-on-updating-port-status-after-reenabling-olt", log.Fields{"device": device})
-		return err
+		return NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err).Log()
 	}
 	//Update the device oper status as ACTIVE
 	cloned.OperStatus = voltha.OperStatus_ACTIVE
 	dh.device = cloned
 
 	if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
-		log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
-		return err
+		return NewErrAdapter("state-update-failed", log.Fields{
+			"device-id":      device.Id,
+			"connect-status": cloned.ConnectStatus,
+			"oper-status":    cloned.OperStatus}, err).Log()
 	}
 
 	log.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
@@ -1325,8 +1399,7 @@
 	//Free the flow-ids for the NNI port
 	nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
 	if err != nil {
-		log.Error("Failed to fetch nni from kv store")
-		return err
+		return NewErrPersistence("get", "nni", 0, nil, err).Log()
 	}
 	log.Debugw("NNI are ", log.Fields{"nni": nni})
 	for _, nniIntfID := range nni {
@@ -1338,10 +1411,9 @@
 		dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
 	}
 	if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
-		log.Error("Failed to clear nni from kv store")
-		return err
+		return NewErrPersistence("clear", "nni", 0, nil, err).Log()
 	}
-	return err
+	return nil
 }
 
 // DeleteDevice deletes the device instance from openolt handler array.  Also clears allocated resource manager resources.  Also reboots the OLT hardware!
@@ -1365,8 +1437,9 @@
 			var onuGemData []rsrcMgr.OnuGemInfo
 			err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
 			if err != nil {
-				log.Errorw("Failed to get onu info for port ", log.Fields{"ponport": ponPort})
-				return err
+				return NewErrNotFound("onu", log.Fields{
+					"device-id": dh.device.Id,
+					"pon-port":  ponPort}, err).Log()
 			}
 			for _, onu := range onuGemData {
 				onuID := make([]uint32, 1)
@@ -1413,16 +1486,17 @@
 	//Reset the state
 	if dh.Client != nil {
 		if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
-			log.Errorw("Failed-to-reboot-olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
-			return err
+			return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
 		}
 	}
 	cloned := proto.Clone(device).(*voltha.Device)
 	cloned.OperStatus = voltha.OperStatus_UNKNOWN
 	cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
 	if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
-		log.Errorw("error-updating-device-state", log.Fields{"deviceID": device.Id, "error": err})
-		return err
+		return NewErrAdapter("device-state-update-failed", log.Fields{
+			"device-id":      device.Id,
+			"connect-status": cloned.ConnectStatus,
+			"oper-status":    cloned.OperStatus}, err).Log()
 	}
 	return nil
 }
@@ -1430,42 +1504,35 @@
 //RebootDevice reboots the given device
 func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
 	if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
-		log.Errorw("Failed to reboot olt ", log.Fields{"deviceID": dh.deviceID, "err": err})
-		return err
+		return NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
 	}
-
 	log.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
-
 	return nil
 }
 
-func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) {
+func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
 	log.Debugw("Received packet-in", log.Fields{
 		"packet-indication": *packetIn,
 		"packet":            hex.EncodeToString(packetIn.Pkt),
 	})
 	logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
 	if err != nil {
-		log.Errorw("Error getting logical port from packet-in", log.Fields{
-			"error":  err,
-			"packet": hex.EncodeToString(packetIn.Pkt),
-		})
-		return
+		return NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err).Log()
 	}
 	log.Debugw("sending packet-in to core", log.Fields{
 		"logicalPortNum": logicalPortNum,
 		"packet":         hex.EncodeToString(packetIn.Pkt),
 	})
 	if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
-		log.Errorw("Error sending packet-in to core", log.Fields{
-			"error":  err,
-			"packet": hex.EncodeToString(packetIn.Pkt),
-		})
-		return
+		return NewErrCommunication("send-packet-in", log.Fields{
+			"destination": "core",
+			"source":      dh.deviceType,
+			"packet":      hex.EncodeToString(packetIn.Pkt)}, err).Log()
 	}
 	log.Debugw("Success sending packet-in to core!", log.Fields{
 		"packet": hex.EncodeToString(packetIn.Pkt),
 	})
+	return nil
 }
 
 // PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
@@ -1523,14 +1590,22 @@
 		})
 
 		if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
-			log.Errorw("Error while sending packet-out to ONU", log.Fields{
-				"error":  err,
-				"packet": hex.EncodeToString(packet.Data),
-			})
-			return err
+			return NewErrCommunication("packet-out-send", log.Fields{
+				"source":             "adapter",
+				"destination":        "onu",
+				"egress-port-number": egressPortNo,
+				"interface-id":       intfID,
+				"oni-id":             onuID,
+				"uni-id":             uniID,
+				"gem-port-id":        gemPortID,
+				"packet":             hex.EncodeToString(packet.Data)}, err).Log()
 		}
 	} else if egressPortType == voltha.Port_ETHERNET_NNI {
-		uplinkPkt := oop.UplinkPacket{IntfId: IntfIDFromNniPortNum(uint32(egressPortNo)), Pkt: packet.Data}
+		nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
+		if err != nil {
+			return NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err).Log()
+		}
+		uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
 
 		log.Debugw("sending-packet-to-nni", log.Fields{
 			"uplink_pkt": uplinkPkt,
@@ -1538,11 +1613,7 @@
 		})
 
 		if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
-			log.Errorw("Error while sending packet-out to NNI", log.Fields{
-				"error":  err,
-				"packet": hex.EncodeToString(packet.Data),
-			})
-			return err
+			return NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err).Log()
 		}
 	} else {
 		log.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
@@ -1602,8 +1673,7 @@
 
 	go dh.notifyChildDevices("unreachable")
 	if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
-		log.Errorw("error-updating-device-state", log.Fields{"deviceID": dh.device.Id, "error": err})
-		return
+		NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
 	}
 }
 
@@ -1627,7 +1697,9 @@
 		// Bug is opened for VOL-2505 to support NNI disable feature.
 		log.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
 			log.Fields{"Device": dh.device, "port": port})
-		return fmt.Errorf("received-disable-enable-nni-port-request, received-port %s", port.GetType())
+		return NewErrAdapter("illegal-port-request", log.Fields{
+			"port-type":    port.GetType,
+			"enable-state": enablePort}, nil).Log()
 	}
 	// fetch interfaceid from PortNo
 	ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
@@ -1638,8 +1710,9 @@
 		out, err := dh.Client.EnablePonIf(ctx, ponIntf)
 
 		if err != nil {
-			log.Errorw("error-while-enable-Pon-port", log.Fields{"DeviceID": dh.device, "Port": port, "error": err})
-			return err
+			return NewErrAdapter("pon-port-enable-failed", log.Fields{
+				"device-id": dh.device.Id,
+				"port":      port}, err).Log()
 		}
 		// updating interface local cache for collecting stats
 		dh.activePorts.Store(ponID, true)
@@ -1648,16 +1721,18 @@
 		operStatus = voltha.OperStatus_UNKNOWN
 		out, err := dh.Client.DisablePonIf(ctx, ponIntf)
 		if err != nil {
-			log.Errorw("error-while-disabling-interface", log.Fields{"DeviceID": dh.device, "Port": port})
-			return err
+			return NewErrAdapter("pon-port-disable-failed", log.Fields{
+				"device-id": dh.device.Id,
+				"port":      port}, err).Log()
 		}
 		// updating interface local cache for collecting stats
 		dh.activePorts.Store(ponID, false)
 		log.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
 	}
-	if errs := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); errs != nil {
-		log.Errorw("portstate-update-failed", log.Fields{"Device": dh.deviceID, "port": port.PortNo, "error": errs})
-		return errs
+	if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
+		return NewErrAdapter("port-state-update-failed", log.Fields{
+			"device-id": dh.deviceID,
+			"port":      port.PortNo}, err).Log()
 	}
 	return nil
 }
@@ -1670,8 +1745,9 @@
 	for _, port := range cloned.Ports {
 		if port.AdminState == common.AdminState_DISABLED {
 			if err := dh.DisablePort(port); err != nil {
-				log.Errorw("error-occurred-while-disabling-port", log.Fields{"DeviceId": dh.deviceID, "port": port, "error": err})
-				return err
+				return NewErrAdapter("port-disable-failed", log.Fields{
+					"device-id": dh.deviceID,
+					"port":      port}, err).Log()
 			}
 		}
 	}