mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
Merge pull request #7897 from vmarmol/cadvisor
Update cAdvisor dependency.
This commit is contained in:
commit
5f6d54b36b
78
Godeps/Godeps.json
generated
78
Godeps/Godeps.json
generated
@ -19,11 +19,6 @@
|
|||||||
"Comment": "null-12",
|
"Comment": "null-12",
|
||||||
"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
|
"Rev": "7dda39b2e7d5e265014674c5af696ba4186679e9"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"ImportPath": "code.google.com/p/go.exp/inotify",
|
|
||||||
"Comment": "null-75",
|
|
||||||
"Rev": "bd8df7009305d6ada223ea3c95b94c0f38bfa119"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"ImportPath": "code.google.com/p/google-api-go-client/compute/v1",
|
"ImportPath": "code.google.com/p/google-api-go-client/compute/v1",
|
||||||
"Comment": "release-96",
|
"Comment": "release-96",
|
||||||
@ -206,83 +201,88 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/api",
|
"ImportPath": "github.com/google/cadvisor/api",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "github.com/google/cadvisor/collector",
|
||||||
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/container",
|
"ImportPath": "github.com/google/cadvisor/container",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/events",
|
"ImportPath": "github.com/google/cadvisor/events",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/fs",
|
"ImportPath": "github.com/google/cadvisor/fs",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/healthz",
|
"ImportPath": "github.com/google/cadvisor/healthz",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/http",
|
"ImportPath": "github.com/google/cadvisor/http",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/info/v1",
|
"ImportPath": "github.com/google/cadvisor/info/v1",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/info/v2",
|
"ImportPath": "github.com/google/cadvisor/info/v2",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/manager",
|
"ImportPath": "github.com/google/cadvisor/manager",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/metrics",
|
"ImportPath": "github.com/google/cadvisor/metrics",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/pages",
|
"ImportPath": "github.com/google/cadvisor/pages",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/storage",
|
"ImportPath": "github.com/google/cadvisor/storage",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/summary",
|
"ImportPath": "github.com/google/cadvisor/summary",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/utils",
|
"ImportPath": "github.com/google/cadvisor/utils",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/validate",
|
"ImportPath": "github.com/google/cadvisor/validate",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/cadvisor/version",
|
"ImportPath": "github.com/google/cadvisor/version",
|
||||||
"Comment": "0.12.0-21-g3166552",
|
"Comment": "0.13.0-22-ge3aa15a",
|
||||||
"Rev": "3166552cc4481e48dc1002e000d7e4ae8d5b9850"
|
"Rev": "e3aa15a3bbee5367532ac56aa55be41441c55356"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/google/gofuzz",
|
"ImportPath": "github.com/google/gofuzz",
|
||||||
@ -429,6 +429,10 @@
|
|||||||
"ImportPath": "golang.org/x/crypto/ssh",
|
"ImportPath": "golang.org/x/crypto/ssh",
|
||||||
"Rev": "c84e1f8e3a7e322d497cd16c0e8a13c7e127baf3"
|
"Rev": "c84e1f8e3a7e322d497cd16c0e8a13c7e127baf3"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"ImportPath": "golang.org/x/exp/inotify",
|
||||||
|
"Rev": "d00e13ec443927751b2bd49e97dea7bf3b6a6487"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "golang.org/x/net/context",
|
"ImportPath": "golang.org/x/net/context",
|
||||||
"Rev": "cbcac7bb8415db9b6cb4d1ebab1dc9afbd688b97"
|
"Rev": "cbcac7bb8415db9b6cb4d1ebab1dc9afbd688b97"
|
||||||
|
29
Godeps/_workspace/src/github.com/google/cadvisor/api/handler.go
generated
vendored
29
Godeps/_workspace/src/github.com/google/cadvisor/api/handler.go
generated
vendored
@ -199,29 +199,28 @@ func getEventRequest(r *http.Request) (*events.Request, bool, error) {
|
|||||||
query.IncludeSubcontainers = newBool
|
query.IncludeSubcontainers = newBool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if val, ok := urlMap["oom_events"]; ok {
|
eventTypes := map[string]info.EventType{
|
||||||
|
"oom_events": info.EventOom,
|
||||||
|
"oom_kill_events": info.EventOomKill,
|
||||||
|
"creation_events": info.EventContainerCreation,
|
||||||
|
"deletion_events": info.EventContainerDeletion,
|
||||||
|
}
|
||||||
|
allEventTypes := false
|
||||||
|
if val, ok := urlMap["all_events"]; ok {
|
||||||
newBool, err := strconv.ParseBool(val[0])
|
newBool, err := strconv.ParseBool(val[0])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
query.EventType[info.EventOom] = newBool
|
allEventTypes = newBool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if val, ok := urlMap["oom_kill_events"]; ok {
|
for opt, eventType := range eventTypes {
|
||||||
|
if allEventTypes {
|
||||||
|
query.EventType[eventType] = true
|
||||||
|
} else if val, ok := urlMap[opt]; ok {
|
||||||
newBool, err := strconv.ParseBool(val[0])
|
newBool, err := strconv.ParseBool(val[0])
|
||||||
if err == nil {
|
if err == nil {
|
||||||
query.EventType[info.EventOomKill] = newBool
|
query.EventType[eventType] = newBool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if val, ok := urlMap["creation_events"]; ok {
|
|
||||||
newBool, err := strconv.ParseBool(val[0])
|
|
||||||
if err == nil {
|
|
||||||
query.EventType[info.EventContainerCreation] = newBool
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if val, ok := urlMap["deletion_events"]; ok {
|
|
||||||
newBool, err := strconv.ParseBool(val[0])
|
|
||||||
if err == nil {
|
|
||||||
query.EventType[info.EventContainerDeletion] = newBool
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if val, ok := urlMap["max_events"]; ok {
|
if val, ok := urlMap["max_events"]; ok {
|
||||||
newInt, err := strconv.Atoi(val[0])
|
newInt, err := strconv.Atoi(val[0])
|
||||||
|
83
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager.go
generated
vendored
Normal file
83
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type collectorManager struct {
|
||||||
|
collectors []*collectorData
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ CollectorManager = &collectorManager{}
|
||||||
|
|
||||||
|
type collectorData struct {
|
||||||
|
collector Collector
|
||||||
|
nextCollectionTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns a new CollectorManager that is thread-compatible.
|
||||||
|
func NewCollectorManager() (CollectorManager, error) {
|
||||||
|
return &collectorManager{
|
||||||
|
collectors: []*collectorData{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cm *collectorManager) RegisterCollector(collector Collector) error {
|
||||||
|
cm.collectors = append(cm.collectors, &collectorData{
|
||||||
|
collector: collector,
|
||||||
|
nextCollectionTime: time.Now(),
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cm *collectorManager) Collect() (time.Time, error) {
|
||||||
|
var errors []error
|
||||||
|
|
||||||
|
// Collect from all collectors that are ready.
|
||||||
|
var next time.Time
|
||||||
|
for _, c := range cm.collectors {
|
||||||
|
if c.nextCollectionTime.Before(time.Now()) {
|
||||||
|
nextCollection, err := c.collector.Collect()
|
||||||
|
if err != nil {
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
c.nextCollectionTime = nextCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep track of the next collector that will be ready.
|
||||||
|
if next.IsZero() || next.After(c.nextCollectionTime) {
|
||||||
|
next = c.nextCollectionTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return next, compileErrors(errors)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make an error slice into a single error.
|
||||||
|
func compileErrors(errors []error) error {
|
||||||
|
if len(errors) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
res := make([]string, len(errors))
|
||||||
|
for i := range errors {
|
||||||
|
res[i] = fmt.Sprintf("Error %d: %v", i, errors[i].Error())
|
||||||
|
}
|
||||||
|
return fmt.Errorf("%s", strings.Join(res, ","))
|
||||||
|
}
|
70
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager_test.go
generated
vendored
Normal file
70
Godeps/_workspace/src/github.com/google/cadvisor/collector/collector_manager_test.go
generated
vendored
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeCollector struct {
|
||||||
|
nextCollectionTime time.Time
|
||||||
|
err error
|
||||||
|
collectedFrom int
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *fakeCollector) Collect() (time.Time, error) {
|
||||||
|
fc.collectedFrom++
|
||||||
|
return fc.nextCollectionTime, fc.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *fakeCollector) Name() string {
|
||||||
|
return "fake-collector"
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCollect(t *testing.T) {
|
||||||
|
cm := &collectorManager{}
|
||||||
|
|
||||||
|
firstTime := time.Now().Add(-time.Hour)
|
||||||
|
secondTime := time.Now().Add(time.Hour)
|
||||||
|
f1 := &fakeCollector{
|
||||||
|
nextCollectionTime: firstTime,
|
||||||
|
}
|
||||||
|
f2 := &fakeCollector{
|
||||||
|
nextCollectionTime: secondTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
assert := assert.New(t)
|
||||||
|
assert.NoError(cm.RegisterCollector(f1))
|
||||||
|
assert.NoError(cm.RegisterCollector(f2))
|
||||||
|
|
||||||
|
// First collection, everyone gets collected from.
|
||||||
|
nextTime, err := cm.Collect()
|
||||||
|
assert.Equal(firstTime, nextTime)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(1, f1.collectedFrom)
|
||||||
|
assert.Equal(1, f2.collectedFrom)
|
||||||
|
|
||||||
|
f1.nextCollectionTime = time.Now().Add(2 * time.Hour)
|
||||||
|
|
||||||
|
// Second collection, only the one that is ready gets collected from.
|
||||||
|
nextTime, err = cm.Collect()
|
||||||
|
assert.Equal(secondTime, nextTime)
|
||||||
|
assert.NoError(err)
|
||||||
|
assert.Equal(2, f1.collectedFrom)
|
||||||
|
assert.Equal(1, f2.collectedFrom)
|
||||||
|
}
|
31
Godeps/_workspace/src/github.com/google/cadvisor/collector/fakes.go
generated
vendored
Normal file
31
Godeps/_workspace/src/github.com/google/cadvisor/collector/fakes.go
generated
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FakeCollectorManager struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fkm *FakeCollectorManager) RegisterCollector(collector Collector) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fkm *FakeCollectorManager) Collect() (time.Time, error) {
|
||||||
|
var zero time.Time
|
||||||
|
return zero, nil
|
||||||
|
}
|
45
Godeps/_workspace/src/github.com/google/cadvisor/collector/types.go
generated
vendored
Normal file
45
Godeps/_workspace/src/github.com/google/cadvisor/collector/types.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2015 Google Inc. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TODO(vmarmol): Export to a custom metrics type when that is available.
|
||||||
|
|
||||||
|
// Metric collector.
|
||||||
|
type Collector interface {
|
||||||
|
// Collect metrics from this collector.
|
||||||
|
// Returns the next time this collector should be collected from.
|
||||||
|
// Next collection time is always returned, even when an error occurs.
|
||||||
|
// A collection time of zero means no more collection.
|
||||||
|
Collect() (time.Time, error)
|
||||||
|
|
||||||
|
// Name of this collector.
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manages and runs collectors.
|
||||||
|
type CollectorManager interface {
|
||||||
|
// Register a collector.
|
||||||
|
RegisterCollector(collector Collector) error
|
||||||
|
|
||||||
|
// Collect from collectors that are ready and return the next time
|
||||||
|
// at which a collector will be ready to collect from.
|
||||||
|
// Next collection time is always returned, even when an error occurs.
|
||||||
|
// A collection time of zero means no more collection.
|
||||||
|
Collect() (time.Time, error)
|
||||||
|
}
|
8
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/factory.go
generated
vendored
8
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/factory.go
generated
vendored
@ -134,17 +134,19 @@ func FullContainerName(dockerId string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Docker handles all containers under /docker
|
// Docker handles all containers under /docker
|
||||||
func (self *dockerFactory) CanHandle(name string) (bool, error) {
|
func (self *dockerFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
|
// docker factory accepts all containers it can handle.
|
||||||
|
canAccept := true
|
||||||
// Check if the container is known to docker and it is active.
|
// Check if the container is known to docker and it is active.
|
||||||
id := ContainerNameToDockerId(name)
|
id := ContainerNameToDockerId(name)
|
||||||
|
|
||||||
// We assume that if Inspect fails then the container is not known to docker.
|
// We assume that if Inspect fails then the container is not known to docker.
|
||||||
ctnr, err := self.client.InspectContainer(id)
|
ctnr, err := self.client.InspectContainer(id)
|
||||||
if err != nil || !ctnr.State.Running {
|
if err != nil || !ctnr.State.Running {
|
||||||
return false, fmt.Errorf("error inspecting container: %v", err)
|
return false, canAccept, fmt.Errorf("error inspecting container: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, nil
|
return true, canAccept, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseDockerVersion(full_version_string string) ([]int, error) {
|
func parseDockerVersion(full_version_string string) ([]int, error) {
|
||||||
|
5
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go
generated
vendored
5
Godeps/_workspace/src/github.com/google/cadvisor/container/docker/handler.go
generated
vendored
@ -68,6 +68,9 @@ type dockerContainerHandler struct {
|
|||||||
|
|
||||||
// Time at which this container was created.
|
// Time at which this container was created.
|
||||||
creationTime time.Time
|
creationTime time.Time
|
||||||
|
|
||||||
|
// Metadata labels associated with the container.
|
||||||
|
labels map[string]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDockerContainerHandler(
|
func newDockerContainerHandler(
|
||||||
@ -115,6 +118,7 @@ func newDockerContainerHandler(
|
|||||||
// Add the name and bare ID as aliases of the container.
|
// Add the name and bare ID as aliases of the container.
|
||||||
handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"))
|
handler.aliases = append(handler.aliases, strings.TrimPrefix(ctnr.Name, "/"))
|
||||||
handler.aliases = append(handler.aliases, id)
|
handler.aliases = append(handler.aliases, id)
|
||||||
|
handler.labels = ctnr.Config.Labels
|
||||||
|
|
||||||
return handler, nil
|
return handler, nil
|
||||||
}
|
}
|
||||||
@ -184,6 +188,7 @@ func (self *dockerContainerHandler) GetSpec() (info.ContainerSpec, error) {
|
|||||||
if self.usesAufsDriver {
|
if self.usesAufsDriver {
|
||||||
spec.HasFilesystem = true
|
spec.HasFilesystem = true
|
||||||
}
|
}
|
||||||
|
spec.Labels = self.labels
|
||||||
|
|
||||||
return spec, err
|
return spec, err
|
||||||
}
|
}
|
||||||
|
23
Godeps/_workspace/src/github.com/google/cadvisor/container/factory.go
generated
vendored
23
Godeps/_workspace/src/github.com/google/cadvisor/container/factory.go
generated
vendored
@ -22,11 +22,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ContainerHandlerFactory interface {
|
type ContainerHandlerFactory interface {
|
||||||
// Create a new ContainerHandler using this factory. CanHandle() must have returned true.
|
// Create a new ContainerHandler using this factory. CanHandleAndAccept() must have returned true.
|
||||||
NewContainerHandler(name string) (ContainerHandler, error)
|
NewContainerHandler(name string) (c ContainerHandler, err error)
|
||||||
|
|
||||||
// Returns whether this factory can handle the specified container.
|
// Returns whether this factory can handle and accept the specified container.
|
||||||
CanHandle(name string) (bool, error)
|
CanHandleAndAccept(name string) (handle bool, accept bool, err error)
|
||||||
|
|
||||||
// Name of the factory.
|
// Name of the factory.
|
||||||
String() string
|
String() string
|
||||||
@ -57,25 +57,30 @@ func HasFactories() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new ContainerHandler for the specified container.
|
// Create a new ContainerHandler for the specified container.
|
||||||
func NewContainerHandler(name string) (ContainerHandler, error) {
|
func NewContainerHandler(name string) (ContainerHandler, bool, error) {
|
||||||
factoriesLock.RLock()
|
factoriesLock.RLock()
|
||||||
defer factoriesLock.RUnlock()
|
defer factoriesLock.RUnlock()
|
||||||
|
|
||||||
// Create the ContainerHandler with the first factory that supports it.
|
// Create the ContainerHandler with the first factory that supports it.
|
||||||
for _, factory := range factories {
|
for _, factory := range factories {
|
||||||
canHandle, err := factory.CanHandle(name)
|
canHandle, canAccept, err := factory.CanHandleAndAccept(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(4).Infof("Error trying to work out if we can hande %s: %v", name, err)
|
glog.V(4).Infof("Error trying to work out if we can handle %s: %v", name, err)
|
||||||
}
|
}
|
||||||
if canHandle {
|
if canHandle {
|
||||||
|
if !canAccept {
|
||||||
|
glog.V(3).Infof("Factory %q can handle container %q, but ignoring.", factory, name)
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
glog.V(3).Infof("Using factory %q for container %q", factory, name)
|
glog.V(3).Infof("Using factory %q for container %q", factory, name)
|
||||||
return factory.NewContainerHandler(name)
|
handle, err := factory.NewContainerHandler(name)
|
||||||
|
return handle, canAccept, err
|
||||||
} else {
|
} else {
|
||||||
glog.V(4).Infof("Factory %q was unable to handle container %q", factory, name)
|
glog.V(4).Infof("Factory %q was unable to handle container %q", factory, name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf("no known factory can handle creation of container")
|
return nil, false, fmt.Errorf("no known factory can handle creation of container")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the known factories.
|
// Clear the known factories.
|
||||||
|
42
Godeps/_workspace/src/github.com/google/cadvisor/container/factory_test.go
generated
vendored
42
Godeps/_workspace/src/github.com/google/cadvisor/container/factory_test.go
generated
vendored
@ -24,14 +24,15 @@ type mockContainerHandlerFactory struct {
|
|||||||
mock.Mock
|
mock.Mock
|
||||||
Name string
|
Name string
|
||||||
CanHandleValue bool
|
CanHandleValue bool
|
||||||
|
CanAcceptValue bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandlerFactory) String() string {
|
func (self *mockContainerHandlerFactory) String() string {
|
||||||
return self.Name
|
return self.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandlerFactory) CanHandle(name string) (bool, error) {
|
func (self *mockContainerHandlerFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
return self.CanHandleValue, nil
|
return self.CanHandleValue, self.CanAcceptValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *mockContainerHandlerFactory) NewContainerHandler(name string) (ContainerHandler, error) {
|
func (self *mockContainerHandlerFactory) NewContainerHandler(name string) (ContainerHandler, error) {
|
||||||
@ -50,6 +51,7 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) {
|
|||||||
allwaysYes := &mockContainerHandlerFactory{
|
allwaysYes := &mockContainerHandlerFactory{
|
||||||
Name: "yes",
|
Name: "yes",
|
||||||
CanHandleValue: true,
|
CanHandleValue: true,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysYes)
|
RegisterContainerHandlerFactory(allwaysYes)
|
||||||
|
|
||||||
@ -60,7 +62,7 @@ func TestNewContainerHandler_FirstMatches(t *testing.T) {
|
|||||||
}
|
}
|
||||||
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
||||||
|
|
||||||
cont, err := NewContainerHandler(testContainerName)
|
cont, _, err := NewContainerHandler(testContainerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -76,11 +78,13 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) {
|
|||||||
allwaysNo := &mockContainerHandlerFactory{
|
allwaysNo := &mockContainerHandlerFactory{
|
||||||
Name: "no",
|
Name: "no",
|
||||||
CanHandleValue: false,
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysNo)
|
RegisterContainerHandlerFactory(allwaysNo)
|
||||||
allwaysYes := &mockContainerHandlerFactory{
|
allwaysYes := &mockContainerHandlerFactory{
|
||||||
Name: "yes",
|
Name: "yes",
|
||||||
CanHandleValue: true,
|
CanHandleValue: true,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysYes)
|
RegisterContainerHandlerFactory(allwaysYes)
|
||||||
|
|
||||||
@ -91,7 +95,7 @@ func TestNewContainerHandler_SecondMatches(t *testing.T) {
|
|||||||
}
|
}
|
||||||
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
allwaysYes.On("NewContainerHandler", testContainerName).Return(mockContainer, nil)
|
||||||
|
|
||||||
cont, err := NewContainerHandler(testContainerName)
|
cont, _, err := NewContainerHandler(testContainerName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -107,16 +111,44 @@ func TestNewContainerHandler_NoneMatch(t *testing.T) {
|
|||||||
allwaysNo1 := &mockContainerHandlerFactory{
|
allwaysNo1 := &mockContainerHandlerFactory{
|
||||||
Name: "no",
|
Name: "no",
|
||||||
CanHandleValue: false,
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysNo1)
|
RegisterContainerHandlerFactory(allwaysNo1)
|
||||||
allwaysNo2 := &mockContainerHandlerFactory{
|
allwaysNo2 := &mockContainerHandlerFactory{
|
||||||
Name: "no",
|
Name: "no",
|
||||||
CanHandleValue: false,
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
}
|
}
|
||||||
RegisterContainerHandlerFactory(allwaysNo2)
|
RegisterContainerHandlerFactory(allwaysNo2)
|
||||||
|
|
||||||
_, err := NewContainerHandler(testContainerName)
|
_, _, err := NewContainerHandler(testContainerName)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Error("Expected NewContainerHandler to fail")
|
t.Error("Expected NewContainerHandler to fail")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewContainerHandler_Accept(t *testing.T) {
|
||||||
|
ClearContainerHandlerFactories()
|
||||||
|
|
||||||
|
// Register handler that can handle the container, but can't accept it.
|
||||||
|
cannotHandle := &mockContainerHandlerFactory{
|
||||||
|
Name: "no",
|
||||||
|
CanHandleValue: false,
|
||||||
|
CanAcceptValue: true,
|
||||||
|
}
|
||||||
|
RegisterContainerHandlerFactory(cannotHandle)
|
||||||
|
cannotAccept := &mockContainerHandlerFactory{
|
||||||
|
Name: "no",
|
||||||
|
CanHandleValue: true,
|
||||||
|
CanAcceptValue: false,
|
||||||
|
}
|
||||||
|
RegisterContainerHandlerFactory(cannotAccept)
|
||||||
|
|
||||||
|
_, accept, err := NewContainerHandler(testContainerName)
|
||||||
|
if err != nil {
|
||||||
|
t.Error("Expected NewContainerHandler to succeed")
|
||||||
|
}
|
||||||
|
if accept == true {
|
||||||
|
t.Error("Expected NewContainerHandler to ignore the container.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
69
Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/helpers.go
generated
vendored
69
Godeps/_workspace/src/github.com/google/cadvisor/container/libcontainer/helpers.go
generated
vendored
@ -100,14 +100,34 @@ func DockerStateDir(dockerRoot string) string {
|
|||||||
return path.Join(dockerRoot, "containers")
|
return path.Join(dockerRoot, "containers")
|
||||||
}
|
}
|
||||||
|
|
||||||
func DiskStatsCopy(blkio_stats []cgroups.BlkioStatEntry) (stat []info.PerDiskStats) {
|
func DiskStatsCopy0(major, minor uint64) *info.PerDiskStats {
|
||||||
if len(blkio_stats) == 0 {
|
disk := info.PerDiskStats{
|
||||||
return
|
Major: major,
|
||||||
|
Minor: minor,
|
||||||
}
|
}
|
||||||
|
disk.Stats = make(map[string]uint64)
|
||||||
|
return &disk
|
||||||
|
}
|
||||||
|
|
||||||
type DiskKey struct {
|
type DiskKey struct {
|
||||||
Major uint64
|
Major uint64
|
||||||
Minor uint64
|
Minor uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DiskStatsCopy1(disk_stat map[DiskKey]*info.PerDiskStats) []info.PerDiskStats {
|
||||||
|
i := 0
|
||||||
|
stat := make([]info.PerDiskStats, len(disk_stat))
|
||||||
|
for _, disk := range disk_stat {
|
||||||
|
stat[i] = *disk
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return stat
|
||||||
|
}
|
||||||
|
|
||||||
|
func DiskStatsCopy(blkio_stats []cgroups.BlkioStatEntry) (stat []info.PerDiskStats) {
|
||||||
|
if len(blkio_stats) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
disk_stat := make(map[DiskKey]*info.PerDiskStats)
|
disk_stat := make(map[DiskKey]*info.PerDiskStats)
|
||||||
for i := range blkio_stats {
|
for i := range blkio_stats {
|
||||||
major := blkio_stats[i].Major
|
major := blkio_stats[i].Major
|
||||||
@ -118,12 +138,7 @@ func DiskStatsCopy(blkio_stats []cgroups.BlkioStatEntry) (stat []info.PerDiskSta
|
|||||||
}
|
}
|
||||||
diskp, ok := disk_stat[disk_key]
|
diskp, ok := disk_stat[disk_key]
|
||||||
if !ok {
|
if !ok {
|
||||||
disk := info.PerDiskStats{
|
diskp = DiskStatsCopy0(major, minor)
|
||||||
Major: major,
|
|
||||||
Minor: minor,
|
|
||||||
}
|
|
||||||
disk.Stats = make(map[string]uint64)
|
|
||||||
diskp = &disk
|
|
||||||
disk_stat[disk_key] = diskp
|
disk_stat[disk_key] = diskp
|
||||||
}
|
}
|
||||||
op := blkio_stats[i].Op
|
op := blkio_stats[i].Op
|
||||||
@ -132,22 +147,11 @@ func DiskStatsCopy(blkio_stats []cgroups.BlkioStatEntry) (stat []info.PerDiskSta
|
|||||||
}
|
}
|
||||||
diskp.Stats[op] = blkio_stats[i].Value
|
diskp.Stats[op] = blkio_stats[i].Value
|
||||||
}
|
}
|
||||||
i := 0
|
return DiskStatsCopy1(disk_stat)
|
||||||
stat = make([]info.PerDiskStats, len(disk_stat))
|
|
||||||
for _, disk := range disk_stat {
|
|
||||||
stat[i] = *disk
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert libcontainer stats to info.ContainerStats.
|
// Convert libcontainer stats to info.ContainerStats.
|
||||||
func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStats {
|
func toContainerStats0(s *cgroups.Stats, ret *info.ContainerStats) {
|
||||||
s := libcontainerStats.CgroupStats
|
|
||||||
ret := new(info.ContainerStats)
|
|
||||||
ret.Timestamp = time.Now()
|
|
||||||
|
|
||||||
if s != nil {
|
|
||||||
ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode
|
ret.Cpu.Usage.User = s.CpuStats.CpuUsage.UsageInUsermode
|
||||||
ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode
|
ret.Cpu.Usage.System = s.CpuStats.CpuUsage.UsageInKernelmode
|
||||||
n := len(s.CpuStats.CpuUsage.PercpuUsage)
|
n := len(s.CpuStats.CpuUsage.PercpuUsage)
|
||||||
@ -158,7 +162,9 @@ func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStat
|
|||||||
ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i]
|
ret.Cpu.Usage.PerCpu[i] = s.CpuStats.CpuUsage.PercpuUsage[i]
|
||||||
ret.Cpu.Usage.Total += s.CpuStats.CpuUsage.PercpuUsage[i]
|
ret.Cpu.Usage.Total += s.CpuStats.CpuUsage.PercpuUsage[i]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toContainerStats1(s *cgroups.Stats, ret *info.ContainerStats) {
|
||||||
ret.DiskIo.IoServiceBytes = DiskStatsCopy(s.BlkioStats.IoServiceBytesRecursive)
|
ret.DiskIo.IoServiceBytes = DiskStatsCopy(s.BlkioStats.IoServiceBytesRecursive)
|
||||||
ret.DiskIo.IoServiced = DiskStatsCopy(s.BlkioStats.IoServicedRecursive)
|
ret.DiskIo.IoServiced = DiskStatsCopy(s.BlkioStats.IoServicedRecursive)
|
||||||
ret.DiskIo.IoQueued = DiskStatsCopy(s.BlkioStats.IoQueuedRecursive)
|
ret.DiskIo.IoQueued = DiskStatsCopy(s.BlkioStats.IoQueuedRecursive)
|
||||||
@ -167,7 +173,9 @@ func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStat
|
|||||||
ret.DiskIo.IoWaitTime = DiskStatsCopy(s.BlkioStats.IoWaitTimeRecursive)
|
ret.DiskIo.IoWaitTime = DiskStatsCopy(s.BlkioStats.IoWaitTimeRecursive)
|
||||||
ret.DiskIo.IoMerged = DiskStatsCopy(s.BlkioStats.IoMergedRecursive)
|
ret.DiskIo.IoMerged = DiskStatsCopy(s.BlkioStats.IoMergedRecursive)
|
||||||
ret.DiskIo.IoTime = DiskStatsCopy(s.BlkioStats.IoTimeRecursive)
|
ret.DiskIo.IoTime = DiskStatsCopy(s.BlkioStats.IoTimeRecursive)
|
||||||
|
}
|
||||||
|
|
||||||
|
func toContainerStats2(s *cgroups.Stats, ret *info.ContainerStats) {
|
||||||
ret.Memory.Usage = s.MemoryStats.Usage
|
ret.Memory.Usage = s.MemoryStats.Usage
|
||||||
if v, ok := s.MemoryStats.Stats["pgfault"]; ok {
|
if v, ok := s.MemoryStats.Stats["pgfault"]; ok {
|
||||||
ret.Memory.ContainerData.Pgfault = v
|
ret.Memory.ContainerData.Pgfault = v
|
||||||
@ -184,7 +192,8 @@ func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(libcontainerStats.Interfaces) > 0 {
|
|
||||||
|
func toContainerStats3(libcontainerStats *libcontainer.Stats, ret *info.ContainerStats) {
|
||||||
// TODO(vmarmol): Handle multiple interfaces.
|
// TODO(vmarmol): Handle multiple interfaces.
|
||||||
ret.Network.RxBytes = libcontainerStats.Interfaces[0].RxBytes
|
ret.Network.RxBytes = libcontainerStats.Interfaces[0].RxBytes
|
||||||
ret.Network.RxPackets = libcontainerStats.Interfaces[0].RxPackets
|
ret.Network.RxPackets = libcontainerStats.Interfaces[0].RxPackets
|
||||||
@ -195,5 +204,19 @@ func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStat
|
|||||||
ret.Network.TxErrors = libcontainerStats.Interfaces[0].TxErrors
|
ret.Network.TxErrors = libcontainerStats.Interfaces[0].TxErrors
|
||||||
ret.Network.TxDropped = libcontainerStats.Interfaces[0].TxDropped
|
ret.Network.TxDropped = libcontainerStats.Interfaces[0].TxDropped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toContainerStats(libcontainerStats *libcontainer.Stats) *info.ContainerStats {
|
||||||
|
s := libcontainerStats.CgroupStats
|
||||||
|
ret := new(info.ContainerStats)
|
||||||
|
ret.Timestamp = time.Now()
|
||||||
|
|
||||||
|
if s != nil {
|
||||||
|
toContainerStats0(s, ret)
|
||||||
|
toContainerStats1(s, ret)
|
||||||
|
toContainerStats2(s, ret)
|
||||||
|
}
|
||||||
|
if len(libcontainerStats.Interfaces) > 0 {
|
||||||
|
toContainerStats3(libcontainerStats, ret)
|
||||||
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
10
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/factory.go
generated
vendored
10
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/factory.go
generated
vendored
@ -15,6 +15,7 @@
|
|||||||
package raw
|
package raw
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@ -24,6 +25,8 @@ import (
|
|||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var dockerOnly = flag.Bool("docker_only", false, "Only report docker containers in addition to root stats")
|
||||||
|
|
||||||
type rawFactory struct {
|
type rawFactory struct {
|
||||||
// Factory for machine information.
|
// Factory for machine information.
|
||||||
machineInfoFactory info.MachineInfoFactory
|
machineInfoFactory info.MachineInfoFactory
|
||||||
@ -43,9 +46,10 @@ func (self *rawFactory) NewContainerHandler(name string) (container.ContainerHan
|
|||||||
return newRawContainerHandler(name, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo)
|
return newRawContainerHandler(name, self.cgroupSubsystems, self.machineInfoFactory, self.fsInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The raw factory can handle any container.
|
// The raw factory can handle any container. If --docker_only is set to false, non-docker containers are ignored.
|
||||||
func (self *rawFactory) CanHandle(name string) (bool, error) {
|
func (self *rawFactory) CanHandleAndAccept(name string) (bool, bool, error) {
|
||||||
return true, nil
|
accept := name == "/" || !*dockerOnly
|
||||||
|
return true, accept, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo) error {
|
func Register(machineInfoFactory info.MachineInfoFactory, fsInfo fs.FsInfo) error {
|
||||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/container/raw/handler.go
generated
vendored
@ -24,7 +24,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.google.com/p/go.exp/inotify"
|
|
||||||
"github.com/docker/libcontainer/cgroups"
|
"github.com/docker/libcontainer/cgroups"
|
||||||
cgroup_fs "github.com/docker/libcontainer/cgroups/fs"
|
cgroup_fs "github.com/docker/libcontainer/cgroups/fs"
|
||||||
"github.com/docker/libcontainer/configs"
|
"github.com/docker/libcontainer/configs"
|
||||||
@ -34,6 +33,7 @@ import (
|
|||||||
"github.com/google/cadvisor/fs"
|
"github.com/google/cadvisor/fs"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
"github.com/google/cadvisor/utils"
|
"github.com/google/cadvisor/utils"
|
||||||
|
"golang.org/x/exp/inotify"
|
||||||
)
|
)
|
||||||
|
|
||||||
type rawContainerHandler struct {
|
type rawContainerHandler struct {
|
||||||
|
101
Godeps/_workspace/src/github.com/google/cadvisor/events/handler.go
generated
vendored
101
Godeps/_workspace/src/github.com/google/cadvisor/events/handler.go
generated
vendored
@ -23,20 +23,21 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
|
"github.com/google/cadvisor/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
type EventSlice []*info.Event
|
type byTimestamp []*info.Event
|
||||||
|
|
||||||
// functions necessary to implement the sort interface on the Events struct
|
// functions necessary to implement the sort interface on the Events struct
|
||||||
func (e EventSlice) Len() int {
|
func (e byTimestamp) Len() int {
|
||||||
return len(e)
|
return len(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e EventSlice) Swap(i, j int) {
|
func (e byTimestamp) Swap(i, j int) {
|
||||||
e[i], e[j] = e[j], e[i]
|
e[i], e[j] = e[j], e[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e EventSlice) Less(i, j int) bool {
|
func (e byTimestamp) Less(i, j int) bool {
|
||||||
return e[i].Timestamp.Before(e[j].Timestamp)
|
return e[i].Timestamp.Before(e[j].Timestamp)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ type EventManager interface {
|
|||||||
// On successful registration, an EventChannel object is returned.
|
// On successful registration, an EventChannel object is returned.
|
||||||
WatchEvents(request *Request) (*EventChannel, error)
|
WatchEvents(request *Request) (*EventChannel, error)
|
||||||
// GetEvents() returns all detected events based on the filters specified in request.
|
// GetEvents() returns all detected events based on the filters specified in request.
|
||||||
GetEvents(request *Request) (EventSlice, error)
|
GetEvents(request *Request) ([]*info.Event, error)
|
||||||
// AddEvent allows the caller to add an event to an EventManager
|
// AddEvent allows the caller to add an event to an EventManager
|
||||||
// object
|
// object
|
||||||
AddEvent(e *info.Event) error
|
AddEvent(e *info.Event) error
|
||||||
@ -89,17 +90,18 @@ type EventManager interface {
|
|||||||
|
|
||||||
// events provides an implementation for the EventManager interface.
|
// events provides an implementation for the EventManager interface.
|
||||||
type events struct {
|
type events struct {
|
||||||
// eventList holds the complete set of events found over an
|
// eventStore holds the events by event type.
|
||||||
// EventManager events instantiation.
|
eventStore map[info.EventType]*utils.TimedStore
|
||||||
eventList EventSlice
|
|
||||||
// map of registered watchers keyed by watch id.
|
// map of registered watchers keyed by watch id.
|
||||||
watchers map[int]*watch
|
watchers map[int]*watch
|
||||||
// lock guarding the eventList.
|
// lock guarding the eventStore.
|
||||||
eventsLock sync.RWMutex
|
eventsLock sync.RWMutex
|
||||||
// lock guarding watchers.
|
// lock guarding watchers.
|
||||||
watcherLock sync.RWMutex
|
watcherLock sync.RWMutex
|
||||||
// last allocated watch id.
|
// last allocated watch id.
|
||||||
lastId int
|
lastId int
|
||||||
|
// Event storage policy.
|
||||||
|
storagePolicy StoragePolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
// initialized by a call to WatchEvents(), a watch struct will then be added
|
// initialized by a call to WatchEvents(), a watch struct will then be added
|
||||||
@ -125,11 +127,34 @@ func NewEventChannel(watchId int) *EventChannel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns a pointer to an initialized Events object
|
// Policy specifying how many events to store.
|
||||||
func NewEventManager() *events {
|
// MaxAge is the max duration for which to keep events.
|
||||||
|
// MaxNumEvents is the max number of events to keep (-1 for no limit).
|
||||||
|
type StoragePolicy struct {
|
||||||
|
// Defaults limites, used if a per-event limit is not set.
|
||||||
|
DefaultMaxAge time.Duration
|
||||||
|
DefaultMaxNumEvents int
|
||||||
|
|
||||||
|
// Per-event type limits.
|
||||||
|
PerTypeMaxAge map[info.EventType]time.Duration
|
||||||
|
PerTypeMaxNumEvents map[info.EventType]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func DefaultStoragePolicy() StoragePolicy {
|
||||||
|
return StoragePolicy{
|
||||||
|
DefaultMaxAge: 24 * time.Hour,
|
||||||
|
DefaultMaxNumEvents: 100000,
|
||||||
|
PerTypeMaxAge: make(map[info.EventType]time.Duration),
|
||||||
|
PerTypeMaxNumEvents: make(map[info.EventType]int),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns a pointer to an initialized Events object.
|
||||||
|
func NewEventManager(storagePolicy StoragePolicy) *events {
|
||||||
return &events{
|
return &events{
|
||||||
eventList: make(EventSlice, 0),
|
eventStore: make(map[info.EventType]*utils.TimedStore, 0),
|
||||||
watchers: make(map[int]*watch),
|
watchers: make(map[int]*watch),
|
||||||
|
storagePolicy: storagePolicy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,13 +184,13 @@ func (self *EventChannel) GetWatchId() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sorts and returns up to the last MaxEventsReturned chronological elements
|
// sorts and returns up to the last MaxEventsReturned chronological elements
|
||||||
func getMaxEventsReturned(request *Request, eSlice EventSlice) EventSlice {
|
func getMaxEventsReturned(request *Request, eSlice []*info.Event) []*info.Event {
|
||||||
sort.Sort(eSlice)
|
sort.Sort(byTimestamp(eSlice))
|
||||||
n := request.MaxEventsReturned
|
n := request.MaxEventsReturned
|
||||||
if n >= eSlice.Len() || n <= 0 {
|
if n >= len(eSlice) || n <= 0 {
|
||||||
return eSlice
|
return eSlice
|
||||||
}
|
}
|
||||||
return eSlice[eSlice.Len()-n:]
|
return eSlice[len(eSlice)-n:]
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the request wants all subcontainers, this returns if the request's
|
// If the request wants all subcontainers, this returns if the request's
|
||||||
@ -194,7 +219,7 @@ func checkIfEventSatisfiesRequest(request *Request, event *info.Event) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.EventType[event.EventType] != true {
|
if !request.EventType[event.EventType] {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if request.ContainerName != "" {
|
if request.ContainerName != "" {
|
||||||
@ -203,20 +228,32 @@ func checkIfEventSatisfiesRequest(request *Request, event *info.Event) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// method of Events object that screens Event objects found in the eventList
|
// method of Events object that screens Event objects found in the eventStore
|
||||||
// attribute and if they fit the parameters passed by the Request object,
|
// attribute and if they fit the parameters passed by the Request object,
|
||||||
// adds it to a slice of *Event objects that is returned. If both MaxEventsReturned
|
// adds it to a slice of *Event objects that is returned. If both MaxEventsReturned
|
||||||
// and StartTime/EndTime are specified in the request object, then only
|
// and StartTime/EndTime are specified in the request object, then only
|
||||||
// up to the most recent MaxEventsReturned events in that time range are returned.
|
// up to the most recent MaxEventsReturned events in that time range are returned.
|
||||||
func (self *events) GetEvents(request *Request) (EventSlice, error) {
|
func (self *events) GetEvents(request *Request) ([]*info.Event, error) {
|
||||||
returnEventList := EventSlice{}
|
returnEventList := []*info.Event{}
|
||||||
self.eventsLock.RLock()
|
self.eventsLock.RLock()
|
||||||
defer self.eventsLock.RUnlock()
|
defer self.eventsLock.RUnlock()
|
||||||
for _, e := range self.eventList {
|
for eventType, fetch := range request.EventType {
|
||||||
|
if !fetch {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
evs, ok := self.eventStore[eventType]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
res := evs.InTimeRange(request.StartTime, request.EndTime, request.MaxEventsReturned)
|
||||||
|
for _, in := range res {
|
||||||
|
e := in.(*info.Event)
|
||||||
if checkIfEventSatisfiesRequest(request, e) {
|
if checkIfEventSatisfiesRequest(request, e) {
|
||||||
returnEventList = append(returnEventList, e)
|
returnEventList = append(returnEventList, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
returnEventList = getMaxEventsReturned(request, returnEventList)
|
returnEventList = getMaxEventsReturned(request, returnEventList)
|
||||||
return returnEventList, nil
|
return returnEventList, nil
|
||||||
}
|
}
|
||||||
@ -241,11 +278,23 @@ func (self *events) WatchEvents(request *Request) (*EventChannel, error) {
|
|||||||
return returnEventChannel, nil
|
return returnEventChannel, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// helper function to update the event manager's eventList
|
// helper function to update the event manager's eventStore
|
||||||
func (self *events) updateEventList(e *info.Event) {
|
func (self *events) updateEventStore(e *info.Event) {
|
||||||
self.eventsLock.Lock()
|
self.eventsLock.Lock()
|
||||||
defer self.eventsLock.Unlock()
|
defer self.eventsLock.Unlock()
|
||||||
self.eventList = append(self.eventList, e)
|
if _, ok := self.eventStore[e.EventType]; !ok {
|
||||||
|
maxAge := self.storagePolicy.DefaultMaxAge
|
||||||
|
maxNumEvents := self.storagePolicy.DefaultMaxNumEvents
|
||||||
|
if age, ok := self.storagePolicy.PerTypeMaxAge[e.EventType]; ok {
|
||||||
|
maxAge = age
|
||||||
|
}
|
||||||
|
if numEvents, ok := self.storagePolicy.PerTypeMaxNumEvents[e.EventType]; ok {
|
||||||
|
maxNumEvents = numEvents
|
||||||
|
}
|
||||||
|
|
||||||
|
self.eventStore[e.EventType] = utils.NewTimedStore(maxAge, maxNumEvents)
|
||||||
|
}
|
||||||
|
self.eventStore[e.EventType].Add(e.Timestamp, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *events) findValidWatchers(e *info.Event) []*watch {
|
func (self *events) findValidWatchers(e *info.Event) []*watch {
|
||||||
@ -260,10 +309,10 @@ func (self *events) findValidWatchers(e *info.Event) []*watch {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// method of Events object that adds the argument Event object to the
|
// method of Events object that adds the argument Event object to the
|
||||||
// eventList. It also feeds the event to a set of watch channels
|
// eventStore. It also feeds the event to a set of watch channels
|
||||||
// held by the manager if it satisfies the request keys of the channels
|
// held by the manager if it satisfies the request keys of the channels
|
||||||
func (self *events) AddEvent(e *info.Event) error {
|
func (self *events) AddEvent(e *info.Event) error {
|
||||||
self.updateEventList(e)
|
self.updateEventStore(e)
|
||||||
self.watcherLock.RLock()
|
self.watcherLock.RLock()
|
||||||
defer self.watcherLock.RUnlock()
|
defer self.watcherLock.RUnlock()
|
||||||
watchesToSend := self.findValidWatchers(e)
|
watchesToSend := self.findValidWatchers(e)
|
||||||
|
12
Godeps/_workspace/src/github.com/google/cadvisor/events/handler_test.go
generated
vendored
12
Godeps/_workspace/src/github.com/google/cadvisor/events/handler_test.go
generated
vendored
@ -47,7 +47,7 @@ func initializeScenario(t *testing.T) (*events, *Request, *info.Event, *info.Eve
|
|||||||
fakeEvent := makeEvent(createOldTime(t), "/")
|
fakeEvent := makeEvent(createOldTime(t), "/")
|
||||||
fakeEvent2 := makeEvent(time.Now(), "/")
|
fakeEvent2 := makeEvent(time.Now(), "/")
|
||||||
|
|
||||||
return NewEventManager(), NewRequest(), fakeEvent, fakeEvent2
|
return NewEventManager(DefaultStoragePolicy()), NewRequest(), fakeEvent, fakeEvent2
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkNumberOfEvents(t *testing.T, numEventsExpected int, numEventsReceived int) {
|
func checkNumberOfEvents(t *testing.T, numEventsExpected int, numEventsReceived int) {
|
||||||
@ -150,8 +150,8 @@ func TestAddEventAddsEventsToEventManager(t *testing.T) {
|
|||||||
|
|
||||||
myEventHolder.AddEvent(fakeEvent)
|
myEventHolder.AddEvent(fakeEvent)
|
||||||
|
|
||||||
checkNumberOfEvents(t, 1, myEventHolder.eventList.Len())
|
checkNumberOfEvents(t, 1, len(myEventHolder.eventStore))
|
||||||
ensureProperEventReturned(t, fakeEvent, myEventHolder.eventList[0])
|
ensureProperEventReturned(t, fakeEvent, myEventHolder.eventStore[info.EventOom].Get(0).(*info.Event))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetEventsForOneEvent(t *testing.T) {
|
func TestGetEventsForOneEvent(t *testing.T) {
|
||||||
@ -164,7 +164,7 @@ func TestGetEventsForOneEvent(t *testing.T) {
|
|||||||
|
|
||||||
receivedEvents, err := myEventHolder.GetEvents(myRequest)
|
receivedEvents, err := myEventHolder.GetEvents(myRequest)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
checkNumberOfEvents(t, 1, receivedEvents.Len())
|
checkNumberOfEvents(t, 1, len(receivedEvents))
|
||||||
ensureProperEventReturned(t, fakeEvent2, receivedEvents[0])
|
ensureProperEventReturned(t, fakeEvent2, receivedEvents[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ func TestGetEventsForTimePeriod(t *testing.T) {
|
|||||||
receivedEvents, err := myEventHolder.GetEvents(myRequest)
|
receivedEvents, err := myEventHolder.GetEvents(myRequest)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
checkNumberOfEvents(t, 1, receivedEvents.Len())
|
checkNumberOfEvents(t, 1, len(receivedEvents))
|
||||||
ensureProperEventReturned(t, fakeEvent, receivedEvents[0])
|
ensureProperEventReturned(t, fakeEvent, receivedEvents[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,5 +192,5 @@ func TestGetEventsForNoTypeRequested(t *testing.T) {
|
|||||||
|
|
||||||
receivedEvents, err := myEventHolder.GetEvents(myRequest)
|
receivedEvents, err := myEventHolder.GetEvents(myRequest)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
checkNumberOfEvents(t, 0, receivedEvents.Len())
|
checkNumberOfEvents(t, 0, len(receivedEvents))
|
||||||
}
|
}
|
||||||
|
12
Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go
generated
vendored
12
Godeps/_workspace/src/github.com/google/cadvisor/info/v1/container.go
generated
vendored
@ -43,6 +43,9 @@ type ContainerSpec struct {
|
|||||||
// Time at which the container was created.
|
// Time at which the container was created.
|
||||||
CreationTime time.Time `json:"creation_time,omitempty"`
|
CreationTime time.Time `json:"creation_time,omitempty"`
|
||||||
|
|
||||||
|
// Metadata labels associated with this container.
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
|
||||||
HasCpu bool `json:"has_cpu"`
|
HasCpu bool `json:"has_cpu"`
|
||||||
Cpu CpuSpec `json:"cpu,omitempty"`
|
Cpu CpuSpec `json:"cpu,omitempty"`
|
||||||
|
|
||||||
@ -505,19 +508,10 @@ const (
|
|||||||
|
|
||||||
// Extra information about an event. Only one type will be set.
|
// Extra information about an event. Only one type will be set.
|
||||||
type EventData struct {
|
type EventData struct {
|
||||||
// Information about a container creation event.
|
|
||||||
Created *CreatedEventData `json:"created,omitempty"`
|
|
||||||
|
|
||||||
// Information about an OOM kill event.
|
// Information about an OOM kill event.
|
||||||
OomKill *OomKillEventData `json:"oom,omitempty"`
|
OomKill *OomKillEventData `json:"oom,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Information related to a container creation event.
|
|
||||||
type CreatedEventData struct {
|
|
||||||
// Spec of the container at creation.
|
|
||||||
Spec ContainerSpec `json:"spec"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Information related to an OOM kill instance
|
// Information related to an OOM kill instance
|
||||||
type OomKillEventData struct {
|
type OomKillEventData struct {
|
||||||
// process id of the killed process
|
// process id of the killed process
|
||||||
|
3
Godeps/_workspace/src/github.com/google/cadvisor/info/v2/container.go
generated
vendored
3
Godeps/_workspace/src/github.com/google/cadvisor/info/v2/container.go
generated
vendored
@ -64,6 +64,9 @@ type ContainerSpec struct {
|
|||||||
// An example of a namespace is "docker" for Docker containers.
|
// An example of a namespace is "docker" for Docker containers.
|
||||||
Namespace string `json:"namespace,omitempty"`
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
|
||||||
|
// Metadata labels associated with this container.
|
||||||
|
Labels map[string]string `json:"labels,omitempty"`
|
||||||
|
|
||||||
HasCpu bool `json:"has_cpu"`
|
HasCpu bool `json:"has_cpu"`
|
||||||
Cpu CpuSpec `json:"cpu,omitempty"`
|
Cpu CpuSpec `json:"cpu,omitempty"`
|
||||||
|
|
||||||
|
32
Godeps/_workspace/src/github.com/google/cadvisor/manager/container.go
generated
vendored
32
Godeps/_workspace/src/github.com/google/cadvisor/manager/container.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/docker/docker/pkg/units"
|
"github.com/docker/docker/pkg/units"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"github.com/google/cadvisor/collector"
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
"github.com/google/cadvisor/info/v2"
|
"github.com/google/cadvisor/info/v2"
|
||||||
@ -63,6 +64,9 @@ type containerData struct {
|
|||||||
|
|
||||||
// Tells the container to stop.
|
// Tells the container to stop.
|
||||||
stop chan bool
|
stop chan bool
|
||||||
|
|
||||||
|
// Runs custom metric collectors.
|
||||||
|
collectorManager collector.CollectorManager
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *containerData) Start() error {
|
func (c *containerData) Start() error {
|
||||||
@ -109,7 +113,7 @@ func (c *containerData) DerivedStats() (v2.DerivedStats, error) {
|
|||||||
return c.summaryReader.DerivedStats()
|
return c.summaryReader.DerivedStats()
|
||||||
}
|
}
|
||||||
|
|
||||||
func newContainerData(containerName string, memoryStorage *memory.InMemoryStorage, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool) (*containerData, error) {
|
func newContainerData(containerName string, memoryStorage *memory.InMemoryStorage, handler container.ContainerHandler, loadReader cpuload.CpuLoadReader, logUsage bool, collectorManager collector.CollectorManager) (*containerData, error) {
|
||||||
if memoryStorage == nil {
|
if memoryStorage == nil {
|
||||||
return nil, fmt.Errorf("nil memory storage")
|
return nil, fmt.Errorf("nil memory storage")
|
||||||
}
|
}
|
||||||
@ -129,6 +133,7 @@ func newContainerData(containerName string, memoryStorage *memory.InMemoryStorag
|
|||||||
logUsage: logUsage,
|
logUsage: logUsage,
|
||||||
loadAvg: -1.0, // negative value indicates uninitialized.
|
loadAvg: -1.0, // negative value indicates uninitialized.
|
||||||
stop: make(chan bool, 1),
|
stop: make(chan bool, 1),
|
||||||
|
collectorManager: collectorManager,
|
||||||
}
|
}
|
||||||
cont.info.ContainerReference = ref
|
cont.info.ContainerReference = ref
|
||||||
|
|
||||||
@ -172,6 +177,7 @@ func (self *containerData) nextHousekeeping(lastHousekeeping time.Time) time.Tim
|
|||||||
return lastHousekeeping.Add(self.housekeepingInterval)
|
return lastHousekeeping.Add(self.housekeepingInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(vmarmol): Implement stats collecting as a custom collector.
|
||||||
func (c *containerData) housekeeping() {
|
func (c *containerData) housekeeping() {
|
||||||
// Long housekeeping is either 100ms or half of the housekeeping interval.
|
// Long housekeeping is either 100ms or half of the housekeeping interval.
|
||||||
longHousekeeping := 100 * time.Millisecond
|
longHousekeeping := 100 * time.Millisecond
|
||||||
@ -226,12 +232,24 @@ func (c *containerData) housekeeping() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Schedule the next housekeeping. Sleep until that time.
|
// Run custom collectors.
|
||||||
nextHousekeeping := c.nextHousekeeping(lastHousekeeping)
|
nextCollectionTime, err := c.collectorManager.Collect()
|
||||||
if time.Now().Before(nextHousekeeping) {
|
if err != nil && c.allowErrorLogging() {
|
||||||
time.Sleep(nextHousekeeping.Sub(time.Now()))
|
glog.Warningf("[%s] Collection failed: %v", c.info.Name, err)
|
||||||
}
|
}
|
||||||
lastHousekeeping = nextHousekeeping
|
|
||||||
|
// Next housekeeping is the first of the stats or the custom collector's housekeeping.
|
||||||
|
nextHousekeeping := c.nextHousekeeping(lastHousekeeping)
|
||||||
|
next := nextHousekeeping
|
||||||
|
if !nextCollectionTime.IsZero() && nextCollectionTime.Before(nextHousekeeping) {
|
||||||
|
next = nextCollectionTime
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule the next housekeeping. Sleep until that time.
|
||||||
|
if time.Now().Before(next) {
|
||||||
|
time.Sleep(next.Sub(time.Now()))
|
||||||
|
}
|
||||||
|
lastHousekeeping = next
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +320,7 @@ func (c *containerData) updateStats() error {
|
|||||||
err := c.summaryReader.AddSample(*stats)
|
err := c.summaryReader.AddSample(*stats)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore summary errors for now.
|
// Ignore summary errors for now.
|
||||||
glog.V(2).Infof("failed to add summary stats for %q: %v", c.info.Name, err)
|
glog.V(2).Infof("Failed to add summary stats for %q: %v", c.info.Name, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ref, err := c.handler.ContainerReference()
|
ref, err := c.handler.ContainerReference()
|
||||||
|
3
Godeps/_workspace/src/github.com/google/cadvisor/manager/container_test.go
generated
vendored
3
Godeps/_workspace/src/github.com/google/cadvisor/manager/container_test.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/cadvisor/collector"
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
itest "github.com/google/cadvisor/info/v1/test"
|
itest "github.com/google/cadvisor/info/v1/test"
|
||||||
@ -40,7 +41,7 @@ func setupContainerData(t *testing.T, spec info.ContainerSpec) (*containerData,
|
|||||||
nil,
|
nil,
|
||||||
)
|
)
|
||||||
memoryStorage := memory.New(60, nil)
|
memoryStorage := memory.New(60, nil)
|
||||||
ret, err := newContainerData(containerName, memoryStorage, mockHandler, nil, false)
|
ret, err := newContainerData(containerName, memoryStorage, mockHandler, nil, false, &collector.FakeCollectorManager{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
96
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager.go
generated
vendored
96
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager.go
generated
vendored
@ -20,12 +20,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path"
|
"path"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/docker/libcontainer/cgroups"
|
"github.com/docker/libcontainer/cgroups"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
"github.com/google/cadvisor/collector"
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
"github.com/google/cadvisor/container/docker"
|
"github.com/google/cadvisor/container/docker"
|
||||||
"github.com/google/cadvisor/container/raw"
|
"github.com/google/cadvisor/container/raw"
|
||||||
@ -42,6 +44,8 @@ import (
|
|||||||
var globalHousekeepingInterval = flag.Duration("global_housekeeping_interval", 1*time.Minute, "Interval between global housekeepings")
|
var globalHousekeepingInterval = flag.Duration("global_housekeeping_interval", 1*time.Minute, "Interval between global housekeepings")
|
||||||
var logCadvisorUsage = flag.Bool("log_cadvisor_usage", false, "Whether to log the usage of the cAdvisor container")
|
var logCadvisorUsage = flag.Bool("log_cadvisor_usage", false, "Whether to log the usage of the cAdvisor container")
|
||||||
var enableLoadReader = flag.Bool("enable_load_reader", false, "Whether to enable cpu load reader")
|
var enableLoadReader = flag.Bool("enable_load_reader", false, "Whether to enable cpu load reader")
|
||||||
|
var eventStorageAgeLimit = flag.String("event_storage_age_limit", "default=24h", "Max length of time for which to store events (per type). Value is a comma separated list of key values, where the keys are event types (e.g.: creation, oom) or \"default\" and the value is a duration. Default is applied to all non-specified event types")
|
||||||
|
var eventStorageEventLimit = flag.String("event_storage_event_limit", "default=100000", "Max number of events to store (per type). Value is a comma separated list of key values, where the keys are event types (e.g.: creation, oom) or \"default\" and the value is an integer. Default is applied to all non-specified event types")
|
||||||
|
|
||||||
// The Manager interface defines operations for starting a manager and getting
|
// The Manager interface defines operations for starting a manager and getting
|
||||||
// container and machine information.
|
// container and machine information.
|
||||||
@ -73,6 +77,9 @@ type Manager interface {
|
|||||||
// Get info for all requested containers based on the request options.
|
// Get info for all requested containers based on the request options.
|
||||||
GetRequestedContainersInfo(containerName string, options v2.RequestOptions) (map[string]*info.ContainerInfo, error)
|
GetRequestedContainersInfo(containerName string, options v2.RequestOptions) (map[string]*info.ContainerInfo, error)
|
||||||
|
|
||||||
|
// Returns true if the named container exists.
|
||||||
|
Exists(containerName string) bool
|
||||||
|
|
||||||
// Get information about the machine.
|
// Get information about the machine.
|
||||||
GetMachineInfo() (*info.MachineInfo, error)
|
GetMachineInfo() (*info.MachineInfo, error)
|
||||||
|
|
||||||
@ -133,7 +140,7 @@ func New(memoryStorage *memory.InMemoryStorage, sysfs sysfs.SysFs) (Manager, err
|
|||||||
newManager.versionInfo = *versionInfo
|
newManager.versionInfo = *versionInfo
|
||||||
glog.Infof("Version: %+v", newManager.versionInfo)
|
glog.Infof("Version: %+v", newManager.versionInfo)
|
||||||
|
|
||||||
newManager.eventHandler = events.NewEventManager()
|
newManager.eventHandler = events.NewEventManager(parseEventsStoragePolicy())
|
||||||
|
|
||||||
// Register Docker container factory.
|
// Register Docker container factory.
|
||||||
err = docker.Register(newManager, fsInfo)
|
err = docker.Register(newManager, fsInfo)
|
||||||
@ -618,14 +625,39 @@ func (m *manager) GetVersionInfo() (*info.VersionInfo, error) {
|
|||||||
return &m.versionInfo, nil
|
return &m.versionInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *manager) Exists(containerName string) bool {
|
||||||
|
m.containersLock.Lock()
|
||||||
|
defer m.containersLock.Unlock()
|
||||||
|
|
||||||
|
namespacedName := namespacedContainerName{
|
||||||
|
Name: containerName,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := m.containers[namespacedName]
|
||||||
|
if ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// Create a container.
|
// Create a container.
|
||||||
func (m *manager) createContainer(containerName string) error {
|
func (m *manager) createContainer(containerName string) error {
|
||||||
handler, err := container.NewContainerHandler(containerName)
|
handler, accept, err := container.NewContainerHandler(containerName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !accept {
|
||||||
|
// ignoring this container.
|
||||||
|
glog.V(4).Infof("ignoring container %q", containerName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// TODO(vmarmol): Register collectors.
|
||||||
|
collectorManager, err := collector.NewCollectorManager()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
logUsage := *logCadvisorUsage && containerName == m.cadvisorContainer
|
logUsage := *logCadvisorUsage && containerName == m.cadvisorContainer
|
||||||
cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage)
|
cont, err := newContainerData(containerName, m.memoryStorage, handler, m.loadReader, logUsage, collectorManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -659,14 +691,13 @@ func (m *manager) createContainer(containerName string) error {
|
|||||||
if alreadyExists {
|
if alreadyExists {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
glog.V(2).Infof("Added container: %q (aliases: %v, namespace: %q)", containerName, cont.info.Aliases, cont.info.Namespace)
|
glog.V(3).Infof("Added container: %q (aliases: %v, namespace: %q)", containerName, cont.info.Aliases, cont.info.Namespace)
|
||||||
|
|
||||||
contSpec, err := cont.handler.GetSpec()
|
contSpec, err := cont.handler.GetSpec()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if contSpec.CreationTime.After(m.startupTime) {
|
|
||||||
contRef, err := cont.handler.ContainerReference()
|
contRef, err := cont.handler.ContainerReference()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -676,17 +707,11 @@ func (m *manager) createContainer(containerName string) error {
|
|||||||
ContainerName: contRef.Name,
|
ContainerName: contRef.Name,
|
||||||
Timestamp: contSpec.CreationTime,
|
Timestamp: contSpec.CreationTime,
|
||||||
EventType: info.EventContainerCreation,
|
EventType: info.EventContainerCreation,
|
||||||
EventData: info.EventData{
|
|
||||||
Created: &info.CreatedEventData{
|
|
||||||
Spec: contSpec,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
err = m.eventHandler.AddEvent(newEvent)
|
err = m.eventHandler.AddEvent(newEvent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Start the container's housekeeping.
|
// Start the container's housekeeping.
|
||||||
cont.Start()
|
cont.Start()
|
||||||
@ -721,7 +746,7 @@ func (m *manager) destroyContainer(containerName string) error {
|
|||||||
Name: alias,
|
Name: alias,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
glog.V(2).Infof("Destroyed container: %q (aliases: %v, namespace: %q)", containerName, cont.info.Aliases, cont.info.Namespace)
|
glog.V(3).Infof("Destroyed container: %q (aliases: %v, namespace: %q)", containerName, cont.info.Aliases, cont.info.Namespace)
|
||||||
|
|
||||||
contRef, err := cont.handler.ContainerReference()
|
contRef, err := cont.handler.ContainerReference()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -925,3 +950,50 @@ func (self *manager) GetPastEvents(request *events.Request) ([]*info.Event, erro
|
|||||||
func (self *manager) CloseEventChannel(watch_id int) {
|
func (self *manager) CloseEventChannel(watch_id int) {
|
||||||
self.eventHandler.StopWatch(watch_id)
|
self.eventHandler.StopWatch(watch_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parses the events StoragePolicy from the flags.
|
||||||
|
func parseEventsStoragePolicy() events.StoragePolicy {
|
||||||
|
policy := events.DefaultStoragePolicy()
|
||||||
|
|
||||||
|
// Parse max age.
|
||||||
|
parts := strings.Split(*eventStorageAgeLimit, ",")
|
||||||
|
for _, part := range parts {
|
||||||
|
items := strings.Split(part, "=")
|
||||||
|
if len(items) != 2 {
|
||||||
|
glog.Warningf("Unknown event storage policy %q when parsing max age", part)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dur, err := time.ParseDuration(items[1])
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("Unable to parse event max age duration %q: %v", items[1], err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if items[0] == "default" {
|
||||||
|
policy.DefaultMaxAge = dur
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
policy.PerTypeMaxAge[info.EventType(items[0])] = dur
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse max number.
|
||||||
|
parts = strings.Split(*eventStorageEventLimit, ",")
|
||||||
|
for _, part := range parts {
|
||||||
|
items := strings.Split(part, "=")
|
||||||
|
if len(items) != 2 {
|
||||||
|
glog.Warningf("Unknown event storage policy %q when parsing max event limit", part)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val, err := strconv.Atoi(items[1])
|
||||||
|
if err != nil {
|
||||||
|
glog.Warningf("Unable to parse integer from %q: %v", items[1], err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if items[0] == "default" {
|
||||||
|
policy.DefaultMaxNumEvents = val
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
policy.PerTypeMaxNumEvents[info.EventType(items[0])] = val
|
||||||
|
}
|
||||||
|
|
||||||
|
return policy
|
||||||
|
}
|
||||||
|
5
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager_mock.go
generated
vendored
5
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager_mock.go
generated
vendored
@ -70,6 +70,11 @@ func (c *ManagerMock) GetRequestedContainersInfo(containerName string, options v
|
|||||||
return args.Get(0).(map[string]*info.ContainerInfo), args.Error(1)
|
return args.Get(0).(map[string]*info.ContainerInfo), args.Error(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ManagerMock) Exists(name string) bool {
|
||||||
|
args := c.Called(name)
|
||||||
|
return args.Get(0).(bool)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *ManagerMock) WatchForEvents(queryuest *events.Request, passedChannel chan *info.Event) error {
|
func (c *ManagerMock) WatchForEvents(queryuest *events.Request, passedChannel chan *info.Event) error {
|
||||||
args := c.Called(queryuest, passedChannel)
|
args := c.Called(queryuest, passedChannel)
|
||||||
return args.Error(0)
|
return args.Error(0)
|
||||||
|
3
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager_test.go
generated
vendored
3
Godeps/_workspace/src/github.com/google/cadvisor/manager/manager_test.go
generated
vendored
@ -22,6 +22,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/cadvisor/collector"
|
||||||
"github.com/google/cadvisor/container"
|
"github.com/google/cadvisor/container"
|
||||||
"github.com/google/cadvisor/container/docker"
|
"github.com/google/cadvisor/container/docker"
|
||||||
info "github.com/google/cadvisor/info/v1"
|
info "github.com/google/cadvisor/info/v1"
|
||||||
@ -52,7 +53,7 @@ func createManagerAndAddContainers(
|
|||||||
spec,
|
spec,
|
||||||
nil,
|
nil,
|
||||||
).Once()
|
).Once()
|
||||||
cont, err := newContainerData(name, memoryStorage, mockHandler, nil, false)
|
cont, err := newContainerData(name, memoryStorage, mockHandler, nil, false, &collector.FakeCollectorManager{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
19
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers.go
generated
vendored
19
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers.go
generated
vendored
@ -195,12 +195,14 @@ func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootDir := getRootDir(containerName)
|
||||||
|
|
||||||
// Make a list of the parent containers and their links
|
// Make a list of the parent containers and their links
|
||||||
pathParts := strings.Split(string(cont.Name), "/")
|
pathParts := strings.Split(string(cont.Name), "/")
|
||||||
parentContainers := make([]link, 0, len(pathParts))
|
parentContainers := make([]link, 0, len(pathParts))
|
||||||
parentContainers = append(parentContainers, link{
|
parentContainers = append(parentContainers, link{
|
||||||
Text: "root",
|
Text: "root",
|
||||||
Link: ContainersPage,
|
Link: path.Join(rootDir, ContainersPage),
|
||||||
})
|
})
|
||||||
for i := 1; i < len(pathParts); i++ {
|
for i := 1; i < len(pathParts); i++ {
|
||||||
// Skip empty parts.
|
// Skip empty parts.
|
||||||
@ -209,16 +211,19 @@ func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) e
|
|||||||
}
|
}
|
||||||
parentContainers = append(parentContainers, link{
|
parentContainers = append(parentContainers, link{
|
||||||
Text: pathParts[i],
|
Text: pathParts[i],
|
||||||
Link: path.Join(ContainersPage, path.Join(pathParts[1:i+1]...)),
|
Link: path.Join(rootDir, ContainersPage, path.Join(pathParts[1:i+1]...)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the links for the subcontainers.
|
// Build the links for the subcontainers.
|
||||||
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
subcontainerLinks := make([]link, 0, len(cont.Subcontainers))
|
||||||
for _, sub := range cont.Subcontainers {
|
for _, sub := range cont.Subcontainers {
|
||||||
|
if !m.Exists(sub.Name) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
subcontainerLinks = append(subcontainerLinks, link{
|
subcontainerLinks = append(subcontainerLinks, link{
|
||||||
Text: getContainerDisplayName(sub),
|
Text: getContainerDisplayName(sub),
|
||||||
Link: path.Join(ContainersPage, sub.Name),
|
Link: path.Join(rootDir, ContainersPage, sub.Name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +241,7 @@ func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) e
|
|||||||
MemoryAvailable: cont.Spec.HasMemory,
|
MemoryAvailable: cont.Spec.HasMemory,
|
||||||
NetworkAvailable: cont.Spec.HasNetwork,
|
NetworkAvailable: cont.Spec.HasNetwork,
|
||||||
FsAvailable: cont.Spec.HasFilesystem,
|
FsAvailable: cont.Spec.HasFilesystem,
|
||||||
|
Root: rootDir,
|
||||||
}
|
}
|
||||||
err = pageTemplate.Execute(w, data)
|
err = pageTemplate.Execute(w, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -245,3 +251,10 @@ func serveContainersPage(m manager.Manager, w http.ResponseWriter, u *url.URL) e
|
|||||||
glog.V(5).Infof("Request took %s", time.Since(start))
|
glog.V(5).Infof("Request took %s", time.Since(start))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build a relative path to the root of the container page.
|
||||||
|
func getRootDir(containerName string) string {
|
||||||
|
// The root is at: container depth
|
||||||
|
levels := (strings.Count(containerName, "/"))
|
||||||
|
return strings.Repeat("../", levels)
|
||||||
|
}
|
||||||
|
20
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers_html.go
generated
vendored
20
Godeps/_workspace/src/github.com/google/cadvisor/pages/containers_html.go
generated
vendored
@ -19,23 +19,23 @@ const containersHtmlTemplate = `
|
|||||||
<head>
|
<head>
|
||||||
<title>cAdvisor - {{.DisplayName}}</title>
|
<title>cAdvisor - {{.DisplayName}}</title>
|
||||||
<!-- Latest compiled and minified CSS -->
|
<!-- Latest compiled and minified CSS -->
|
||||||
<link rel="stylesheet" href="/static/bootstrap-3.1.1.min.css">
|
<link rel="stylesheet" href="{{.Root}}static/bootstrap-3.1.1.min.css">
|
||||||
|
|
||||||
<!-- Optional theme -->
|
<!-- Optional theme -->
|
||||||
<link rel="stylesheet" href="/static/bootstrap-theme-3.1.1.min.css">
|
<link rel="stylesheet" href="{{.Root}}static/bootstrap-theme-3.1.1.min.css">
|
||||||
|
|
||||||
<link rel="stylesheet" href="/static/containers.css">
|
<link rel="stylesheet" href="{{.Root}}static/containers.css">
|
||||||
|
|
||||||
<!-- Latest compiled and minified JavaScript -->
|
<!-- Latest compiled and minified JavaScript -->
|
||||||
<script src="/static/jquery-1.10.2.min.js"></script>
|
<script src="{{.Root}}static/jquery-1.10.2.min.js"></script>
|
||||||
<script src="/static/bootstrap-3.1.1.min.js"></script>
|
<script src="{{.Root}}static/bootstrap-3.1.1.min.js"></script>
|
||||||
<script type="text/javascript" src="/static/google-jsapi.js"></script>
|
<script type="text/javascript" src="{{.Root}}static/google-jsapi.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="/static/containers.js"></script>
|
<script type="text/javascript" src="{{.Root}}static/containers.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container theme-showcase" >
|
<div class="container theme-showcase" >
|
||||||
<a href="/" class="col-sm-12" id="logo">
|
<a href="{{.Root}}" class="col-sm-12" id="logo">
|
||||||
</a>
|
</a>
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
@ -49,7 +49,7 @@ const containersHtmlTemplate = `
|
|||||||
</div>
|
</div>
|
||||||
{{if .IsRoot}}
|
{{if .IsRoot}}
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<h4><a href="/docker">Docker Containers</a></h4>
|
<h4><a href="../docker">Docker Containers</a></h4>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .Subcontainers}}
|
{{if .Subcontainers}}
|
||||||
@ -179,7 +179,7 @@ const containersHtmlTemplate = `
|
|||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
startPage({{.ContainerName}}, {{.CpuAvailable}}, {{.MemoryAvailable}});
|
startPage({{.ContainerName}}, {{.CpuAvailable}}, {{.MemoryAvailable}}, {{.Root}});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
3
Godeps/_workspace/src/github.com/google/cadvisor/pages/docker.go
generated
vendored
3
Godeps/_workspace/src/github.com/google/cadvisor/pages/docker.go
generated
vendored
@ -34,6 +34,7 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error
|
|||||||
|
|
||||||
// The container name is the path after the handler
|
// The container name is the path after the handler
|
||||||
containerName := u.Path[len(DockerPage):]
|
containerName := u.Path[len(DockerPage):]
|
||||||
|
rootDir := getRootDir(u.Path)
|
||||||
|
|
||||||
var data *pageData
|
var data *pageData
|
||||||
if containerName == "" {
|
if containerName == "" {
|
||||||
@ -62,6 +63,7 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error
|
|||||||
Link: DockerPage,
|
Link: DockerPage,
|
||||||
}},
|
}},
|
||||||
Subcontainers: subcontainers,
|
Subcontainers: subcontainers,
|
||||||
|
Root: rootDir,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Get the container.
|
// Get the container.
|
||||||
@ -103,6 +105,7 @@ func serveDockerPage(m manager.Manager, w http.ResponseWriter, u *url.URL) error
|
|||||||
MemoryAvailable: cont.Spec.HasMemory,
|
MemoryAvailable: cont.Spec.HasMemory,
|
||||||
NetworkAvailable: cont.Spec.HasNetwork,
|
NetworkAvailable: cont.Spec.HasNetwork,
|
||||||
FsAvailable: cont.Spec.HasFilesystem,
|
FsAvailable: cont.Spec.HasFilesystem,
|
||||||
|
Root: rootDir,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
Godeps/_workspace/src/github.com/google/cadvisor/pages/pages.go
generated
vendored
1
Godeps/_workspace/src/github.com/google/cadvisor/pages/pages.go
generated
vendored
@ -51,6 +51,7 @@ type pageData struct {
|
|||||||
MemoryAvailable bool
|
MemoryAvailable bool
|
||||||
NetworkAvailable bool
|
NetworkAvailable bool
|
||||||
FsAvailable bool
|
FsAvailable bool
|
||||||
|
Root string
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
14
Godeps/_workspace/src/github.com/google/cadvisor/pages/static/containers_js.go
generated
vendored
14
Godeps/_workspace/src/github.com/google/cadvisor/pages/static/containers_js.go
generated
vendored
@ -1518,21 +1518,21 @@ function drawGauges(elementId, gauges) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the machine info.
|
// Get the machine info.
|
||||||
function getMachineInfo(callback) {
|
function getMachineInfo(rootDir, callback) {
|
||||||
$.getJSON("/api/v1.0/machine", function(data) {
|
$.getJSON(rootDir + "api/v1.0/machine", function(data) {
|
||||||
callback(data);
|
callback(data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the container stats for the specified container.
|
// Get the container stats for the specified container.
|
||||||
function getStats(containerName, callback) {
|
function getStats(rootDir, containerName, callback) {
|
||||||
// Request 60s of container history and no samples.
|
// Request 60s of container history and no samples.
|
||||||
var request = JSON.stringify({
|
var request = JSON.stringify({
|
||||||
// Update main.statsRequestedByUI while updating "num_stats" here.
|
// Update main.statsRequestedByUI while updating "num_stats" here.
|
||||||
"num_stats": 60,
|
"num_stats": 60,
|
||||||
"num_samples": 0
|
"num_samples": 0
|
||||||
});
|
});
|
||||||
$.post("/api/v1.0/containers" + containerName, request, function(data) {
|
$.post(rootDir + "api/v1.0/containers" + containerName, request, function(data) {
|
||||||
callback(data);
|
callback(data);
|
||||||
}, "json");
|
}, "json");
|
||||||
}
|
}
|
||||||
@ -1891,7 +1891,7 @@ function drawCharts(machineInfo, containerInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Executed when the page finishes loading.
|
// Executed when the page finishes loading.
|
||||||
function startPage(containerName, hasCpu, hasMemory) {
|
function startPage(containerName, hasCpu, hasMemory, rootDir) {
|
||||||
// Don't fetch data if we don't have any resource.
|
// Don't fetch data if we don't have any resource.
|
||||||
if (!hasCpu && !hasMemory) {
|
if (!hasCpu && !hasMemory) {
|
||||||
return;
|
return;
|
||||||
@ -1902,9 +1902,9 @@ function startPage(containerName, hasCpu, hasMemory) {
|
|||||||
window.cadvisor.firstRun = true;
|
window.cadvisor.firstRun = true;
|
||||||
|
|
||||||
// Get machine info, then get the stats every 1s.
|
// Get machine info, then get the stats every 1s.
|
||||||
getMachineInfo(function(machineInfo) {
|
getMachineInfo(rootDir, function(machineInfo) {
|
||||||
setInterval(function() {
|
setInterval(function() {
|
||||||
getStats(containerName, function(containerInfo){
|
getStats(rootDir, containerName, function(containerInfo){
|
||||||
if (window.cadvisor.firstRun && containerInfo.spec.has_filesystem) {
|
if (window.cadvisor.firstRun && containerInfo.spec.has_filesystem) {
|
||||||
window.cadvisor.firstRun = false;
|
window.cadvisor.firstRun = false;
|
||||||
startFileSystemUsage("filesystem-usage", machineInfo, containerInfo);
|
startFileSystemUsage("filesystem-usage", machineInfo, containerInfo);
|
||||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/storage/memory/memory.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/storage/memory/memory.go
generated
vendored
@ -57,7 +57,7 @@ func (self *containerStorage) RecentStats(start, end time.Time, maxStats int) ([
|
|||||||
func newContainerStore(ref info.ContainerReference, maxAge time.Duration) *containerStorage {
|
func newContainerStore(ref info.ContainerReference, maxAge time.Duration) *containerStorage {
|
||||||
return &containerStorage{
|
return &containerStorage{
|
||||||
ref: ref,
|
ref: ref,
|
||||||
recentStats: utils.NewTimedStore(maxAge),
|
recentStats: utils.NewTimedStore(maxAge, -1),
|
||||||
maxAge: maxAge,
|
maxAge: maxAge,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/utils/oomparser/oomparser.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/utils/oomparser/oomparser.go
generated
vendored
@ -180,7 +180,7 @@ func trySystemd() (*OomParser, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
glog.V(1).Infof("oomparser using systemd")
|
glog.Infof("oomparser using systemd")
|
||||||
return &OomParser{
|
return &OomParser{
|
||||||
ioreader: bufio.NewReader(readcloser),
|
ioreader: bufio.NewReader(readcloser),
|
||||||
}, nil
|
}, nil
|
||||||
|
14
Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store.go
generated
vendored
14
Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store.go
generated
vendored
@ -19,10 +19,12 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A time-based buffer for ContainerStats. Holds information for a specific time period.
|
// A time-based buffer for ContainerStats.
|
||||||
|
// Holds information for a specific time period and/or a max number of items.
|
||||||
type TimedStore struct {
|
type TimedStore struct {
|
||||||
buffer []timedStoreData
|
buffer []timedStoreData
|
||||||
age time.Duration
|
age time.Duration
|
||||||
|
maxItems int
|
||||||
}
|
}
|
||||||
|
|
||||||
type timedStoreData struct {
|
type timedStoreData struct {
|
||||||
@ -31,10 +33,12 @@ type timedStoreData struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns a new thread-compatible TimedStore.
|
// Returns a new thread-compatible TimedStore.
|
||||||
func NewTimedStore(age time.Duration) *TimedStore {
|
// A maxItems value of -1 means no limit.
|
||||||
|
func NewTimedStore(age time.Duration, maxItems int) *TimedStore {
|
||||||
return &TimedStore{
|
return &TimedStore{
|
||||||
buffer: make([]timedStoreData, 0),
|
buffer: make([]timedStoreData, 0),
|
||||||
age: age,
|
age: age,
|
||||||
|
maxItems: maxItems,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,6 +53,12 @@ func (self *TimedStore) Add(timestamp time.Time, item interface{}) {
|
|||||||
self.buffer = self.buffer[index:]
|
self.buffer = self.buffer[index:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove any elements if over our max size.
|
||||||
|
if self.maxItems >= 0 && (len(self.buffer)+1) > self.maxItems {
|
||||||
|
startIndex := len(self.buffer) + 1 - self.maxItems
|
||||||
|
self.buffer = self.buffer[startIndex:]
|
||||||
|
}
|
||||||
|
|
||||||
copied := item
|
copied := item
|
||||||
self.buffer = append(self.buffer, timedStoreData{
|
self.buffer = append(self.buffer, timedStoreData{
|
||||||
timestamp: timestamp,
|
timestamp: timestamp,
|
||||||
|
37
Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store_test.go
generated
vendored
37
Godeps/_workspace/src/github.com/google/cadvisor/utils/timed_store_test.go
generated
vendored
@ -55,7 +55,7 @@ func expectElements(t *testing.T, actual []interface{}, expected []int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAdd(t *testing.T) {
|
func TestAdd(t *testing.T) {
|
||||||
sb := NewTimedStore(5 * time.Second)
|
sb := NewTimedStore(5*time.Second, 100)
|
||||||
|
|
||||||
// Add 1.
|
// Add 1.
|
||||||
sb.Add(createTime(0), 0)
|
sb.Add(createTime(0), 0)
|
||||||
@ -84,7 +84,7 @@ func TestAdd(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
sb := NewTimedStore(5 * time.Second)
|
sb := NewTimedStore(5*time.Second, -1)
|
||||||
sb.Add(createTime(1), 1)
|
sb.Add(createTime(1), 1)
|
||||||
sb.Add(createTime(2), 2)
|
sb.Add(createTime(2), 2)
|
||||||
sb.Add(createTime(3), 3)
|
sb.Add(createTime(3), 3)
|
||||||
@ -97,7 +97,7 @@ func TestGet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInTimeRange(t *testing.T) {
|
func TestInTimeRange(t *testing.T) {
|
||||||
sb := NewTimedStore(5 * time.Second)
|
sb := NewTimedStore(5*time.Second, -1)
|
||||||
assert := assert.New(t)
|
assert := assert.New(t)
|
||||||
|
|
||||||
var empty time.Time
|
var empty time.Time
|
||||||
@ -174,7 +174,7 @@ func TestInTimeRange(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestInTimeRangeWithLimit(t *testing.T) {
|
func TestInTimeRangeWithLimit(t *testing.T) {
|
||||||
sb := NewTimedStore(5 * time.Second)
|
sb := NewTimedStore(5*time.Second, -1)
|
||||||
sb.Add(createTime(1), 1)
|
sb.Add(createTime(1), 1)
|
||||||
sb.Add(createTime(2), 2)
|
sb.Add(createTime(2), 2)
|
||||||
sb.Add(createTime(3), 3)
|
sb.Add(createTime(3), 3)
|
||||||
@ -190,3 +190,32 @@ func TestInTimeRangeWithLimit(t *testing.T) {
|
|||||||
expectElements(t, sb.InTimeRange(empty, empty, 1), []int{4})
|
expectElements(t, sb.InTimeRange(empty, empty, 1), []int{4})
|
||||||
assert.Empty(t, sb.InTimeRange(empty, empty, 0))
|
assert.Empty(t, sb.InTimeRange(empty, empty, 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLimitedSize(t *testing.T) {
|
||||||
|
sb := NewTimedStore(time.Hour, 5)
|
||||||
|
|
||||||
|
// Add 1.
|
||||||
|
sb.Add(createTime(0), 0)
|
||||||
|
expectSize(t, sb, 1)
|
||||||
|
expectAllElements(t, sb, []int{0})
|
||||||
|
|
||||||
|
// Fill the buffer.
|
||||||
|
for i := 1; i <= 5; i++ {
|
||||||
|
expectSize(t, sb, i)
|
||||||
|
sb.Add(createTime(i), i)
|
||||||
|
}
|
||||||
|
expectSize(t, sb, 5)
|
||||||
|
expectAllElements(t, sb, []int{1, 2, 3, 4, 5})
|
||||||
|
|
||||||
|
// Add more than is available in the buffer
|
||||||
|
sb.Add(createTime(6), 6)
|
||||||
|
expectSize(t, sb, 5)
|
||||||
|
expectAllElements(t, sb, []int{2, 3, 4, 5, 6})
|
||||||
|
|
||||||
|
// Replace all elements.
|
||||||
|
for i := 7; i <= 10; i++ {
|
||||||
|
sb.Add(createTime(i), i)
|
||||||
|
}
|
||||||
|
expectSize(t, sb, 5)
|
||||||
|
expectAllElements(t, sb, []int{6, 7, 8, 9, 10})
|
||||||
|
}
|
||||||
|
2
Godeps/_workspace/src/github.com/google/cadvisor/version/version.go
generated
vendored
2
Godeps/_workspace/src/github.com/google/cadvisor/version/version.go
generated
vendored
@ -15,4 +15,4 @@
|
|||||||
package version
|
package version
|
||||||
|
|
||||||
// Version of cAdvisor.
|
// Version of cAdvisor.
|
||||||
const VERSION = "0.12.0"
|
const VERSION = "0.13.0"
|
||||||
|
@ -24,7 +24,7 @@ Example:
|
|||||||
}
|
}
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package inotify
|
package inotify // import "golang.org/x/exp/inotify"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
@ -221,7 +221,7 @@ func (e *Event) String() string {
|
|||||||
|
|
||||||
m := e.Mask
|
m := e.Mask
|
||||||
for _, b := range eventBits {
|
for _, b := range eventBits {
|
||||||
if m&b.Value != 0 {
|
if m&b.Value == b.Value {
|
||||||
m &^= b.Value
|
m &^= b.Value
|
||||||
events += "|" + b.Name
|
events += "|" + b.Name
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user