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	"github.com/olivere/elastic/uritemplates"
14)
15
16// ClusterStatsService is documented at
17// https://www.elastic.co/guide/en/elasticsearch/reference/6.7/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", "true")
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, PerformRequestOptions{
112		Method: "GET",
113		Path:   path,
114		Params: params,
115	})
116	if err != nil {
117		return nil, err
118	}
119
120	// Return operation response
121	ret := new(ClusterStatsResponse)
122	if err := s.client.decoder.Decode(res.Body, ret); err != nil {
123		return nil, err
124	}
125	return ret, nil
126}
127
128// ClusterStatsResponse is the response of ClusterStatsService.Do.
129type ClusterStatsResponse struct {
130	Timestamp   int64                `json:"timestamp"`
131	ClusterName string               `json:"cluster_name"`
132	ClusterUUID string               `json:"cluster_uuid"`
133	Status      string               `json:"status,omitempty"` // e.g. green
134	Indices     *ClusterStatsIndices `json:"indices"`
135	Nodes       *ClusterStatsNodes   `json:"nodes"`
136}
137
138type ClusterStatsIndices struct {
139	Count      int                            `json:"count"` // number of indices
140	Shards     *ClusterStatsIndicesShards     `json:"shards"`
141	Docs       *ClusterStatsIndicesDocs       `json:"docs"`
142	Store      *ClusterStatsIndicesStore      `json:"store"`
143	FieldData  *ClusterStatsIndicesFieldData  `json:"fielddata"`
144	QueryCache *ClusterStatsIndicesQueryCache `json:"query_cache"`
145	Completion *ClusterStatsIndicesCompletion `json:"completion"`
146	Segments   *ClusterStatsIndicesSegments   `json:"segments"`
147}
148
149type ClusterStatsIndicesShards struct {
150	Total       int                             `json:"total"`
151	Primaries   int                             `json:"primaries"`
152	Replication float64                         `json:"replication"`
153	Index       *ClusterStatsIndicesShardsIndex `json:"index"`
154}
155
156type ClusterStatsIndicesShardsIndex struct {
157	Shards      *ClusterStatsIndicesShardsIndexIntMinMax     `json:"shards"`
158	Primaries   *ClusterStatsIndicesShardsIndexIntMinMax     `json:"primaries"`
159	Replication *ClusterStatsIndicesShardsIndexFloat64MinMax `json:"replication"`
160}
161
162type ClusterStatsIndicesShardsIndexIntMinMax struct {
163	Min int     `json:"min"`
164	Max int     `json:"max"`
165	Avg float64 `json:"avg"`
166}
167
168type ClusterStatsIndicesShardsIndexFloat64MinMax struct {
169	Min float64 `json:"min"`
170	Max float64 `json:"max"`
171	Avg float64 `json:"avg"`
172}
173
174type ClusterStatsIndicesDocs struct {
175	Count   int `json:"count"`
176	Deleted int `json:"deleted"`
177}
178
179type ClusterStatsIndicesStore struct {
180	Size        string `json:"size"` // e.g. "5.3gb"
181	SizeInBytes int64  `json:"size_in_bytes"`
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,omitempty"`
192}
193
194type ClusterStatsIndicesQueryCache struct {
195	MemorySize        string `json:"memory_size"` // e.g. "61.3kb"
196	MemorySizeInBytes int64  `json:"memory_size_in_bytes"`
197	TotalCount        int64  `json:"total_count"`
198	HitCount          int64  `json:"hit_count"`
199	MissCount         int64  `json:"miss_count"`
200	CacheSize         int64  `json:"cache_size"`
201	CacheCount        int64  `json:"cache_count"`
202	Evictions         int64  `json:"evictions"`
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,omitempty"`
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	TermsMemory               string                                      `json:"terms_memory"` // e.g. "61.3kb"
219	TermsMemoryInBytes        int64                                       `json:"terms_memory_in_bytes"`
220	StoredFieldsMemory        string                                      `json:"stored_fields_memory"` // e.g. "61.3kb"
221	StoredFieldsMemoryInBytes int64                                       `json:"stored_fields_memory_in_bytes"`
222	NormsMemory               string                                      `json:"norms_memory"` // e.g. "61.3kb"
223	NormsMemoryInBytes        int64                                       `json:"norms_memory_in_bytes"`
224	PointsMemory              string                                      `json:"points_memory"` // e.g. "61.3kb"
225	PointsMemoryInBytes       int64                                       `json:"points_memory_in_bytes"`
226	DocValuesMemory           string                                      `json:"doc_values_memory"` // e.g. "61.3kb"
227	DocValuesMemoryInBytes    int64                                       `json:"doc_values_memory_in_bytes"`
228	IndexWriterMemory         string                                      `json:"index_writer_memory"` // e.g. "61.3kb"
229	IndexWriterMemoryInBytes  int64                                       `json:"index_writer_memory_in_bytes"`
230	VersionMapMemory          string                                      `json:"version_map_memory"` // e.g. "61.3kb"
231	VersionMapMemoryInBytes   int64                                       `json:"version_map_memory_in_bytes"`
232	FixedBitSet               string                                      `json:"fixed_bit_set"` // e.g. "61.3kb"
233	FixedBitSetInBytes        int64                                       `json:"fixed_bit_set_memory_in_bytes"`
234	FileSizes                 map[string]*ClusterStatsIndicesSegmentsFile `json:"file_sizes"`
235}
236
237type ClusterStatsIndicesSegmentsFile struct {
238	Size        string `json:"size"` // e.g. "61.3kb"
239	SizeInBytes int64  `json:"size_in_bytes"`
240	Description string `json:"description,omitempty"`
241}
242
243// ---
244
245type ClusterStatsNodes struct {
246	Count    *ClusterStatsNodesCount        `json:"count"`
247	Versions []string                       `json:"versions"`
248	OS       *ClusterStatsNodesOsStats      `json:"os"`
249	Process  *ClusterStatsNodesProcessStats `json:"process"`
250	JVM      *ClusterStatsNodesJvmStats     `json:"jvm"`
251	FS       *ClusterStatsNodesFsStats      `json:"fs"`
252	Plugins  []*ClusterStatsNodesPlugin     `json:"plugins"`
253}
254
255type ClusterStatsNodesCount struct {
256	Total            int `json:"total"`
257	Data             int `json:"data"`
258	CoordinatingOnly int `json:"coordinating_only"`
259	Master           int `json:"master"`
260	Ingest           int `json:"ingest"`
261}
262
263type ClusterStatsNodesOsStats struct {
264	AvailableProcessors int                            `json:"available_processors"`
265	Mem                 *ClusterStatsNodesOsStatsMem   `json:"mem"`
266	CPU                 []*ClusterStatsNodesOsStatsCPU `json:"cpu"`
267}
268
269type ClusterStatsNodesOsStatsMem struct {
270	Total        string `json:"total"` // e.g. "16gb"
271	TotalInBytes int64  `json:"total_in_bytes"`
272}
273
274type ClusterStatsNodesOsStatsCPU struct {
275	Vendor           string `json:"vendor"`
276	Model            string `json:"model"`
277	MHz              int    `json:"mhz"`
278	TotalCores       int    `json:"total_cores"`
279	TotalSockets     int    `json:"total_sockets"`
280	CoresPerSocket   int    `json:"cores_per_socket"`
281	CacheSize        string `json:"cache_size"` // e.g. "256b"
282	CacheSizeInBytes int64  `json:"cache_size_in_bytes"`
283	Count            int    `json:"count"`
284}
285
286type ClusterStatsNodesProcessStats struct {
287	CPU                 *ClusterStatsNodesProcessStatsCPU                 `json:"cpu"`
288	OpenFileDescriptors *ClusterStatsNodesProcessStatsOpenFileDescriptors `json:"open_file_descriptors"`
289}
290
291type ClusterStatsNodesProcessStatsCPU struct {
292	Percent float64 `json:"percent"`
293}
294
295type ClusterStatsNodesProcessStatsOpenFileDescriptors struct {
296	Min int64 `json:"min"`
297	Max int64 `json:"max"`
298	Avg int64 `json:"avg"`
299}
300
301type ClusterStatsNodesJvmStats struct {
302	MaxUptime         string                              `json:"max_uptime"` // e.g. "5h"
303	MaxUptimeInMillis int64                               `json:"max_uptime_in_millis"`
304	Versions          []*ClusterStatsNodesJvmStatsVersion `json:"versions"`
305	Mem               *ClusterStatsNodesJvmStatsMem       `json:"mem"`
306	Threads           int64                               `json:"threads"`
307}
308
309type ClusterStatsNodesJvmStatsVersion struct {
310	Version   string `json:"version"`    // e.g. "1.8.0_45"
311	VMName    string `json:"vm_name"`    // e.g. "Java HotSpot(TM) 64-Bit Server VM"
312	VMVersion string `json:"vm_version"` // e.g. "25.45-b02"
313	VMVendor  string `json:"vm_vendor"`  // e.g. "Oracle Corporation"
314	Count     int    `json:"count"`
315}
316
317type ClusterStatsNodesJvmStatsMem struct {
318	HeapUsed        string `json:"heap_used"`
319	HeapUsedInBytes int64  `json:"heap_used_in_bytes"`
320	HeapMax         string `json:"heap_max"`
321	HeapMaxInBytes  int64  `json:"heap_max_in_bytes"`
322}
323
324type ClusterStatsNodesFsStats struct {
325	Path                 string `json:"path"`
326	Mount                string `json:"mount"`
327	Dev                  string `json:"dev"`
328	Total                string `json:"total"` // e.g. "930.7gb"`
329	TotalInBytes         int64  `json:"total_in_bytes"`
330	Free                 string `json:"free"` // e.g. "930.7gb"`
331	FreeInBytes          int64  `json:"free_in_bytes"`
332	Available            string `json:"available"` // e.g. "930.7gb"`
333	AvailableInBytes     int64  `json:"available_in_bytes"`
334	DiskReads            int64  `json:"disk_reads"`
335	DiskWrites           int64  `json:"disk_writes"`
336	DiskIOOp             int64  `json:"disk_io_op"`
337	DiskReadSize         string `json:"disk_read_size"` // e.g. "0b"`
338	DiskReadSizeInBytes  int64  `json:"disk_read_size_in_bytes"`
339	DiskWriteSize        string `json:"disk_write_size"` // e.g. "0b"`
340	DiskWriteSizeInBytes int64  `json:"disk_write_size_in_bytes"`
341	DiskIOSize           string `json:"disk_io_size"` // e.g. "0b"`
342	DiskIOSizeInBytes    int64  `json:"disk_io_size_in_bytes"`
343	DiskQueue            string `json:"disk_queue"`
344	DiskServiceTime      string `json:"disk_service_time"`
345}
346
347type ClusterStatsNodesPlugin struct {
348	Name        string `json:"name"`
349	Version     string `json:"version"`
350	Description string `json:"description"`
351	URL         string `json:"url"`
352	JVM         bool   `json:"jvm"`
353	Site        bool   `json:"site"`
354}
355