diff --git a/client/client.go b/client/client.go index 9a211185..9a2fd3fe 100644 --- a/client/client.go +++ b/client/client.go @@ -19,11 +19,14 @@ import ( "bytes" "encoding/json" "fmt" + "io" "io/ioutil" "net/http" "path" "strings" + "github.com/golang/glog" + "github.com/google/cadvisor/events" info "github.com/google/cadvisor/info/v1" ) @@ -39,10 +42,32 @@ func NewClient(url string) (*Client, error) { } return &Client{ - baseUrl: fmt.Sprintf("%sapi/v1.2/", url), + baseUrl: fmt.Sprintf("%sapi/v1.3/", url), }, nil } +// Returns all past events that satisfy the request +func (self *Client) EventStaticInfo(name string) (einfo []*events.Event, err error) { + u := self.eventsInfoUrl(name) + glog.V(3).Infof("got complete url %v", u) + ret := new([]*events.Event) + if err = self.httpGetJsonData(ret, nil, u, "event info"); err != nil { + return + } + einfo = *ret + return +} + +// Streams all events that occur that satisfy the request into the channel +// that is passed +func (self *Client) EventStreamingInfo(name string, einfo chan interface{}) (err error) { + u := self.eventsInfoUrl(name) + if err = self.getEventStreamingData(u, einfo); err != nil { + return + } + return nil +} + // MachineInfo returns the JSON machine information for this client. // A non-nil error result indicates a problem with obtaining // the JSON machine information data. @@ -128,6 +153,10 @@ func (self *Client) dockerInfoUrl(name string) string { return self.baseUrl + path.Join("docker", name) } +func (self *Client) eventsInfoUrl(name string) string { + return self.baseUrl + path.Join("events", name) +} + func (self *Client) httpGetJsonData(data, postData interface{}, url, infoName string) error { var resp *http.Response var err error @@ -162,3 +191,31 @@ func (self *Client) httpGetJsonData(data, postData interface{}, url, infoName st } return nil } + +func (self *Client) getEventStreamingData(url string, einfo chan interface{}) error { + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return err + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("Status code is not OK: %v (%s)", resp.StatusCode, resp.Status) + } + + dec := json.NewDecoder(resp.Body) + var m interface{} + for { + err := dec.Decode(&m) + if err != nil { + if err == io.EOF { + break + } + return err + } + einfo <- m + } + return nil +} diff --git a/client/client_test.go b/client/client_test.go index c309650a..40b4c64f 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -91,7 +91,7 @@ func TestGetMachineinfo(t *testing.T) { }, }, } - client, server, err := cadvisorTestClient("/api/v1.2/machine", nil, minfo, t) + client, server, err := cadvisorTestClient("/api/v1.3/machine", nil, minfo, t) if err != nil { t.Fatalf("unable to get a client %v", err) } @@ -113,7 +113,7 @@ func TestGetContainerInfo(t *testing.T) { } containerName := "/some/container" cinfo := itest.GenerateRandomContainerInfo(containerName, 4, query, 1*time.Second) - client, server, err := cadvisorTestClient(fmt.Sprintf("/api/v1.2/containers%v", containerName), query, cinfo, t) + client, server, err := cadvisorTestClient(fmt.Sprintf("/api/v1.3/containers%v", containerName), query, cinfo, t) if err != nil { t.Fatalf("unable to get a client %v", err) } @@ -165,7 +165,7 @@ func TestGetSubcontainersInfo(t *testing.T) { *cinfo1, *cinfo2, } - client, server, err := cadvisorTestClient(fmt.Sprintf("/api/v1.2/subcontainers%v", containerName), query, response, t) + client, server, err := cadvisorTestClient(fmt.Sprintf("/api/v1.3/subcontainers%v", containerName), query, response, t) if err != nil { t.Fatalf("unable to get a client %v", err) } diff --git a/client/clientexample/main.go b/client/clientexample/main.go new file mode 100644 index 00000000..1e1bd0dd --- /dev/null +++ b/client/clientexample/main.go @@ -0,0 +1,64 @@ +// Copyright 2014 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 main + +import ( + "flag" + + "github.com/golang/glog" + "github.com/google/cadvisor/client" +) + +func staticClientExample() { + staticClient, err := client.NewClient("http://localhost:8080/") + if err != nil { + glog.Errorf("tried to make client and got error %v", err) + return + } + einfo, err := staticClient.EventStaticInfo("?oom_events=true&historical=true") + if err != nil { + glog.Errorf("got error retrieving event info: %v", err) + return + } + for idx, ev := range einfo { + glog.Infof("static einfo %v: %v", idx, ev) + } +} + +func streamingClientExample() { + streamingClient, err := client.NewClient("http://localhost:8080/") + if err != nil { + glog.Errorf("tried to make client and got error %v", err) + return + } + einfo := make(chan interface{}) + go func() { + err = streamingClient.EventStreamingInfo("?oom_events=true", einfo) + if err != nil { + glog.Errorf("got error retrieving event info: %v", err) + return + } + }() + for ev := range einfo { + glog.Infof("streaming einfo: %v", ev) + } +} + +// demonstrates how to use event clients +func main() { + flag.Parse() + staticClientExample() + streamingClientExample() +}