event.go 2.6 KB

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