diff --git a/lib/stats.go b/lib/stats.go index 229d8409..591156e7 100644 --- a/lib/stats.go +++ b/lib/stats.go @@ -15,8 +15,8 @@ import ( type ContainerStats struct { Container string CPU float64 - cpuNano uint64 - systemNano uint64 + CPUNano uint64 + SystemNano uint64 MemUsage uint64 MemLimit uint64 MemPerc float64 @@ -29,8 +29,8 @@ type ContainerStats struct { // GetContainerStats gets the running stats for a given container func (c *ContainerServer) GetContainerStats(ctr *oci.Container, previousStats *ContainerStats) (*ContainerStats, error) { - previousCPU := previousStats.cpuNano - previousSystem := previousStats.systemNano + previousCPU := previousStats.CPUNano + previousSystem := previousStats.SystemNano libcontainerStats, err := c.LibcontainerStats(ctr) if err != nil { return nil, err diff --git a/server/container_stats.go b/server/container_stats.go index 17df31ad..8e6176af 100644 --- a/server/container_stats.go +++ b/server/container_stats.go @@ -4,6 +4,7 @@ import ( "fmt" "time" + "github.com/kubernetes-incubator/cri-o/lib" "golang.org/x/net/context" pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" ) @@ -16,5 +17,35 @@ func (s *Server) ContainerStats(ctx context.Context, req *pb.ContainerStatsReque recordOperation(operation, time.Now()) recordError(operation, err) }() - return nil, fmt.Errorf("not implemented") + + container := s.GetContainer(req.ContainerId) + if container == nil { + return nil, fmt.Errorf("invalid container") + } + + now := time.Now().UnixNano() + stats, err := s.GetContainerStats(container, &lib.ContainerStats{}) + if err != nil { + return nil, err + } + + return &pb.ContainerStatsResponse{ + &pb.ContainerStats{ + Attributes: &pb.ContainerAttributes{ + Id: req.ContainerId, + Metadata: container.Metadata(), + Labels: container.Labels(), + Annotations: container.Annotations(), + }, + Cpu: &pb.CpuUsage{ + Timestamp: now, + UsageCoreNanoSeconds: &pb.UInt64Value{stats.CPUNano + stats.SystemNano}, + }, + Memory: &pb.MemoryUsage{ + Timestamp: now, + WorkingSetBytes: &pb.UInt64Value{stats.MemUsage}, + }, + WritableLayer: nil, + }, + }, nil } diff --git a/server/container_stats_list.go b/server/container_stats_list.go index 2c564714..7c78879b 100644 --- a/server/container_stats_list.go +++ b/server/container_stats_list.go @@ -1,9 +1,9 @@ package server import ( - "fmt" "time" + "github.com/sirupsen/logrus" "golang.org/x/net/context" pb "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" ) @@ -15,5 +15,32 @@ func (s *Server) ListContainerStats(ctx context.Context, req *pb.ListContainerSt recordOperation(operation, time.Now()) recordError(operation, err) }() - return nil, fmt.Errorf("not implemented") + + // This is an inefficient method, since the container will be resolved twice, + // once by the container list code and once by the GetContainerStats call. + containers, err := s.ListContainers(ctx, &pb.ListContainersRequest{ + &pb.ContainerFilter{ + Id: req.Filter.Id, + PodSandboxId: req.Filter.PodSandboxId, + LabelSelector: req.Filter.LabelSelector, + }, + }) + if err != nil { + return nil, err + } + + var allStats []*pb.ContainerStats + + for _, container := range containers.Containers { + stats, err := s.ContainerStats(ctx, &pb.ContainerStatsRequest{ContainerId: container.Id}) + if err != nil { + logrus.Warn("unable to get stats for container %s", container.Id) + continue + } + allStats = append(allStats, stats.Stats) + } + + return &pb.ListContainerStatsResponse{ + Stats: allStats, + }, nil }