diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go b/Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go index bfdbeb2cfbac2..3d850be694327 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go @@ -244,6 +244,10 @@ func libcontainerConfigToContainerSpec(config *libcontainerconfigs.Config, mi *i spec.Memory.Limit = math.MaxUint64 spec.Memory.SwapLimit = math.MaxUint64 + // wsj add + spec.HasBoncMetrics = true + spec.Bonc.Threads = 0 + if config.Cgroups.Resources != nil { if config.Cgroups.Resources.Memory > 0 { spec.Memory.Limit = uint64(config.Cgroups.Resources.Memory) @@ -301,6 +305,24 @@ func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) { return spec, err } + +func (self *dockerContainerHandler) getBoncStats(stats *info.ContainerStats) error { + if self.ignoreMetrics.Has(container.BoncMetrics) { + return nil + } + if self.pid == 0 { + return nil + } + sum, sSum, err := containerlibcontainer.GetThreads(self.rootFs, self.pid) + // glog.Errorf(" [ test ] sum: %d; sSum: %d; err: %v.", sum, sSum, err) + if err != nil { + return err + } + stats.BoncMetrics.Threads = uint32(sum) + stats.BoncMetrics.Sockets = uint32(sSum) + return nil +} + func (self *dockerContainerHandler) getFsStats(stats *info.ContainerStats) error { if self.ignoreMetrics.Has(container.DiskUsageMetrics) { return nil @@ -361,7 +383,12 @@ func (self *dockerContainerHandler) GetStats() (*info.ContainerStats, error) { if err != nil { return stats, err } - + // Get bonc stats. + err = self.getBoncStats(stats) + if err != nil { + return stats, err + } + // glog.Errorf(" [ test ] thread: %d; self.RootFs: %s; self.pid: %v.", stats.BoncMetrics.Threads, self.rootFs, self.pid) return stats, nil } diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/container/factory.go b/Godeps/_workspace/src/github.com/google/cadvisor/container/factory.go index 140e728938607..93a626da995f0 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/container/factory.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/container/factory.go @@ -47,6 +47,7 @@ const ( NetworkUsageMetrics MetricKind = "network" NetworkTcpUsageMetrics MetricKind = "tcp" AppMetrics MetricKind = "app" + BoncMetrics MetricKind = "bonc" ) func (mk MetricKind) String() string { diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/helpers.go b/Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/helpers.go index bcf265866aa94..cdfa1253982fb 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/helpers.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/helpers.go @@ -23,7 +23,7 @@ import ( "strconv" "strings" "time" - + "sort" "github.com/google/cadvisor/container" info "github.com/google/cadvisor/info/v1" @@ -447,3 +447,111 @@ func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStat } return ret } + +// thread +type Process struct { + Pid string + Command string + Arguments string + Started time.Time +} + +type byModTime []os.FileInfo + +func (bmt byModTime) Len() int { return len(bmt) } +func (bmt byModTime) Swap(i, j int) { bmt[i], bmt[j] = bmt[j], bmt[i] } +func (bmt byModTime) Less(i, j int) bool { + // If the creation times are identical, sort by filename (pid) instead. + if bmt[i].ModTime() == bmt[j].ModTime() { + return sort.StringsAreSorted([]string{bmt[i].Name(), bmt[j].Name()}) + } + return bmt[i].ModTime().UnixNano() < bmt[j].ModTime().UnixNano() +} + +func GetSocket(spath, pid string) (int, error) { + + fName := path.Join(spath, pid, "/fd") + files, err := ioutil.ReadDir(fName) + if err != nil { + return 0, nil + } + var sum int = 0 + var mSock map[string]string = make(map[string]string) + + sort.Sort(byModTime(files)) + for _, f := range files { + // name, err := os.Readlink("/proc/" + pid + "/fd/" + f.Name()) + name, err := os.Readlink(fName + "/" + f.Name()) + //glog.Errorf("name: %s;fileName: %s; path: %s.", name, f.Name(), fName + "/" + f.Name()) + if strings.Contains(name, "socket:[") && err == nil { + iNode := getInode(name) + if _, ok := mSock[iNode]; ok == false { + mSock[iNode] = "" + sum += 1 + } + } + } + return sum, nil +} + +func getThreadByPth(rootFs, pid string) (int, error) { + fName := path.Join(rootFs, pid, "/status") + info, err := ioutil.ReadFile(fName) + if err != nil { + return 0, err + } + + tmp := strings.Split(string(info), "\n") + for _, v := range tmp { + if strings.Contains(v, "Threads:") { + th := strings.Split(v, "Threads:") + if len(th) == 2 { + num := strings.Trim(th[1], "\t") + return strconv.Atoi(num) + } + } + } + return 0, nil +} + +func GetThreads(rootFs string, pid int) (int, int, error){ + fName := path.Join(rootFs, "proc", strconv.Itoa(pid), "root/proc") + glog.Errorf("GetThreads: fName: %s; rootFs: %s; pid: %d.", fName, rootFs, pid) + files, err := ioutil.ReadDir(fName) + if err != nil { + return 0, 0, err + } + sort.Sort(byModTime(files)) + var pidFiles []os.FileInfo + for _, f := range files { + if _, err := strconv.Atoi(f.Name()); err == nil && f.IsDir() { + pidFiles = append(pidFiles, f) + } + } + sum, sSum := 0, 0 + for _, pidFile := range pidFiles { + num, err := getThreadByPth(fName, pidFile.Name()) + if err != nil { + return 0, 0, err + //glog.Errorf("pid: %s; err: %v.", pidFile.Name(), err) + }else{ + //glog.Errorf("pid: %s; thread: %d", pidFile.Name(), num) + sum += num + } + if sNum, err := GetSocket(fName, pidFile.Name()); err != nil { + return 0, 0, err + }else{ + sSum += sNum + } + + } + glog.Errorf("there are thread: %d; socket num: %d.", sum, sSum) + return sum, sSum, nil +} + +func getInode(name string) string { + // socket:[22744] + tmp := strings.Replace(name, "socket:[", "", -1) + tmp = strings.Replace(tmp, "]", "", -1) + return tmp +} diff --git a/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go b/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go index 6e7e65897560c..43229e32fa528 100644 --- a/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go +++ b/Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go @@ -41,6 +41,11 @@ type MemorySpec struct { SwapLimit uint64 `json:"swap_limit,omitempty"` } +// wsj add +type BoncSpec struct { + Threads uint32 `json:"threads, omitempty"` +} + type ContainerSpec struct { // Time at which the container was created. CreationTime time.Time `json:"creation_time,omitempty"` @@ -66,6 +71,10 @@ type ContainerSpec struct { HasCustomMetrics bool `json:"has_custom_metrics"` CustomMetrics []MetricSpec `json:"custom_metrics,omitempty"` + // wsj add + HasBoncMetrics bool `json:"has_bonc_metrics"` + Bonc BoncSpec `json:"bonc,omitempty"` + // Image name used for this container. Image string `json:"image,omitempty"` } @@ -361,6 +370,12 @@ type InterfaceStats struct { TxDropped uint64 `json:"tx_dropped"` } +// wsj add +type BoncStats struct { + Threads uint32 `json:"threads,omitempty"` + Sockets uint32 `json:"sockets, omitempty"` +} + type NetworkStats struct { InterfaceStats `json:",inline"` Interfaces []InterfaceStats `json:"interfaces,omitempty"` @@ -489,6 +504,8 @@ type ContainerStats struct { //Custom metrics from all collectors CustomMetrics map[string][]MetricVal `json:"custom_metrics,omitempty"` + //Bonc metrics from all collectors + BoncMetrics BoncStats `json:"bonc_stats,omitempty"` } func timeEq(t1, t2 time.Time, tolerance time.Duration) bool {