WIP: Add stats API for 2.0.
First cut on 2.0 stats API. Main change in returned stats is that presence checks (eg. HasCPU) are embedded in each stat. Added support to handle querying container with name. Current syntax: /stats?name=/&count=1, /stats?name=docker/928c058ce260ac2a55972b18cb991fa0475fbbb7bc15bd295e62b76964d05fe6 [default count: 64] Other handlers to include: dockerid, dockeralias. We can make subcontainers inclusion as an option too.
This commit is contained in:
parent
a0a419614f
commit
2e2a31bea2
@ -17,6 +17,7 @@ package api
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/google/cadvisor/events"
|
||||
@ -31,6 +32,7 @@ const (
|
||||
machineApi = "machine"
|
||||
dockerApi = "docker"
|
||||
summaryApi = "summary"
|
||||
statsApi = "stats"
|
||||
specApi = "spec"
|
||||
eventsApi = "events"
|
||||
storageApi = "storage"
|
||||
@ -314,6 +316,22 @@ func (self *version2_0) HandleRequest(requestType string, request []string, m ma
|
||||
}
|
||||
|
||||
return writeResult(stats, w)
|
||||
case statsApi:
|
||||
name := getContainerName(request)
|
||||
sr, err := getStatsRequest(name, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
glog.V(2).Infof("Api - Stats: Looking for stats for container %q, options %+v", name, sr)
|
||||
query := info.ContainerInfoRequest{
|
||||
NumStats: sr.Count,
|
||||
}
|
||||
cont, err := m.GetContainerInfo(name, &query)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get container %q: %v", name, err)
|
||||
}
|
||||
contStats := convertStats(cont)
|
||||
return writeResult(contStats, w)
|
||||
case specApi:
|
||||
containerName := getContainerName(request)
|
||||
glog.V(2).Infof("Api - Spec(%v)", containerName)
|
||||
@ -365,3 +383,59 @@ func convertSpec(specV1 info.ContainerSpec) v2.ContainerSpec {
|
||||
}
|
||||
return specV2
|
||||
}
|
||||
|
||||
func convertStats(cont *info.ContainerInfo) []v2.ContainerStats {
|
||||
stats := []v2.ContainerStats{}
|
||||
for _, val := range cont.Stats {
|
||||
stat := v2.ContainerStats{
|
||||
Timestamp: val.Timestamp,
|
||||
HasCpu: cont.Spec.HasCpu,
|
||||
HasMemory: cont.Spec.HasMemory,
|
||||
HasNetwork: cont.Spec.HasNetwork,
|
||||
HasFilesystem: cont.Spec.HasFilesystem,
|
||||
HasDiskIo: cont.Spec.HasDiskIo,
|
||||
}
|
||||
if stat.HasCpu {
|
||||
stat.Cpu = val.Cpu
|
||||
}
|
||||
if stat.HasMemory {
|
||||
stat.Memory = val.Memory
|
||||
}
|
||||
if stat.HasNetwork {
|
||||
// TODO(rjnagal): Return stats about all network interfaces.
|
||||
stat.Network = append(stat.Network, val.Network)
|
||||
}
|
||||
if stat.HasFilesystem {
|
||||
stat.Filesystem = val.Filesystem
|
||||
}
|
||||
if stat.HasDiskIo {
|
||||
stat.DiskIo = val.DiskIo
|
||||
}
|
||||
// TODO(rjnagal): Handle load stats.
|
||||
stats = append(stats, stat)
|
||||
}
|
||||
return stats
|
||||
}
|
||||
|
||||
func getStatsRequest(id string, r *http.Request) (v2.StatsRequest, error) {
|
||||
// fill in the defaults.
|
||||
sr := v2.StatsRequest{
|
||||
IdType: "name",
|
||||
Count: 64,
|
||||
Recursive: false,
|
||||
}
|
||||
idType := r.URL.Query().Get("type")
|
||||
if len(idType) != 0 && idType != "name" {
|
||||
return sr, fmt.Errorf("unknown 'type' %q for container name %q", idType, id)
|
||||
}
|
||||
count := r.URL.Query().Get("count")
|
||||
if len(count) != 0 {
|
||||
n, err := strconv.ParseUint(count, 10, 32)
|
||||
if err != nil {
|
||||
return sr, fmt.Errorf("failed to parse 'count' option: %v", count)
|
||||
}
|
||||
sr.Count = int(n)
|
||||
}
|
||||
// TODO(rjnagal): Add option to specify recursive.
|
||||
return sr, nil
|
||||
}
|
||||
|
@ -16,6 +16,10 @@ package v2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
// TODO(rjnagal): Remove dependency after moving all stats structs from v1.
|
||||
// using v1 now for easy conversion.
|
||||
"github.com/google/cadvisor/info/v1"
|
||||
)
|
||||
|
||||
type CpuSpec struct {
|
||||
@ -54,6 +58,29 @@ type ContainerSpec struct {
|
||||
Memory MemorySpec `json:"memory,omitempty"`
|
||||
}
|
||||
|
||||
type ContainerStats struct {
|
||||
// The time of this stat point.
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
// CPU statistics
|
||||
HasCpu bool `json:"has_cpu"`
|
||||
Cpu v1.CpuStats `json:"cpu,omitempty"`
|
||||
// Disk IO statistics
|
||||
HasDiskIo bool `json:"has_diskio"`
|
||||
DiskIo v1.DiskIoStats `json:"diskio,omitempty"`
|
||||
// Memory statistics
|
||||
HasMemory bool `json:"has_memory"`
|
||||
Memory v1.MemoryStats `json:"memory,omitempty"`
|
||||
// Network statistics
|
||||
HasNetwork bool `json:"has_network"`
|
||||
Network []v1.NetworkStats `json:"network,omitempty"`
|
||||
// Filesystem statistics
|
||||
HasFilesystem bool `json:"has_filesystem"`
|
||||
Filesystem []v1.FsStats `json:"filesystem,omitempty"`
|
||||
// Task load statistics
|
||||
HasLoad bool `json:"has_load"`
|
||||
Load v1.LoadStats `json:"load_stats,omitempty"`
|
||||
}
|
||||
|
||||
type Percentiles struct {
|
||||
// Indicates whether the stats are present or not.
|
||||
// If true, values below do not have any data.
|
||||
@ -114,3 +141,12 @@ type FsInfo struct {
|
||||
// Labels associated with this filesystem.
|
||||
Labels []string `json:"labels"`
|
||||
}
|
||||
|
||||
type StatsRequest struct {
|
||||
// Type of container identifier specified - "name", "dockerid", dockeralias"
|
||||
IdType string `json:"type"`
|
||||
// Number of stats to return
|
||||
Count int `json:"count"`
|
||||
// Whether to include stats for child subcontainers.
|
||||
Recursive bool `json:"recursive"`
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user