1package api 2 3import ( 4 "bytes" 5 "strconv" 6) 7 8// Event can be used to query the Event endpoints 9type Event struct { 10 c *Client 11} 12 13// UserEvent represents an event that was fired by the user 14type UserEvent struct { 15 ID string 16 Name string 17 Payload []byte 18 NodeFilter string 19 ServiceFilter string 20 TagFilter string 21 Version int 22 LTime uint64 23} 24 25// Event returns a handle to the event endpoints 26func (c *Client) Event() *Event { 27 return &Event{c} 28} 29 30// Fire is used to fire a new user event. Only the Name, Payload and Filters 31// are respected. This returns the ID or an associated error. Cross DC requests 32// are supported. 33func (e *Event) Fire(params *UserEvent, q *WriteOptions) (string, *WriteMeta, error) { 34 r := e.c.newRequest("PUT", "/v1/event/fire/"+params.Name) 35 r.setWriteOptions(q) 36 if params.NodeFilter != "" { 37 r.params.Set("node", params.NodeFilter) 38 } 39 if params.ServiceFilter != "" { 40 r.params.Set("service", params.ServiceFilter) 41 } 42 if params.TagFilter != "" { 43 r.params.Set("tag", params.TagFilter) 44 } 45 if params.Payload != nil { 46 r.body = bytes.NewReader(params.Payload) 47 } 48 r.header.Set("Content-Type", "application/octet-stream") 49 50 rtt, resp, err := requireOK(e.c.doRequest(r)) 51 if err != nil { 52 return "", nil, err 53 } 54 defer closeResponseBody(resp) 55 56 wm := &WriteMeta{RequestTime: rtt} 57 var out UserEvent 58 if err := decodeBody(resp, &out); err != nil { 59 return "", nil, err 60 } 61 return out.ID, wm, nil 62} 63 64// List is used to get the most recent events an agent has received. 65// This list can be optionally filtered by the name. This endpoint supports 66// quasi-blocking queries. The index is not monotonic, nor does it provide provide 67// LastContact or KnownLeader. 68func (e *Event) List(name string, q *QueryOptions) ([]*UserEvent, *QueryMeta, error) { 69 r := e.c.newRequest("GET", "/v1/event/list") 70 r.setQueryOptions(q) 71 if name != "" { 72 r.params.Set("name", name) 73 } 74 rtt, resp, err := requireOK(e.c.doRequest(r)) 75 if err != nil { 76 return nil, nil, err 77 } 78 defer closeResponseBody(resp) 79 80 qm := &QueryMeta{} 81 parseQueryMeta(resp, qm) 82 qm.RequestTime = rtt 83 84 var entries []*UserEvent 85 if err := decodeBody(resp, &entries); err != nil { 86 return nil, nil, err 87 } 88 return entries, qm, nil 89} 90 91// IDToIndex is a bit of a hack. This simulates the index generation to 92// convert an event ID into a WaitIndex. 93func (e *Event) IDToIndex(uuid string) uint64 { 94 lower := uuid[0:8] + uuid[9:13] + uuid[14:18] 95 upper := uuid[19:23] + uuid[24:36] 96 lowVal, err := strconv.ParseUint(lower, 16, 64) 97 if err != nil { 98 panic("Failed to convert " + lower) 99 } 100 highVal, err := strconv.ParseUint(upper, 16, 64) 101 if err != nil { 102 panic("Failed to convert " + upper) 103 } 104 return lowVal ^ highVal 105} 106