github.com/hustcat/docker@v1.3.3-0.20160314103604-901c67a8eeab/api/client/events.go (about) 1 package client 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "sort" 8 "strings" 9 "sync" 10 "time" 11 12 "golang.org/x/net/context" 13 14 "github.com/Sirupsen/logrus" 15 Cli "github.com/docker/docker/cli" 16 "github.com/docker/docker/opts" 17 "github.com/docker/docker/pkg/jsonlog" 18 flag "github.com/docker/docker/pkg/mflag" 19 "github.com/docker/engine-api/types" 20 eventtypes "github.com/docker/engine-api/types/events" 21 "github.com/docker/engine-api/types/filters" 22 ) 23 24 // CmdEvents prints a live stream of real time events from the server. 25 // 26 // Usage: docker events [OPTIONS] 27 func (cli *DockerCli) CmdEvents(args ...string) error { 28 cmd := Cli.Subcmd("events", nil, Cli.DockerCommands["events"].Description, true) 29 since := cmd.String([]string{"-since"}, "", "Show all events created since timestamp") 30 until := cmd.String([]string{"-until"}, "", "Stream events until this timestamp") 31 flFilter := opts.NewListOpts(nil) 32 cmd.Var(&flFilter, []string{"f", "-filter"}, "Filter output based on conditions provided") 33 cmd.Require(flag.Exact, 0) 34 35 cmd.ParseFlags(args, true) 36 37 eventFilterArgs := filters.NewArgs() 38 39 // Consolidate all filter flags, and sanity check them early. 40 // They'll get process in the daemon/server. 41 for _, f := range flFilter.GetAll() { 42 var err error 43 eventFilterArgs, err = filters.ParseFlag(f, eventFilterArgs) 44 if err != nil { 45 return err 46 } 47 } 48 49 options := types.EventsOptions{ 50 Since: *since, 51 Until: *until, 52 Filters: eventFilterArgs, 53 } 54 55 responseBody, err := cli.client.Events(context.Background(), options) 56 if err != nil { 57 return err 58 } 59 defer responseBody.Close() 60 61 return streamEvents(responseBody, cli.out) 62 } 63 64 // streamEvents decodes prints the incoming events in the provided output. 65 func streamEvents(input io.Reader, output io.Writer) error { 66 return decodeEvents(input, func(event eventtypes.Message, err error) error { 67 if err != nil { 68 return err 69 } 70 printOutput(event, output) 71 return nil 72 }) 73 } 74 75 type eventProcessor func(event eventtypes.Message, err error) error 76 77 func decodeEvents(input io.Reader, ep eventProcessor) error { 78 dec := json.NewDecoder(input) 79 for { 80 var event eventtypes.Message 81 err := dec.Decode(&event) 82 if err != nil && err == io.EOF { 83 break 84 } 85 86 if procErr := ep(event, err); procErr != nil { 87 return procErr 88 } 89 } 90 return nil 91 } 92 93 // printOutput prints all types of event information. 94 // Each output includes the event type, actor id, name and action. 95 // Actor attributes are printed at the end if the actor has any. 96 func printOutput(event eventtypes.Message, output io.Writer) { 97 if event.TimeNano != 0 { 98 fmt.Fprintf(output, "%s ", time.Unix(0, event.TimeNano).Format(jsonlog.RFC3339NanoFixed)) 99 } else if event.Time != 0 { 100 fmt.Fprintf(output, "%s ", time.Unix(event.Time, 0).Format(jsonlog.RFC3339NanoFixed)) 101 } 102 103 fmt.Fprintf(output, "%s %s %s", event.Type, event.Action, event.Actor.ID) 104 105 if len(event.Actor.Attributes) > 0 { 106 var attrs []string 107 var keys []string 108 for k := range event.Actor.Attributes { 109 keys = append(keys, k) 110 } 111 sort.Strings(keys) 112 for _, k := range keys { 113 v := event.Actor.Attributes[k] 114 attrs = append(attrs, fmt.Sprintf("%s=%s", k, v)) 115 } 116 fmt.Fprintf(output, " (%s)", strings.Join(attrs, ", ")) 117 } 118 fmt.Fprint(output, "\n") 119 } 120 121 type eventHandler struct { 122 handlers map[string]func(eventtypes.Message) 123 mu sync.Mutex 124 } 125 126 func (w *eventHandler) Handle(action string, h func(eventtypes.Message)) { 127 w.mu.Lock() 128 w.handlers[action] = h 129 w.mu.Unlock() 130 } 131 132 // Watch ranges over the passed in event chan and processes the events based on the 133 // handlers created for a given action. 134 // To stop watching, close the event chan. 135 func (w *eventHandler) Watch(c <-chan eventtypes.Message) { 136 for e := range c { 137 w.mu.Lock() 138 h, exists := w.handlers[e.Action] 139 w.mu.Unlock() 140 if !exists { 141 continue 142 } 143 logrus.Debugf("event handler: received event: %v", e) 144 go h(e) 145 } 146 }