1// Copyright 2012-2015 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	"encoding/json"
9	"fmt"
10	"log"
11	"net/url"
12	"strings"
13	"time"
14
15	"gopkg.in/olivere/elastic.v2/uritemplates"
16)
17
18var (
19	_ = fmt.Print
20	_ = log.Print
21	_ = strings.Index
22	_ = uritemplates.Expand
23	_ = url.Parse
24)
25
26// NodesInfoService allows to retrieve one or more or all of the
27// cluster nodes information.
28// It is documented at http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/cluster-nodes-info.html.
29type NodesInfoService struct {
30	client       *Client
31	pretty       bool
32	nodeId       []string
33	metric       []string
34	flatSettings *bool
35	human        *bool
36}
37
38// NewNodesInfoService creates a new NodesInfoService.
39func NewNodesInfoService(client *Client) *NodesInfoService {
40	return &NodesInfoService{
41		client: client,
42		nodeId: []string{"_all"},
43		metric: []string{"_all"},
44	}
45}
46
47// NodeId is a list of node IDs or names to limit the returned information.
48// Use "_local" to return information from the node you're connecting to,
49// leave empty to get information from all nodes.
50func (s *NodesInfoService) NodeId(nodeId ...string) *NodesInfoService {
51	s.nodeId = make([]string, 0)
52	s.nodeId = append(s.nodeId, nodeId...)
53	return s
54}
55
56// Metric is a list of metrics you wish returned. Leave empty to return all.
57// Valid metrics are: settings, os, process, jvm, thread_pool, network,
58// transport, http, and plugins.
59func (s *NodesInfoService) Metric(metric ...string) *NodesInfoService {
60	s.metric = make([]string, 0)
61	s.metric = append(s.metric, metric...)
62	return s
63}
64
65// FlatSettings returns settings in flat format (default: false).
66func (s *NodesInfoService) FlatSettings(flatSettings bool) *NodesInfoService {
67	s.flatSettings = &flatSettings
68	return s
69}
70
71// Human indicates whether to return time and byte values in human-readable format.
72func (s *NodesInfoService) Human(human bool) *NodesInfoService {
73	s.human = &human
74	return s
75}
76
77// Pretty indicates whether to indent the returned JSON.
78func (s *NodesInfoService) Pretty(pretty bool) *NodesInfoService {
79	s.pretty = pretty
80	return s
81}
82
83// buildURL builds the URL for the operation.
84func (s *NodesInfoService) buildURL() (string, url.Values, error) {
85	// Build URL
86	path, err := uritemplates.Expand("/_nodes/{node_id}/{metric}", map[string]string{
87		"node_id": strings.Join(s.nodeId, ","),
88		"metric":  strings.Join(s.metric, ","),
89	})
90	if err != nil {
91		return "", url.Values{}, err
92	}
93
94	// Add query string parameters
95	params := url.Values{}
96	if s.flatSettings != nil {
97		params.Set("flat_settings", fmt.Sprintf("%v", *s.flatSettings))
98	}
99	if s.human != nil {
100		params.Set("human", fmt.Sprintf("%v", *s.human))
101	}
102	if s.pretty {
103		params.Set("pretty", "1")
104	}
105	return path, params, nil
106}
107
108// Validate checks if the operation is valid.
109func (s *NodesInfoService) Validate() error {
110	return nil
111}
112
113// Do executes the operation.
114func (s *NodesInfoService) Do() (*NodesInfoResponse, error) {
115	// Check pre-conditions
116	if err := s.Validate(); err != nil {
117		return nil, err
118	}
119
120	// Get URL for request
121	path, params, err := s.buildURL()
122	if err != nil {
123		return nil, err
124	}
125
126	// Get HTTP response
127	res, err := s.client.PerformRequest("GET", path, params, nil)
128	if err != nil {
129		return nil, err
130	}
131
132	// Return operation response
133	ret := new(NodesInfoResponse)
134	if err := json.Unmarshal(res.Body, ret); err != nil {
135		return nil, err
136	}
137	return ret, nil
138}
139
140// NodesInfoResponse is the response of NodesInfoService.Do.
141type NodesInfoResponse struct {
142	ClusterName string                    `json:"cluster_name"`
143	Nodes       map[string]*NodesInfoNode `json:"nodes"`
144}
145
146type NodesInfoNode struct {
147	// Name of the node, e.g. "Mister Fear"
148	Name string `json:"name"`
149	// TransportAddress, e.g. "inet[/127.0.0.1:9300]"
150	TransportAddress string `json:"transport_address"`
151	// Host is the host name, e.g. "macbookair"
152	Host string `json:"host"`
153	// IP is the IP address, e.g. "192.168.1.2"
154	IP string `json:"ip"`
155	// Version is the Elasticsearch version running on the node, e.g. "1.4.3"
156	Version string `json:"version"`
157	// Build is the Elasticsearch build, e.g. "36a29a7"
158	Build string `json:"build"`
159	// HTTPAddress, e.g. "inet[/127.0.0.1:9200]"
160	HTTPAddress string `json:"http_address"`
161	// HTTPSAddress, e.g. "inet[/127.0.0.1:9200]"
162	HTTPSAddress string `json:"https_address"`
163
164	// Settings of the node, e.g. paths and pidfile.
165	Settings map[string]interface{} `json:"settings"`
166
167	// OS information, e.g. CPU and memory.
168	OS *NodesInfoNodeOS `json:"os"`
169
170	// Process information, e.g. max file descriptors.
171	Process *NodesInfoNodeProcess `json:"process"`
172
173	// JVM information, e.g. VM version.
174	JVM *NodesInfoNodeProcess `json:"jvm"`
175
176	// ThreadPool information.
177	ThreadPool *NodesInfoNodeThreadPool `json:"thread_pool"`
178
179	// Network information.
180	Network *NodesInfoNodeNetwork `json:"network"`
181
182	// Network information.
183	Transport *NodesInfoNodeTransport `json:"transport"`
184
185	// HTTP information.
186	HTTP *NodesInfoNodeHTTP `json:"http"`
187
188	// Plugins information.
189	Plugins []*NodesInfoNodePlugin `json:"plugins"`
190}
191
192type NodesInfoNodeOS struct {
193	RefreshInterval         string `json:"refresh_interval"`           // e.g. 1s
194	RefreshIntervalInMillis int    `json:"refresh_interval_in_millis"` // e.g. 1000
195	AvailableProcessors     int    `json:"available_processors"`       // e.g. 4
196
197	// CPU information
198	CPU struct {
199		Vendor           string `json:"vendor"`              // e.g. Intel
200		Model            string `json:"model"`               // e.g. iMac15,1
201		MHz              int    `json:"mhz"`                 // e.g. 3500
202		TotalCores       int    `json:"total_cores"`         // e.g. 4
203		TotalSockets     int    `json:"total_sockets"`       // e.g. 4
204		CoresPerSocket   int    `json:"cores_per_socket"`    // e.g. 16
205		CacheSizeInBytes int    `json:"cache_size_in_bytes"` // e.g. 256
206	} `json:"cpu"`
207
208	// Mem information
209	Mem struct {
210		Total        string `json:"total"`          // e.g. 16gb
211		TotalInBytes int    `json:"total_in_bytes"` // e.g. 17179869184
212	} `json:"mem"`
213
214	// Swap information
215	Swap struct {
216		Total        string `json:"total"`          // e.g. 1gb
217		TotalInBytes int    `json:"total_in_bytes"` // e.g. 1073741824
218	} `json:"swap"`
219}
220
221type NodesInfoNodeProcess struct {
222	RefreshInterval         string `json:"refresh_interval"`           // e.g. 1s
223	RefreshIntervalInMillis int    `json:"refresh_interval_in_millis"` // e.g. 1000
224	ID                      int    `json:"id"`                         // process id, e.g. 87079
225	MaxFileDescriptors      int    `json:"max_file_descriptors"`       // e.g. 32768
226	Mlockall                bool   `json:"mlockall"`                   // e.g. false
227}
228
229type NodesInfoNodeJVM struct {
230	PID               int       `json:"pid"`        // process id, e.g. 87079
231	Version           string    `json:"version"`    // e.g. "1.8.0_25"
232	VMName            string    `json:"vm_name"`    // e.g. "Java HotSpot(TM) 64-Bit Server VM"
233	VMVersion         string    `json:"vm_version"` // e.g. "25.25-b02"
234	VMVendor          string    `json:"vm_vendor"`  // e.g. "Oracle Corporation"
235	StartTime         time.Time `json:"start_time"` // e.g. "2015-01-03T15:18:30.982Z"
236	StartTimeInMillis int64     `json:"start_time_in_millis"`
237
238	// Mem information
239	Mem struct {
240		HeapInit           string `json:"heap_init"` // e.g. 1gb
241		HeapInitInBytes    int    `json:"heap_init_in_bytes"`
242		HeapMax            string `json:"heap_max"` // e.g. 4gb
243		HeapMaxInBytes     int    `json:"heap_max_in_bytes"`
244		NonHeapInit        string `json:"non_heap_init"` // e.g. 2.4mb
245		NonHeapInitInBytes int    `json:"non_heap_init_in_bytes"`
246		NonHeapMax         string `json:"non_heap_max"` // e.g. 0b
247		NonHeapMaxInBytes  int    `json:"non_heap_max_in_bytes"`
248		DirectMax          string `json:"direct_max"` // e.g. 4gb
249		DirectMaxInBytes   int    `json:"direct_max_in_bytes"`
250	} `json:"mem"`
251
252	GCCollectors []string `json:"gc_collectors"` // e.g. ["ParNew"]
253	MemoryPools  []string `json:"memory_pools"`  // e.g. ["Code Cache", "Metaspace"]
254}
255
256type NodesInfoNodeThreadPool struct {
257	Percolate  *NodesInfoNodeThreadPoolSection `json:"percolate"`
258	Bench      *NodesInfoNodeThreadPoolSection `json:"bench"`
259	Listener   *NodesInfoNodeThreadPoolSection `json:"listener"`
260	Index      *NodesInfoNodeThreadPoolSection `json:"index"`
261	Refresh    *NodesInfoNodeThreadPoolSection `json:"refresh"`
262	Suggest    *NodesInfoNodeThreadPoolSection `json:"suggest"`
263	Generic    *NodesInfoNodeThreadPoolSection `json:"generic"`
264	Warmer     *NodesInfoNodeThreadPoolSection `json:"warmer"`
265	Search     *NodesInfoNodeThreadPoolSection `json:"search"`
266	Flush      *NodesInfoNodeThreadPoolSection `json:"flush"`
267	Optimize   *NodesInfoNodeThreadPoolSection `json:"optimize"`
268	Management *NodesInfoNodeThreadPoolSection `json:"management"`
269	Get        *NodesInfoNodeThreadPoolSection `json:"get"`
270	Merge      *NodesInfoNodeThreadPoolSection `json:"merge"`
271	Bulk       *NodesInfoNodeThreadPoolSection `json:"bulk"`
272	Snapshot   *NodesInfoNodeThreadPoolSection `json:"snapshot"`
273}
274
275type NodesInfoNodeThreadPoolSection struct {
276	Type      string      `json:"type"`       // e.g. fixed
277	Min       int         `json:"min"`        // e.g. 4
278	Max       int         `json:"max"`        // e.g. 4
279	KeepAlive string      `json:"keep_alive"` // e.g. "5m"
280	QueueSize interface{} `json:"queue_size"` // e.g. "1k" or -1
281}
282
283type NodesInfoNodeNetwork struct {
284	RefreshInterval         string `json:"refresh_interval"`           // e.g. 1s
285	RefreshIntervalInMillis int    `json:"refresh_interval_in_millis"` // e.g. 1000
286	PrimaryInterface        struct {
287		Address    string `json:"address"`     // e.g. 192.168.1.2
288		Name       string `json:"name"`        // e.g. en0
289		MACAddress string `json:"mac_address"` // e.g. 11:22:33:44:55:66
290	} `json:"primary_interface"`
291}
292
293type NodesInfoNodeTransport struct {
294	BoundAddress   string `json:"bound_address"`   // e.g. inet[/127.0.0.1:9300]
295	PublishAddress string `json:"publish_address"` // e.g. inet[/127.0.0.1:9300]
296}
297
298type NodesInfoNodeHTTP struct {
299	BoundAddress            string `json:"bound_address"`      // e.g. inet[/127.0.0.1:9300]
300	PublishAddress          string `json:"publish_address"`    // e.g. inet[/127.0.0.1:9300]
301	MaxContentLength        string `json:"max_content_length"` // e.g. "100mb"
302	MaxContentLengthInBytes int64  `json:"max_content_length_in_bytes"`
303}
304
305type NodesInfoNodePlugin struct {
306	Name        string `json:"name"`
307	Description string `json:"description"`
308	Site        bool   `json:"site"`
309	JVM         bool   `json:"jvm"`
310	URL         string `json:"url"` // e.g. /_plugin/dummy/
311}
312