// Get cgroup and networking stats of the specified container func GetStats(cgroupManager cgroups.Manager, rootFs string, pid int, ignoreMetrics container.MetricSet) (*info.ContainerStats, error) { cgroupStats, err := cgroupManager.GetStats() if err != nil { return nil, err } libcontainerStats := &libcontainer.Stats{ CgroupStats: cgroupStats, } stats := toContainerStats(libcontainerStats) // If we know the pid then get network stats from /proc/<pid>/net/dev if pid == 0 { return stats, nil } if !ignoreMetrics.Has(container.NetworkUsageMetrics) { netStats, err := networkStatsFromProc(rootFs, pid) if err != nil { glog.V(2).Infof("Unable to get network stats from pid %d: %v", pid, err) } else { stats.Network.Interfaces = append(stats.Network.Interfaces, netStats...) } } if !ignoreMetrics.Has(container.NetworkTcpUsageMetrics) { t, err := tcpStatsFromProc(rootFs, pid, "net/tcp") if err != nil { glog.V(2).Infof("Unable to get tcp stats from pid %d: %v", pid, err) } else { stats.Network.Tcp = t } t6, err := tcpStatsFromProc(rootFs, pid, "net/tcp6") if err != nil { glog.V(2).Infof("Unable to get tcp6 stats from pid %d: %v", pid, err) } else { stats.Network.Tcp6 = t6 } } // For backwards compatibility. if len(stats.Network.Interfaces) > 0 { stats.Network.InterfaceStats = stats.Network.Interfaces[0] } return stats, nil }
func newDockerContainerHandler( client *docker.Client, name string, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, storageDriver storageDriver, storageDir string, cgroupSubsystems *containerlibcontainer.CgroupSubsystems, inHostNamespace bool, metadataEnvs []string, dockerVersion []int, ignoreMetrics container.MetricSet, ) (container.ContainerHandler, error) { // Create the cgroup paths. cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints)) for key, val := range cgroupSubsystems.MountPoints { cgroupPaths[key] = path.Join(val, name) } // Generate the equivalent cgroup manager for this container. cgroupManager := &cgroupfs.Manager{ Cgroups: &libcontainerconfigs.Cgroup{ Name: name, }, Paths: cgroupPaths, } rootFs := "/" if !inHostNamespace { rootFs = "/rootfs" storageDir = path.Join(rootFs, storageDir) } id := ContainerNameToDockerId(name) // Add the Containers dir where the log files are stored. // FIXME: Give `otherStorageDir` a more descriptive name. otherStorageDir := path.Join(storageDir, pathToContainersDir, id) rwLayerID, err := getRwLayerID(id, storageDir, storageDriver, dockerVersion) if err != nil { return nil, err } var rootfsStorageDir string switch storageDriver { case aufsStorageDriver: rootfsStorageDir = path.Join(storageDir, string(aufsStorageDriver), aufsRWLayer, rwLayerID) case overlayStorageDriver: rootfsStorageDir = path.Join(storageDir, string(overlayStorageDriver), rwLayerID) } handler := &dockerContainerHandler{ id: id, client: client, name: name, machineInfoFactory: machineInfoFactory, cgroupPaths: cgroupPaths, cgroupManager: cgroupManager, storageDriver: storageDriver, fsInfo: fsInfo, rootFs: rootFs, rootfsStorageDir: rootfsStorageDir, envs: make(map[string]string), ignoreMetrics: ignoreMetrics, } if !ignoreMetrics.Has(container.DiskUsageMetrics) { handler.fsHandler = common.NewFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo) } // We assume that if Inspect fails then the container is not known to docker. ctnr, err := client.InspectContainer(id) if err != nil { return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) } handler.creationTime = ctnr.Created handler.pid = ctnr.State.Pid // Add the name and bare ID as aliases of the container. handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id) handler.labels = ctnr.Config.Labels handler.image = ctnr.Config.Image handler.networkMode = ctnr.HostConfig.NetworkMode // split env vars to get metadata map. for _, exposedEnv := range metadataEnvs { for _, envVar := range ctnr.Config.Env { splits := strings.SplitN(envVar, "=", 2) if splits[0] == exposedEnv { handler.envs[strings.ToLower(exposedEnv)] = splits[1] } } } return handler, nil }
func newRktContainerHandler(name string, rktClient rktapi.PublicAPIClient, rktPath string, cgroupSubsystems *libcontainer.CgroupSubsystems, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, rootFs string, ignoreMetrics container.MetricSet) (container.ContainerHandler, error) { aliases := make([]string, 1) isPod := false apiPod := &rktapi.Pod{} parsed, err := parseName(name) if err != nil { return nil, fmt.Errorf("this should be impossible!, new handler failing, but factory allowed, name = %s", name) } //rktnetes uses containerID: rkt://fff40827-b994-4e3a-8f88-6427c2c8a5ac:nginx if parsed.Container == "" { isPod = true aliases = append(aliases, "rkt://"+parsed.Pod) } else { aliases = append(aliases, "rkt://"+parsed.Pod+":"+parsed.Container) } pid := os.Getpid() labels := make(map[string]string) resp, err := rktClient.InspectPod(context.Background(), &rktapi.InspectPodRequest{ Id: parsed.Pod, }) if err != nil { return nil, err } else { var annotations []*rktapi.KeyValue if parsed.Container == "" { pid = int(resp.Pod.Pid) apiPod = resp.Pod annotations = resp.Pod.Annotations } else { var ok bool if annotations, ok = findAnnotations(resp.Pod.Apps, parsed.Container); !ok { glog.Warningf("couldn't find application in Pod matching %v", parsed.Container) } } labels = createLabels(annotations) } cgroupPaths := common.MakeCgroupPaths(cgroupSubsystems.MountPoints, name) // Generate the equivalent cgroup manager for this container. cgroupManager := &cgroupfs.Manager{ Cgroups: &configs.Cgroup{ Name: name, }, Paths: cgroupPaths, } hasNetwork := false if isPod { hasNetwork = true } rootfsStorageDir := getRootFs(rktPath, parsed) handler := &rktContainerHandler{ name: name, rktClient: rktClient, cgroupSubsystems: cgroupSubsystems, machineInfoFactory: machineInfoFactory, cgroupPaths: cgroupPaths, cgroupManager: cgroupManager, fsInfo: fsInfo, hasNetwork: hasNetwork, rootFs: rootFs, isPod: isPod, aliases: aliases, pid: pid, labels: labels, rootfsStorageDir: rootfsStorageDir, ignoreMetrics: ignoreMetrics, apiPod: apiPod, } if !ignoreMetrics.Has(container.DiskUsageMetrics) { handler.fsHandler = common.NewFsHandler(time.Minute, rootfsStorageDir, "", fsInfo) } return handler, nil }
// newDockerContainerHandler returns a new container.ContainerHandler func newDockerContainerHandler( client *docker.Client, name string, machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo, storageDriver storageDriver, storageDir string, cgroupSubsystems *containerlibcontainer.CgroupSubsystems, inHostNamespace bool, metadataEnvs []string, dockerVersion []int, ignoreMetrics container.MetricSet, thinPoolWatcher *devicemapper.ThinPoolWatcher, ) (container.ContainerHandler, error) { // Create the cgroup paths. cgroupPaths := make(map[string]string, len(cgroupSubsystems.MountPoints)) for key, val := range cgroupSubsystems.MountPoints { cgroupPaths[key] = path.Join(val, name) } // Generate the equivalent cgroup manager for this container. cgroupManager := &cgroupfs.Manager{ Cgroups: &libcontainerconfigs.Cgroup{ Name: name, }, Paths: cgroupPaths, } rootFs := "/" if !inHostNamespace { rootFs = "/rootfs" storageDir = path.Join(rootFs, storageDir) } id := ContainerNameToDockerId(name) // Add the Containers dir where the log files are stored. // FIXME: Give `otherStorageDir` a more descriptive name. otherStorageDir := path.Join(storageDir, pathToContainersDir, id) rwLayerID, err := getRwLayerID(id, storageDir, storageDriver, dockerVersion) if err != nil { return nil, err } // Determine the rootfs storage dir OR the pool name to determine the device var ( rootfsStorageDir string poolName string ) switch storageDriver { case aufsStorageDriver: rootfsStorageDir = path.Join(storageDir, string(aufsStorageDriver), aufsRWLayer, rwLayerID) case overlayStorageDriver: rootfsStorageDir = path.Join(storageDir, string(overlayStorageDriver), rwLayerID) case devicemapperStorageDriver: status, err := Status() if err != nil { return nil, fmt.Errorf("unable to determine docker status: %v", err) } poolName = status.DriverStatus[dockerutil.DriverStatusPoolName] } // TODO: extract object mother method handler := &dockerContainerHandler{ id: id, client: client, name: name, machineInfoFactory: machineInfoFactory, cgroupPaths: cgroupPaths, cgroupManager: cgroupManager, storageDriver: storageDriver, fsInfo: fsInfo, rootFs: rootFs, poolName: poolName, rootfsStorageDir: rootfsStorageDir, envs: make(map[string]string), ignoreMetrics: ignoreMetrics, thinPoolWatcher: thinPoolWatcher, } // We assume that if Inspect fails then the container is not known to docker. ctnr, err := client.ContainerInspect(context.Background(), id) if err != nil { return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) } // Timestamp returned by Docker is in time.RFC3339Nano format. handler.creationTime, err = time.Parse(time.RFC3339Nano, ctnr.Created) if err != nil { // This should not happen, report the error just in case return nil, fmt.Errorf("failed to parse the create timestamp %q for container %q: %v", ctnr.Created, id, err) } handler.pid = ctnr.State.Pid // Add the name and bare ID as aliases of the container. handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"), id) handler.labels = ctnr.Config.Labels handler.image = ctnr.Config.Image handler.networkMode = ctnr.HostConfig.NetworkMode handler.deviceID = ctnr.GraphDriver.Data["DeviceId"] // Obtain the IP address for the contianer. // If the NetworkMode starts with 'container:' then we need to use the IP address of the container specified. // This happens in cases such as kubernetes where the containers doesn't have an IP address itself and we need to use the pod's address ipAddress := ctnr.NetworkSettings.IPAddress networkMode := string(ctnr.HostConfig.NetworkMode) if ipAddress == "" && strings.HasPrefix(networkMode, "container:") { containerId := strings.TrimPrefix(networkMode, "container:") c, err := client.ContainerInspect(context.Background(), containerId) if err != nil { return nil, fmt.Errorf("failed to inspect container %q: %v", id, err) } ipAddress = c.NetworkSettings.IPAddress } handler.ipAddress = ipAddress if !ignoreMetrics.Has(container.DiskUsageMetrics) { handler.fsHandler = &dockerFsHandler{ fsHandler: common.NewFsHandler(time.Minute, rootfsStorageDir, otherStorageDir, fsInfo), thinPoolWatcher: thinPoolWatcher, deviceID: handler.deviceID, } } // split env vars to get metadata map. for _, exposedEnv := range metadataEnvs { for _, envVar := range ctnr.Config.Env { splits := strings.SplitN(envVar, "=", 2) if splits[0] == exposedEnv { handler.envs[strings.ToLower(exposedEnv)] = splits[1] } } } return handler, nil }