| // +build linux |
| |
| package main |
| |
| import ( |
| "encoding/json" |
| "os" |
| "sync" |
| "time" |
| |
| "github.com/Sirupsen/logrus" |
| "github.com/codegangsta/cli" |
| "github.com/opencontainers/runc/libcontainer" |
| ) |
| |
| // event struct for encoding the event data to json. |
| type event struct { |
| Type string `json:"type"` |
| ID string `json:"id"` |
| Data interface{} `json:"data,omitempty"` |
| } |
| |
| var eventsCommand = cli.Command{ |
| Name: "events", |
| Usage: "display container events such as OOM notifications and cpu, memeory, IO, and network stats", |
| Flags: []cli.Flag{ |
| cli.DurationFlag{Name: "interval", Value: 5 * time.Second, Usage: "set the stats collection interval"}, |
| cli.BoolFlag{Name: "stats", Usage: "display the container's stats then exit"}, |
| }, |
| Action: func(context *cli.Context) { |
| container, err := getContainer(context) |
| if err != nil { |
| logrus.Fatal(err) |
| } |
| var ( |
| stats = make(chan *libcontainer.Stats, 1) |
| events = make(chan *event, 1024) |
| group = &sync.WaitGroup{} |
| ) |
| group.Add(1) |
| go func() { |
| defer group.Done() |
| enc := json.NewEncoder(os.Stdout) |
| for e := range events { |
| if err := enc.Encode(e); err != nil { |
| logrus.Error(err) |
| } |
| } |
| }() |
| if context.Bool("stats") { |
| s, err := container.Stats() |
| if err != nil { |
| fatal(err) |
| } |
| events <- &event{Type: "stats", ID: container.ID(), Data: s} |
| close(events) |
| group.Wait() |
| return |
| } |
| go func() { |
| for range time.Tick(context.Duration("interval")) { |
| s, err := container.Stats() |
| if err != nil { |
| logrus.Error(err) |
| continue |
| } |
| stats <- s |
| } |
| }() |
| n, err := container.NotifyOOM() |
| if err != nil { |
| logrus.Fatal(err) |
| } |
| for { |
| select { |
| case _, ok := <-n: |
| if ok { |
| // this means an oom event was received, if it is !ok then |
| // the channel was closed because the container stopped and |
| // the cgroups no longer exist. |
| events <- &event{Type: "oom", ID: container.ID()} |
| } else { |
| n = nil |
| } |
| case s := <-stats: |
| events <- &event{Type: "stats", ID: container.ID(), Data: s} |
| } |
| if n == nil { |
| close(events) |
| break |
| } |
| } |
| group.Wait() |
| }, |
| } |