telegraf/plugins/jolokia/jolokia.go

176 lines
3.9 KiB
Go
Raw Normal View History

2015-10-28 08:13:22 +00:00
package jolokia
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"net/url"
2015-10-28 08:13:22 +00:00
"github.com/influxdb/telegraf/plugins"
)
type Server struct {
Name string
Host string
Username string
Password string
Port string
2015-10-28 08:13:22 +00:00
}
type Metric struct {
2015-10-29 13:48:39 +00:00
Name string
Jmx string
2015-10-28 08:13:22 +00:00
}
type JolokiaClient interface {
MakeRequest(req *http.Request) (*http.Response, error)
}
type JolokiaClientImpl struct {
client *http.Client
}
func (c JolokiaClientImpl) MakeRequest(req *http.Request) (*http.Response, error) {
return c.client.Do(req)
}
2015-10-28 08:13:22 +00:00
type Jolokia struct {
jClient JolokiaClient
2015-10-29 13:48:39 +00:00
Context string
Servers []Server
Metrics []Metric
2015-10-28 08:13:22 +00:00
}
func (j *Jolokia) SampleConfig() string {
2015-10-29 13:51:15 +00:00
return `
2015-11-12 16:52:10 +00:00
# This is the context root used to compose the jolokia url
2015-10-28 08:13:22 +00:00
context = "/jolokia/read"
2015-11-12 16:52:10 +00:00
# List of servers exposing jolokia read service
[[plugins.jolokia.servers]]
2015-11-03 21:00:23 +00:00
name = "stable"
host = "192.168.103.2"
port = "8180"
# username = "myuser"
# password = "mypassword"
2015-10-28 08:13:22 +00:00
2015-11-12 16:52:10 +00:00
# List of metrics collected on above servers
# Each metric consists in a name, a jmx path and either a pass or drop slice attributes
# This collect all heap memory usage metrics
[[plugins.jolokia.metrics]]
2015-11-03 21:00:23 +00:00
name = "heap_memory_usage"
jmx = "/java.lang:type=Memory/HeapMemoryUsage"
2015-10-28 08:13:22 +00:00
2015-11-03 21:00:23 +00:00
# This drops the 'committed' value from Eden space measurement
[[plugins.jolokia.metrics]]
2015-11-03 21:00:23 +00:00
name = "memory_eden"
jmx = "/java.lang:type=MemoryPool,name=PS Eden Space/Usage"
2015-10-28 08:13:22 +00:00
2015-11-12 16:52:10 +00:00
# This passes only DaemonThreadCount and ThreadCount
[[plugins.jolokia.metrics]]
2015-11-12 16:52:10 +00:00
name = "heap_threads"
2015-11-03 21:00:23 +00:00
jmx = "/java.lang:type=Threading"
2015-10-28 08:13:22 +00:00
`
}
func (j *Jolokia) Description() string {
return "Read JMX metrics through Jolokia"
}
func (j *Jolokia) getAttr(requestUrl *url.URL) (map[string]interface{}, error) {
// Create + send request
req, err := http.NewRequest("GET", requestUrl.String(), nil)
if err != nil {
return nil, err
}
2015-12-19 20:31:22 +00:00
defer req.Body.Close()
resp, err := j.jClient.MakeRequest(req)
2015-10-28 08:13:22 +00:00
if err != nil {
return nil, err
}
defer resp.Body.Close()
2015-10-29 13:48:39 +00:00
// Process response
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("Response from url \"%s\" has status code %d (%s), expected %d (%s)",
requestUrl,
resp.StatusCode,
http.StatusText(resp.StatusCode),
http.StatusOK,
http.StatusText(http.StatusOK))
return nil, err
}
// read body
body, err := ioutil.ReadAll(resp.Body)
2015-10-28 08:13:22 +00:00
if err != nil {
return nil, err
}
2015-10-29 13:48:39 +00:00
// Unmarshal json
var jsonOut map[string]interface{}
if err = json.Unmarshal([]byte(body), &jsonOut); err != nil {
return nil, errors.New("Error decoding JSON response")
}
2015-10-28 08:13:22 +00:00
2015-10-29 13:48:39 +00:00
return jsonOut, nil
2015-10-28 08:13:22 +00:00
}
func (j *Jolokia) Gather(acc plugins.Accumulator) error {
2015-10-29 13:48:39 +00:00
context := j.Context //"/jolokia/read"
servers := j.Servers
metrics := j.Metrics
2015-12-19 20:31:22 +00:00
tags := make(map[string]string)
2015-10-28 08:13:22 +00:00
2015-10-29 13:48:39 +00:00
for _, server := range servers {
2015-12-19 20:31:22 +00:00
tags["server"] = server.Name
tags["port"] = server.Port
tags["host"] = server.Host
fields := make(map[string]interface{})
2015-10-29 13:48:39 +00:00
for _, metric := range metrics {
2015-10-28 08:13:22 +00:00
2015-10-29 13:48:39 +00:00
measurement := metric.Name
jmxPath := metric.Jmx
2015-10-28 08:13:22 +00:00
// Prepare URL
requestUrl, err := url.Parse("http://" + server.Host + ":" +
server.Port + context + jmxPath)
if err != nil {
return err
}
if server.Username != "" || server.Password != "" {
requestUrl.User = url.UserPassword(server.Username, server.Password)
}
out, _ := j.getAttr(requestUrl)
2015-10-29 13:48:39 +00:00
if values, ok := out["value"]; ok {
2015-12-19 20:31:22 +00:00
switch t := values.(type) {
2015-10-29 13:48:39 +00:00
case map[string]interface{}:
2015-12-19 20:31:22 +00:00
for k, v := range t {
fields[measurement+"_"+k] = v
}
2015-10-29 13:48:39 +00:00
case interface{}:
2015-12-19 20:31:22 +00:00
fields[measurement] = t
2015-10-29 13:48:39 +00:00
}
} else {
2015-12-19 20:31:22 +00:00
fmt.Printf("Missing key 'value' in '%s' output response\n",
requestUrl.String())
2015-10-29 13:48:39 +00:00
}
}
2015-12-19 20:31:22 +00:00
acc.AddFields("jolokia", fields, tags)
2015-10-29 13:48:39 +00:00
}
return nil
2015-10-28 08:13:22 +00:00
}
func init() {
plugins.Add("jolokia", func() plugins.Plugin {
return &Jolokia{jClient: &JolokiaClientImpl{client: &http.Client{}}}
2015-10-28 08:13:22 +00:00
})
}