This commit is contained in:
Vladimir Dementyev 2015-10-24 00:29:45 +00:00
commit 33d4f56d9c
3 changed files with 123 additions and 3 deletions

View File

@ -0,0 +1,69 @@
# HTTP JSON Plugin
The httpjson plugin can collect data from remote URLs which respond with JSON. Then it flattens JSON and finds all numeric values, treating them as floats.
For example, if you have a service called _mycollector_, which has HTTP endpoint for gathering stats http://my.service.com/_stats:
```
[[httpjson.services]]
name = "mycollector"
servers = [
"http://my.service.com/_stats"
]
# HTTP method to use (case-sensitive)
method = "GET"
```
The name is used as a prefix for the measurements.
The `method` specifies HTTP method to use for requests.
You can specify which keys from server response should be considered as tags:
```
[[httpjson.services]]
...
tagKeys = [
"role",
"version"
]
```
**NOTE**: tag values should be strings.
You can also specify additional request parameters for the service:
```
[[httpjson.services]]
...
[httpjson.services.parameters]
event_type = "cpu_spike"
threshold = "0.75"
```
# Sample
Let's say that we have a service named "mycollector", which responds with:
```json
{
"a": 0.5,
"b": {
"c": "some text",
"d": 0.1,
"e": 5
}
}
```
The collected metrics will be:
```
httpjson_mycollector_a value=0.5
httpjson_mycollector_b_d value=0.1
httpjson_mycollector_b_e value=5
```

View File

@ -22,6 +22,7 @@ type Service struct {
Name string
Servers []string
Method string
TagKeys []string
Parameters map[string]string
}
@ -61,6 +62,12 @@ var sampleConfig = `
# HTTP method to use (case-sensitive)
method = "GET"
# List of tag names to extract from server response
# tagKeys = [
# "my_tag_1",
# "my_tag_2"
# ]
# HTTP parameters (all values must be strings)
[httpjson.services.parameters]
event_type = "cpu_spike"
@ -126,7 +133,7 @@ func (h *HttpJson) gatherServer(acc plugins.Accumulator, service Service, server
return err
}
var jsonOut interface{}
var jsonOut map[string]interface{}
if err = json.Unmarshal([]byte(resp), &jsonOut); err != nil {
return errors.New("Error decoding JSON response")
}
@ -135,6 +142,14 @@ func (h *HttpJson) gatherServer(acc plugins.Accumulator, service Service, server
"server": serverURL,
}
for _, tag := range service.TagKeys {
switch v := jsonOut[tag].(type) {
case string:
tags[tag] = v
}
delete(jsonOut, tag)
}
processResponse(acc, service.Name, tags, jsonOut)
return nil
}

View File

@ -28,6 +28,13 @@ const validJSON = `
}
}`
const validJSONTags = `
{
"value": 15,
"role": "master",
"build": "123"
}`
const invalidJSON = "I don't think this is JSON"
const empty = ""
@ -87,8 +94,8 @@ func genMockHttpJson(response string, statusCode int) *HttpJson {
},
Service{
Servers: []string{
"http://server1.example.com/metrics/",
"http://server2.example.com/metrics/",
"http://server3.example.com/metrics/",
"http://server4.example.com/metrics/",
},
Name: "other_webapp",
Method: "POST",
@ -96,6 +103,10 @@ func genMockHttpJson(response string, statusCode int) *HttpJson {
"httpParam1": "12",
"httpParam2": "the second parameter",
},
TagKeys: []string{
"role",
"build",
},
},
},
}
@ -185,3 +196,28 @@ func TestHttpJsonEmptyResponse(t *testing.T) {
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 4)
assert.Equal(t, 0, len(acc.Points))
}
// Test that the proper values are ignored or collected
func TestHttpJson200Tags(t *testing.T) {
httpjson := genMockHttpJson(validJSONTags, 200)
var acc testutil.Accumulator
err := httpjson.Gather(&acc)
require.NoError(t, err)
assert.Equal(t, 4, len(acc.Points))
for _, service := range httpjson.Services {
if service.Name == "other_webapp" {
for _, srv := range service.Servers {
require.NoError(t,
acc.ValidateTaggedValue(
fmt.Sprintf("%s_value", service.Name),
15.0,
map[string]string{"server": srv, "role": "master", "build": "123"},
),
)
}
}
}
}