func getDeviceUplinks()

in x-pack/metricbeat/module/meraki/device_health/uplinks.go [25:121]


func getDeviceUplinks(client *meraki.Client, organizationID string, devices map[Serial]*Device, period time.Duration) error {
	// there are two separate APIs for uplink statuses depending on the type of device (MG or MX/Z).
	// there is a single API for getting the loss and latency metrics regardless of the type of device.
	// in this function we combine loss and latency metrics with device-specific status information,
	// and attach it to the relevant device in the supplied `devices` data structure.
	applicanceUplinks, res, err := client.Appliance.GetOrganizationApplianceUplinkStatuses(organizationID, &meraki.GetOrganizationApplianceUplinkStatusesQueryParams{})
	if err != nil {
		return fmt.Errorf("GetOrganizationApplianceUplinkStatuses failed; [%d] %s. %w", res.StatusCode(), res.Body(), err)
	}

	lossAndLatency, res, err := client.Organizations.GetOrganizationDevicesUplinksLossAndLatency(
		organizationID,
		&meraki.GetOrganizationDevicesUplinksLossAndLatencyQueryParams{
			Timespan: period.Seconds(),
		},
	)
	if err != nil {
		return fmt.Errorf("GetOrganizationDevicesUplinksLossAndLatency failed; [%d] %s. %w", res.StatusCode(), res.Body(), err)
	}

	if applicanceUplinks == nil || lossAndLatency == nil {
		return errors.New("unexpected response from Meraki API: applicanceUplinks or lossAndLatency is nil")
	}

	for _, device := range *applicanceUplinks {
		deviceObj, ok := devices[Serial(device.Serial)]
		if device.HighAvailability != nil && ok && deviceObj != nil {
			devices[Serial(device.Serial)].haStatus = device.HighAvailability
		}

		if device.Uplinks != nil {
			var uplinks []*uplink
			for i := range *device.Uplinks {
				uplinkStatus := (*device.Uplinks)[i]
				uplink := &uplink{
					lastReportedAt: device.LastReportedAt,
					status:         &uplinkStatus,
				}

				for j := range *lossAndLatency {
					metrics := (*lossAndLatency)[j]
					if metrics.TimeSeries != nil && metrics.Serial == device.Serial && metrics.Uplink == uplinkStatus.Interface {
						uplink.lossAndLatency = &metrics
						break
					}
				}

				uplinks = append(uplinks, uplink)
			}

			if ok && deviceObj != nil {
				devices[Serial(device.Serial)].uplinks = uplinks
			}
		}
	}

	cellularGatewayUplinks, res, err := client.CellularGateway.GetOrganizationCellularGatewayUplinkStatuses(organizationID, &meraki.GetOrganizationCellularGatewayUplinkStatusesQueryParams{})
	if err != nil {
		return fmt.Errorf("GetOrganizationCellularGatewayUplinkStatuses failed; [%d] %s. %w", res.StatusCode(), res.Body(), err)
	}

	if cellularGatewayUplinks == nil {
		return errors.New("unexpected response from Meraki API: cellularGatewayUplinks is nil")
	}

	for _, device := range *cellularGatewayUplinks {
		if device.Uplinks == nil {
			continue
		}

		var uplinks []*uplink
		for i := range *device.Uplinks {
			uplinkStatus := (*device.Uplinks)[i]
			uplink := &uplink{
				lastReportedAt:        device.LastReportedAt,
				cellularGatewayStatus: &uplinkStatus,
			}

			for j := range *lossAndLatency {
				metrics := (*lossAndLatency)[j]
				if metrics.TimeSeries != nil && metrics.Serial == device.Serial && metrics.Uplink == uplinkStatus.Interface {
					uplink.lossAndLatency = &metrics
					break
				}
			}

			uplinks = append(uplinks, uplink)
		}

		deviceObj, ok := devices[Serial(device.Serial)]
		if ok && deviceObj != nil {
			devices[Serial(device.Serial)].uplinks = uplinks
		}
	}

	return nil
}