func()

in agent/stats/engine.go [640:719]


func (engine *DockerStatsEngine) taskContainerMetricsUnsafe(taskArn string) ([]*ecstcs.ContainerMetric, error) {
	containerMap, taskExists := engine.tasksToContainers[taskArn]
	if !taskExists {
		return nil, fmt.Errorf("task not found")
	}

	var containerMetrics []*ecstcs.ContainerMetric
	for _, container := range containerMap {
		dockerID := container.containerMetadata.DockerID
		// Check if the container is terminal. If it is, make sure that it is
		// cleaned up properly. We might sometimes miss events from docker task
		// engine and this helps in reconciling the state. The tcs client's
		// GetInstanceMetrics probe is used as the trigger for this.
		if engine.stopTrackingContainerUnsafe(container, taskArn) {
			continue
		}

		// CPU and Memory are both critical, so skip the container if either of these fail.
		cpuStatsSet, err := container.statsQueue.GetCPUStatsSet()
		if err != nil {
			seelog.Infof("cloudwatch metrics for container %v not collected, reason (cpu): %v", dockerID, err)
			continue
		}
		memoryStatsSet, err := container.statsQueue.GetMemoryStatsSet()
		if err != nil {
			seelog.Infof("cloudwatch metrics for container %v not collected, reason (memory): %v", dockerID, err)
			continue
		}

		containerMetric := &ecstcs.ContainerMetric{
			ContainerName:  &container.containerMetadata.Name,
			CpuStatsSet:    cpuStatsSet,
			MemoryStatsSet: memoryStatsSet,
		}

		storageStatsSet, err := container.statsQueue.GetStorageStatsSet()
		if err != nil {
			seelog.Warnf("Error getting storage stats, err: %v, container: %v", err, dockerID)
		} else {
			containerMetric.StorageStatsSet = storageStatsSet
		}

		task, err := engine.resolver.ResolveTask(dockerID)
		if err != nil {
			seelog.Warnf("Task not found for container ID: %s", dockerID)
		} else {
			// send network stats for default/bridge/nat/awsvpc network modes
			if !task.IsNetworkModeAWSVPC() && container.containerMetadata.NetworkMode != hostNetworkMode &&
				container.containerMetadata.NetworkMode != noneNetworkMode {
				networkStatsSet, err := container.statsQueue.GetNetworkStatsSet()
				if err != nil {
					// we log the error and still continue to publish cpu, memory stats
					seelog.Warnf("Error getting network stats: %v, container: %v", err, dockerID)
				} else {
					containerMetric.NetworkStatsSet = networkStatsSet
				}
			} else if task.IsNetworkModeAWSVPC() {
				taskStatsMap, taskExistsInTaskStats := engine.taskToTaskStats[taskArn]
				if !taskExistsInTaskStats {
					return nil, fmt.Errorf("task not found")
				}
				if dockerContainer, err := engine.resolver.ResolveContainer(dockerID); err != nil {
					seelog.Debugf("Could not map container ID to container, container: %s, err: %s", dockerID, err)
				} else {
					// do not add network stats for pause container
					if dockerContainer.Container.Type != apicontainer.ContainerCNIPause {
						networkStats, err := taskStatsMap.StatsQueue.GetNetworkStatsSet()
						if err != nil {
							seelog.Warnf("error getting network stats: %v, task: %v", err, taskArn)
						} else {
							containerMetric.NetworkStatsSet = networkStats
						}
					}
				}
			}
		}
		containerMetrics = append(containerMetrics, containerMetric)
	}
	return containerMetrics, nil
}