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
5package elastic
6
7import (
8	"context"
9	"fmt"
10	"net/url"
11	"strings"
12
13	"gopkg.in/olivere/elastic.v5/uritemplates"
14)
15
16// ClusterStatsService is documented at
17// https://www.elastic.co/guide/en/elasticsearch/reference/5.2/cluster-stats.html.
18type ClusterStatsService struct {
19	client       *Client
20	pretty       bool
21	nodeId       []string
22	flatSettings *bool
23	human        *bool
24}
25
26// NewClusterStatsService creates a new ClusterStatsService.
27func NewClusterStatsService(client *Client) *ClusterStatsService {
28	return &ClusterStatsService{
29		client: client,
30		nodeId: make([]string, 0),
31	}
32}
33
34// NodeId is documented as: A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes.
35func (s *ClusterStatsService) NodeId(nodeId []string) *ClusterStatsService {
36	s.nodeId = nodeId
37	return s
38}
39
40// FlatSettings is documented as: Return settings in flat format (default: false).
41func (s *ClusterStatsService) FlatSettings(flatSettings bool) *ClusterStatsService {
42	s.flatSettings = &flatSettings
43	return s
44}
45
46// Human is documented as: Whether to return time and byte values in human-readable format..
47func (s *ClusterStatsService) Human(human bool) *ClusterStatsService {
48	s.human = &human
49	return s
50}
51
52// Pretty indicates that the JSON response be indented and human readable.
53func (s *ClusterStatsService) Pretty(pretty bool) *ClusterStatsService {
54	s.pretty = pretty
55	return s
56}
57
58// buildURL builds the URL for the operation.
59func (s *ClusterStatsService) buildURL() (string, url.Values, error) {
60	// Build URL
61	var err error
62	var path string
63
64	if len(s.nodeId) > 0 {
65		path, err = uritemplates.Expand("/_cluster/stats/nodes/{node_id}", map[string]string{
66			"node_id": strings.Join(s.nodeId, ","),
67		})
68		if err != nil {
69			return "", url.Values{}, err
70		}
71	} else {
72		path, err = uritemplates.Expand("/_cluster/stats", map[string]string{})
73		if err != nil {
74			return "", url.Values{}, err
75		}
76	}
77
78	// Add query string parameters
79	params := url.Values{}
80	if s.pretty {
81		params.Set("pretty", "1")
82	}
83	if s.flatSettings != nil {
84		params.Set("flat_settings", fmt.Sprintf("%v", *s.flatSettings))
85	}
86	if s.human != nil {
87		params.Set("human", fmt.Sprintf("%v", *s.human))
88	}
89	return path, params, nil
90}
91
92// Validate checks if the operation is valid.
93func (s *ClusterStatsService) Validate() error {
94	return nil
95}
96
97// Do executes the operation.
98func (s *ClusterStatsService) Do(ctx context.Context) (*ClusterStatsResponse, error) {
99	// Check pre-conditions
100	if err := s.Validate(); err != nil {
101		return nil, err
102	}
103
104	// Get URL for request
105	path, params, err := s.buildURL()
106	if err != nil {
107		return nil, err
108	}
109
110	// Get HTTP response
111	res, err := s.client.PerformRequest(ctx, "GET", path, params, nil)
112	if err != nil {
113		return nil, err
114	}
115
116	// Return operation response
117	ret := new(ClusterStatsResponse)
118	if err := s.client.decoder.Decode(res.Body, ret); err != nil {
119		return nil, err
120	}
121	return ret, nil
122}
123
124// ClusterStatsResponse is the response of ClusterStatsService.Do.
125type ClusterStatsResponse struct {
126	Timestamp   int64                `json:"timestamp"`
127	ClusterName string               `json:"cluster_name"`
128	ClusterUUID string               `json:"uuid"`
129	Status      string               `json:"status"`
130	Indices     *ClusterStatsIndices `json:"indices"`
131	Nodes       *ClusterStatsNodes   `json:"nodes"`
132}
133
134type ClusterStatsIndices struct {
135	Count       int                             `json:"count"`
136	Shards      *ClusterStatsIndicesShards      `json:"shards"`
137	Docs        *ClusterStatsIndicesDocs        `json:"docs"`
138	Store       *ClusterStatsIndicesStore       `json:"store"`
139	FieldData   *ClusterStatsIndicesFieldData   `json:"fielddata"`
140	FilterCache *ClusterStatsIndicesFilterCache `json:"filter_cache"`
141	IdCache     *ClusterStatsIndicesIdCache     `json:"id_cache"`
142	Completion  *ClusterStatsIndicesCompletion  `json:"completion"`
143	Segments    *ClusterStatsIndicesSegments    `json:"segments"`
144	Percolate   *ClusterStatsIndicesPercolate   `json:"percolate"`
145}
146
147type ClusterStatsIndicesShards struct {
148	Total       int                             `json:"total"`
149	Primaries   int                             `json:"primaries"`
150	Replication float64                         `json:"replication"`
151	Index       *ClusterStatsIndicesShardsIndex `json:"index"`
152}
153
154type ClusterStatsIndicesShardsIndex struct {
155	Shards      *ClusterStatsIndicesShardsIndexIntMinMax     `json:"shards"`
156	Primaries   *ClusterStatsIndicesShardsIndexIntMinMax     `json:"primaries"`
157	Replication *ClusterStatsIndicesShardsIndexFloat64MinMax `json:"replication"`
158}
159
160type ClusterStatsIndicesShardsIndexIntMinMax struct {
161	Min int     `json:"min"`
162	Max int     `json:"max"`
163	Avg float64 `json:"avg"`
164}
165
166type ClusterStatsIndicesShardsIndexFloat64MinMax struct {
167	Min float64 `json:"min"`
168	Max float64 `json:"max"`
169	Avg float64 `json:"avg"`
170}
171
172type ClusterStatsIndicesDocs struct {
173	Count   int `json:"count"`
174	Deleted int `json:"deleted"`
175}
176
177type ClusterStatsIndicesStore struct {
178	Size                 string `json:"size"` // e.g. "5.3gb"
179	SizeInBytes          int64  `json:"size_in_bytes"`
180	ThrottleTime         string `json:"throttle_time"` // e.g. "0s"
181	ThrottleTimeInMillis int64  `json:"throttle_time_in_millis"`
182}
183
184type ClusterStatsIndicesFieldData struct {
185	MemorySize        string `json:"memory_size"` // e.g. "61.3kb"
186	MemorySizeInBytes int64  `json:"memory_size_in_bytes"`
187	Evictions         int64  `json:"evictions"`
188	Fields            map[string]struct {
189		MemorySize        string `json:"memory_size"` // e.g. "61.3kb"
190		MemorySizeInBytes int64  `json:"memory_size_in_bytes"`
191	} `json:"fields"`
192}
193
194type ClusterStatsIndicesFilterCache struct {
195	MemorySize        string `json:"memory_size"` // e.g. "61.3kb"
196	MemorySizeInBytes int64  `json:"memory_size_in_bytes"`
197	Evictions         int64  `json:"evictions"`
198}
199
200type ClusterStatsIndicesIdCache struct {
201	MemorySize        string `json:"memory_size"` // e.g. "61.3kb"
202	MemorySizeInBytes int64  `json:"memory_size_in_bytes"`
203}
204
205type ClusterStatsIndicesCompletion struct {
206	Size        string `json:"size"` // e.g. "61.3kb"
207	SizeInBytes int64  `json:"size_in_bytes"`
208	Fields      map[string]struct {
209		Size        string `json:"size"` // e.g. "61.3kb"
210		SizeInBytes int64  `json:"size_in_bytes"`
211	} `json:"fields"`
212}
213
214type ClusterStatsIndicesSegments struct {
215	Count                       int64  `json:"count"`
216	Memory                      string `json:"memory"` // e.g. "61.3kb"
217	MemoryInBytes               int64  `json:"memory_in_bytes"`
218	IndexWriterMemory           string `json:"index_writer_memory"` // e.g. "61.3kb"
219	IndexWriterMemoryInBytes    int64  `json:"index_writer_memory_in_bytes"`
220	IndexWriterMaxMemory        string `json:"index_writer_max_memory"` // e.g. "61.3kb"
221	IndexWriterMaxMemoryInBytes int64  `json:"index_writer_max_memory_in_bytes"`
222	VersionMapMemory            string `json:"version_map_memory"` // e.g. "61.3kb"
223	VersionMapMemoryInBytes     int64  `json:"version_map_memory_in_bytes"`
224	FixedBitSet                 string `json:"fixed_bit_set"` // e.g. "61.3kb"
225	FixedBitSetInBytes          int64  `json:"fixed_bit_set_memory_in_bytes"`
226}
227
228type ClusterStatsIndicesPercolate struct {
229	Total int64 `json:"total"`
230	// TODO(oe) The JSON tag here is wrong as of ES 1.5.2 it seems
231	Time              string `json:"get_time"` // e.g. "1s"
232	TimeInBytes       int64  `json:"time_in_millis"`
233	Current           int64  `json:"current"`
234	MemorySize        string `json:"memory_size"` // e.g. "61.3kb"
235	MemorySizeInBytes int64  `json:"memory_sitze_in_bytes"`
236	Queries           int64  `json:"queries"`
237}
238
239// ---
240
241type ClusterStatsNodes struct {
242	Count    *ClusterStatsNodesCount        `json:"count"`
243	Versions []string                       `json:"versions"`
244	OS       *ClusterStatsNodesOsStats      `json:"os"`
245	Process  *ClusterStatsNodesProcessStats `json:"process"`
246	JVM      *ClusterStatsNodesJvmStats     `json:"jvm"`
247	FS       *ClusterStatsNodesFsStats      `json:"fs"`
248	Plugins  []*ClusterStatsNodesPlugin     `json:"plugins"`
249}
250
251type ClusterStatsNodesCount struct {
252	Total            int `json:"total"`
253	Data             int `json:"data"`
254	CoordinatingOnly int `json:"coordinating_only"`
255	Master           int `json:"master"`
256	Ingest           int `json:"ingest"`
257}
258
259type ClusterStatsNodesOsStats struct {
260	AvailableProcessors int                            `json:"available_processors"`
261	Mem                 *ClusterStatsNodesOsStatsMem   `json:"mem"`
262	CPU                 []*ClusterStatsNodesOsStatsCPU `json:"cpu"`
263}
264
265type ClusterStatsNodesOsStatsMem struct {
266	Total        string `json:"total"` // e.g. "16gb"
267	TotalInBytes int64  `json:"total_in_bytes"`
268}
269
270type ClusterStatsNodesOsStatsCPU struct {
271	Vendor           string `json:"vendor"`
272	Model            string `json:"model"`
273	MHz              int    `json:"mhz"`
274	TotalCores       int    `json:"total_cores"`
275	TotalSockets     int    `json:"total_sockets"`
276	CoresPerSocket   int    `json:"cores_per_socket"`
277	CacheSize        string `json:"cache_size"` // e.g. "256b"
278	CacheSizeInBytes int64  `json:"cache_size_in_bytes"`
279	Count            int    `json:"count"`
280}
281
282type ClusterStatsNodesProcessStats struct {
283	CPU                 *ClusterStatsNodesProcessStatsCPU                 `json:"cpu"`
284	OpenFileDescriptors *ClusterStatsNodesProcessStatsOpenFileDescriptors `json:"open_file_descriptors"`
285}
286
287type ClusterStatsNodesProcessStatsCPU struct {
288	Percent float64 `json:"percent"`
289}
290
291type ClusterStatsNodesProcessStatsOpenFileDescriptors struct {
292	Min int64 `json:"min"`
293	Max int64 `json:"max"`
294	Avg int64 `json:"avg"`
295}
296
297type ClusterStatsNodesJvmStats struct {
298	MaxUptime         string                              `json:"max_uptime"` // e.g. "5h"
299	MaxUptimeInMillis int64                               `json:"max_uptime_in_millis"`
300	Versions          []*ClusterStatsNodesJvmStatsVersion `json:"versions"`
301	Mem               *ClusterStatsNodesJvmStatsMem       `json:"mem"`
302	Threads           int64                               `json:"threads"`
303}
304
305type ClusterStatsNodesJvmStatsVersion struct {
306	Version   string `json:"version"`    // e.g. "1.8.0_45"
307	VMName    string `json:"vm_name"`    // e.g. "Java HotSpot(TM) 64-Bit Server VM"
308	VMVersion string `json:"vm_version"` // e.g. "25.45-b02"
309	VMVendor  string `json:"vm_vendor"`  // e.g. "Oracle Corporation"
310	Count     int    `json:"count"`
311}
312
313type ClusterStatsNodesJvmStatsMem struct {
314	HeapUsed        string `json:"heap_used"`
315	HeapUsedInBytes int64  `json:"heap_used_in_bytes"`
316	HeapMax         string `json:"heap_max"`
317	HeapMaxInBytes  int64  `json:"heap_max_in_bytes"`
318}
319
320type ClusterStatsNodesFsStats struct {
321	Path                 string `json:"path"`
322	Mount                string `json:"mount"`
323	Dev                  string `json:"dev"`
324	Total                string `json:"total"` // e.g. "930.7gb"`
325	TotalInBytes         int64  `json:"total_in_bytes"`
326	Free                 string `json:"free"` // e.g. "930.7gb"`
327	FreeInBytes          int64  `json:"free_in_bytes"`
328	Available            string `json:"available"` // e.g. "930.7gb"`
329	AvailableInBytes     int64  `json:"available_in_bytes"`
330	DiskReads            int64  `json:"disk_reads"`
331	DiskWrites           int64  `json:"disk_writes"`
332	DiskIOOp             int64  `json:"disk_io_op"`
333	DiskReadSize         string `json:"disk_read_size"` // e.g. "0b"`
334	DiskReadSizeInBytes  int64  `json:"disk_read_size_in_bytes"`
335	DiskWriteSize        string `json:"disk_write_size"` // e.g. "0b"`
336	DiskWriteSizeInBytes int64  `json:"disk_write_size_in_bytes"`
337	DiskIOSize           string `json:"disk_io_size"` // e.g. "0b"`
338	DiskIOSizeInBytes    int64  `json:"disk_io_size_in_bytes"`
339	DiskQueue            string `json:"disk_queue"`
340	DiskServiceTime      string `json:"disk_service_time"`
341}
342
343type ClusterStatsNodesPlugin struct {
344	Name        string `json:"name"`
345	Version     string `json:"version"`
346	Description string `json:"description"`
347	URL         string `json:"url"`
348	JVM         bool   `json:"jvm"`
349	Site        bool   `json:"site"`
350}
351