cluster_health.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // Copyright 2012-present Oliver Eilhard. All rights reserved.
  2. // Use of this source code is governed by a MIT-license.
  3. // See http://olivere.mit-license.org/license.txt for details.
  4. package elastic
  5. import (
  6. "context"
  7. "fmt"
  8. "net/url"
  9. "strings"
  10. "gopkg.in/olivere/elastic.v5/uritemplates"
  11. )
  12. // ClusterHealthService allows to get a very simple status on the health of the cluster.
  13. //
  14. // See http://www.elastic.co/guide/en/elasticsearch/reference/5.2/cluster-health.html
  15. // for details.
  16. type ClusterHealthService struct {
  17. client *Client
  18. pretty bool
  19. indices []string
  20. level string
  21. local *bool
  22. masterTimeout string
  23. timeout string
  24. waitForActiveShards *int
  25. waitForNodes string
  26. waitForNoRelocatingShards *bool
  27. waitForStatus string
  28. }
  29. // NewClusterHealthService creates a new ClusterHealthService.
  30. func NewClusterHealthService(client *Client) *ClusterHealthService {
  31. return &ClusterHealthService{
  32. client: client,
  33. indices: make([]string, 0),
  34. }
  35. }
  36. // Index limits the information returned to specific indices.
  37. func (s *ClusterHealthService) Index(indices ...string) *ClusterHealthService {
  38. s.indices = append(s.indices, indices...)
  39. return s
  40. }
  41. // Level specifies the level of detail for returned information.
  42. func (s *ClusterHealthService) Level(level string) *ClusterHealthService {
  43. s.level = level
  44. return s
  45. }
  46. // Local indicates whether to return local information. If it is true,
  47. // we do not retrieve the state from master node (default: false).
  48. func (s *ClusterHealthService) Local(local bool) *ClusterHealthService {
  49. s.local = &local
  50. return s
  51. }
  52. // MasterTimeout specifies an explicit operation timeout for connection to master node.
  53. func (s *ClusterHealthService) MasterTimeout(masterTimeout string) *ClusterHealthService {
  54. s.masterTimeout = masterTimeout
  55. return s
  56. }
  57. // Timeout specifies an explicit operation timeout.
  58. func (s *ClusterHealthService) Timeout(timeout string) *ClusterHealthService {
  59. s.timeout = timeout
  60. return s
  61. }
  62. // WaitForActiveShards can be used to wait until the specified number of shards are active.
  63. func (s *ClusterHealthService) WaitForActiveShards(waitForActiveShards int) *ClusterHealthService {
  64. s.waitForActiveShards = &waitForActiveShards
  65. return s
  66. }
  67. // WaitForNodes can be used to wait until the specified number of nodes are available.
  68. // Example: "12" to wait for exact values, ">12" and "<12" for ranges.
  69. func (s *ClusterHealthService) WaitForNodes(waitForNodes string) *ClusterHealthService {
  70. s.waitForNodes = waitForNodes
  71. return s
  72. }
  73. // WaitForNoRelocatingShards can be used to wait until all shard relocations are finished.
  74. func (s *ClusterHealthService) WaitForNoRelocatingShards(waitForNoRelocatingShards bool) *ClusterHealthService {
  75. s.waitForNoRelocatingShards = &waitForNoRelocatingShards
  76. return s
  77. }
  78. // WaitForStatus can be used to wait until the cluster is in a specific state.
  79. // Valid values are: green, yellow, or red.
  80. func (s *ClusterHealthService) WaitForStatus(waitForStatus string) *ClusterHealthService {
  81. s.waitForStatus = waitForStatus
  82. return s
  83. }
  84. // WaitForGreenStatus will wait for the "green" state.
  85. func (s *ClusterHealthService) WaitForGreenStatus() *ClusterHealthService {
  86. return s.WaitForStatus("green")
  87. }
  88. // WaitForYellowStatus will wait for the "yellow" state.
  89. func (s *ClusterHealthService) WaitForYellowStatus() *ClusterHealthService {
  90. return s.WaitForStatus("yellow")
  91. }
  92. // Pretty indicates that the JSON response be indented and human readable.
  93. func (s *ClusterHealthService) Pretty(pretty bool) *ClusterHealthService {
  94. s.pretty = pretty
  95. return s
  96. }
  97. // buildURL builds the URL for the operation.
  98. func (s *ClusterHealthService) buildURL() (string, url.Values, error) {
  99. // Build URL
  100. var err error
  101. var path string
  102. if len(s.indices) > 0 {
  103. path, err = uritemplates.Expand("/_cluster/health/{index}", map[string]string{
  104. "index": strings.Join(s.indices, ","),
  105. })
  106. } else {
  107. path = "/_cluster/health"
  108. }
  109. if err != nil {
  110. return "", url.Values{}, err
  111. }
  112. // Add query string parameters
  113. params := url.Values{}
  114. if s.pretty {
  115. params.Set("pretty", "1")
  116. }
  117. if s.level != "" {
  118. params.Set("level", s.level)
  119. }
  120. if s.local != nil {
  121. params.Set("local", fmt.Sprintf("%v", *s.local))
  122. }
  123. if s.masterTimeout != "" {
  124. params.Set("master_timeout", s.masterTimeout)
  125. }
  126. if s.timeout != "" {
  127. params.Set("timeout", s.timeout)
  128. }
  129. if s.waitForActiveShards != nil {
  130. params.Set("wait_for_active_shards", fmt.Sprintf("%v", s.waitForActiveShards))
  131. }
  132. if s.waitForNodes != "" {
  133. params.Set("wait_for_nodes", s.waitForNodes)
  134. }
  135. if s.waitForNoRelocatingShards != nil {
  136. params.Set("wait_for_no_relocating_shards", fmt.Sprintf("%v", *s.waitForNoRelocatingShards))
  137. }
  138. if s.waitForStatus != "" {
  139. params.Set("wait_for_status", s.waitForStatus)
  140. }
  141. return path, params, nil
  142. }
  143. // Validate checks if the operation is valid.
  144. func (s *ClusterHealthService) Validate() error {
  145. return nil
  146. }
  147. // Do executes the operation.
  148. func (s *ClusterHealthService) Do(ctx context.Context) (*ClusterHealthResponse, error) {
  149. // Check pre-conditions
  150. if err := s.Validate(); err != nil {
  151. return nil, err
  152. }
  153. // Get URL for request
  154. path, params, err := s.buildURL()
  155. if err != nil {
  156. return nil, err
  157. }
  158. // Get HTTP response
  159. res, err := s.client.PerformRequest(ctx, "GET", path, params, nil)
  160. if err != nil {
  161. return nil, err
  162. }
  163. // Return operation response
  164. ret := new(ClusterHealthResponse)
  165. if err := s.client.decoder.Decode(res.Body, ret); err != nil {
  166. return nil, err
  167. }
  168. return ret, nil
  169. }
  170. // ClusterHealthResponse is the response of ClusterHealthService.Do.
  171. type ClusterHealthResponse struct {
  172. ClusterName string `json:"cluster_name"`
  173. Status string `json:"status"`
  174. TimedOut bool `json:"timed_out"`
  175. NumberOfNodes int `json:"number_of_nodes"`
  176. NumberOfDataNodes int `json:"number_of_data_nodes"`
  177. ActivePrimaryShards int `json:"active_primary_shards"`
  178. ActiveShards int `json:"active_shards"`
  179. RelocatingShards int `json:"relocating_shards"`
  180. InitializingShards int `json:"initializing_shards"`
  181. UnassignedShards int `json:"unassigned_shards"`
  182. DelayedUnassignedShards int `json:"delayed_unassigned_shards"`
  183. NumberOfPendingTasks int `json:"number_of_pending_tasks"`
  184. NumberOfInFlightFetch int `json:"number_of_in_flight_fetch"`
  185. TaskMaxWaitTimeInQueueInMillis int `json:"task_max_waiting_in_queue_millis"`
  186. ActiveShardsPercentAsNumber float64 `json:"active_shards_percent_as_number"`
  187. // Validation failures -> index name -> array of validation failures
  188. ValidationFailures []map[string][]string `json:"validation_failures"`
  189. // Index name -> index health
  190. Indices map[string]*ClusterIndexHealth `json:"indices"`
  191. }
  192. // ClusterIndexHealth will be returned as part of ClusterHealthResponse.
  193. type ClusterIndexHealth struct {
  194. Status string `json:"status"`
  195. NumberOfShards int `json:"number_of_shards"`
  196. NumberOfReplicas int `json:"number_of_replicas"`
  197. ActivePrimaryShards int `json:"active_primary_shards"`
  198. ActiveShards int `json:"active_shards"`
  199. RelocatingShards int `json:"relocating_shards"`
  200. InitializingShards int `json:"initializing_shards"`
  201. UnassignedShards int `json:"unassigned_shards"`
  202. // Validation failures
  203. ValidationFailures []string `json:"validation_failures"`
  204. // Shards by id, e.g. "0" or "1"
  205. Shards map[string]*ClusterShardHealth `json:"shards"`
  206. }
  207. // ClusterShardHealth will be returned as part of ClusterHealthResponse.
  208. type ClusterShardHealth struct {
  209. Status string `json:"status"`
  210. PrimaryActive bool `json:"primary_active"`
  211. ActiveShards int `json:"active_shards"`
  212. RelocatingShards int `json:"relocating_shards"`
  213. InitializingShards int `json:"initializing_shards"`
  214. UnassignedShards int `json:"unassigned_shards"`
  215. }