Skip to content

Commit

Permalink
Add response time to httpjson plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
titilambert committed Jan 2, 2016
1 parent 069cb97 commit 6273b0a
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 98 deletions.
2 changes: 1 addition & 1 deletion internal/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func (f *JSONFlattener) FlattenJSON(
}
case float64:
f.Fields[fieldname] = t
case bool, string, []interface{}:
case nil, bool, string, []interface{}:
// ignored types
return nil
default:
Expand Down
27 changes: 17 additions & 10 deletions plugins/httpjson/httpjson.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/url"
"strings"
"sync"
"time"

"github.com/influxdb/telegraf/internal"
"github.com/influxdb/telegraf/plugins"
Expand Down Expand Up @@ -119,7 +120,8 @@ func (h *HttpJson) gatherServer(
acc plugins.Accumulator,
serverURL string,
) error {
resp, err := h.sendRequest(serverURL)
resp, responseTime, err := h.sendRequest(serverURL)

if err != nil {
return err
}
Expand All @@ -141,6 +143,9 @@ func (h *HttpJson) gatherServer(
delete(jsonOut, tag)
}

if responseTime >= 0 {
jsonOut["response_time"] = responseTime
}
f := internal.JSONFlattener{}
err = f.FlattenJSON("", jsonOut)
if err != nil {
Expand All @@ -153,7 +158,7 @@ func (h *HttpJson) gatherServer(
} else {
msrmnt_name = "httpjson_" + h.Name
}
acc.AddFields(msrmnt_name, f.Fields, nil)
acc.AddFields(msrmnt_name, f.Fields, tags)
return nil
}

Expand All @@ -164,11 +169,11 @@ func (h *HttpJson) gatherServer(
// Returns:
// string: body of the response
// error : Any error that may have occurred
func (h *HttpJson) sendRequest(serverURL string) (string, error) {
func (h *HttpJson) sendRequest(serverURL string) (string, float64, error) {
// Prepare URL
requestURL, err := url.Parse(serverURL)
if err != nil {
return "", fmt.Errorf("Invalid server URL \"%s\"", serverURL)
return "", -1, fmt.Errorf("Invalid server URL \"%s\"", serverURL)
}

params := url.Values{}
Expand All @@ -180,19 +185,21 @@ func (h *HttpJson) sendRequest(serverURL string) (string, error) {
// Create + send request
req, err := http.NewRequest(h.Method, requestURL.String(), nil)
if err != nil {
return "", err
return "", -1, err
}

start := time.Now()
resp, err := h.client.MakeRequest(req)
if err != nil {
return "", err
return "", -1, err
}
defer resp.Body.Close()

defer resp.Body.Close()
responseTime := time.Since(start).Seconds()

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return string(body), err
return string(body), responseTime, err
}

// Process response
Expand All @@ -203,10 +210,10 @@ func (h *HttpJson) sendRequest(serverURL string) (string, error) {
http.StatusText(resp.StatusCode),
http.StatusOK,
http.StatusText(http.StatusOK))
return string(body), err
return string(body), responseTime, err
}

return string(body), err
return string(body), responseTime, err
}

func init() {
Expand Down
188 changes: 101 additions & 87 deletions plugins/httpjson/httpjson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
const validJSON = `
{
"parent": {
"child": 3,
"child": 3.0,
"ignored_child": "hi"
},
"ignored_null": null,
Expand Down Expand Up @@ -76,65 +76,64 @@ func (c mockHTTPClient) MakeRequest(req *http.Request) (*http.Response, error) {
//
// Returns:
// *HttpJson: Pointer to an HttpJson object that uses the generated mock HTTP client
func genMockHttpJson(response string, statusCode int) *HttpJson {
return &HttpJson{
func genMockHttpJsons(response string, statusCode int) []*HttpJson {
httpjson1 := &HttpJson{
client: mockHTTPClient{responseBody: response, statusCode: statusCode},
Services: []Service{
Service{
Servers: []string{
"http://server1.example.com/metrics/",
"http://server2.example.com/metrics/",
},
Name: "my_webapp",
Method: "GET",
Parameters: map[string]string{
"httpParam1": "12",
"httpParam2": "the second parameter",
},
},
Service{
Servers: []string{
"http://server3.example.com/metrics/",
"http://server4.example.com/metrics/",
},
Name: "other_webapp",
Method: "POST",
Parameters: map[string]string{
"httpParam1": "12",
"httpParam2": "the second parameter",
},
TagKeys: []string{
"role",
"build",
},
},
Servers: []string{
"http://server1.example.com/metrics/",
"http://server2.example.com/metrics/",
},
Name: "my_webapp",
Method: "GET",
Parameters: map[string]string{
"httpParam1": "12",
"httpParam2": "the second parameter",
},
}
httpjson2 := &HttpJson{
client: mockHTTPClient{responseBody: response, statusCode: statusCode},
Servers: []string{
"http://server3.example.com/metrics/",
"http://server4.example.com/metrics/",
},
Name: "other_webapp",
Method: "POST",
Parameters: map[string]string{
"httpParam1": "12",
"httpParam2": "the second parameter",
},
TagKeys: []string{
"role",
"build",
},
}
httpjsons := []*HttpJson{httpjson1, httpjson2}
return httpjsons
}

// Test that the proper values are ignored or collected
func TestHttpJson200(t *testing.T) {
httpjson := genMockHttpJson(validJSON, 200)

var acc testutil.Accumulator
err := httpjson.Gather(&acc)
require.NoError(t, err)

assert.Equal(t, 8, len(acc.Points))

for _, service := range httpjson.Services {
for _, srv := range service.Servers {
require.NoError(t,
acc.ValidateTaggedValue(
fmt.Sprintf("%s_parent_child", service.Name),
3.0,
map[string]string{"server": srv},
),
)
httpjsons := genMockHttpJsons(validJSON, 200)
for _, httpjson := range httpjsons {
var acc testutil.Accumulator
err := httpjson.Gather(&acc)
require.NoError(t, err)

assert.Equal(t, 2, len(acc.Points))

for _, srv := range httpjson.Servers {
// Override response time
for _, p := range acc.Points {
p.Fields["response_time"] = 1.0
}
require.NoError(t,
acc.ValidateTaggedValue(
fmt.Sprintf("%s_integer", service.Name),
4.0,
acc.ValidateTaggedFieldsValue(
fmt.Sprintf("httpjson_%s", httpjson.Name),
map[string]interface{}{
"parent_child": 3.0,
"integer": 4.0,
"response_time": 1.0,
},
map[string]string{"server": srv},
),
)
Expand All @@ -144,80 +143,95 @@ func TestHttpJson200(t *testing.T) {

// Test response to HTTP 500
func TestHttpJson500(t *testing.T) {
httpjson := genMockHttpJson(validJSON, 500)
httpjsons := genMockHttpJsons(validJSON, 500)

var acc testutil.Accumulator
err := httpjson.Gather(&acc)
for _, httpjson := range httpjsons {
err := httpjson.Gather(&acc)

assert.NotNil(t, err)
// 4 error lines for (2 urls) * (2 services)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 4)
assert.NotNil(t, err)
// 4 error lines for (2 urls) * (2 services)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 2)
}
assert.Equal(t, 0, len(acc.Points))
}

// Test response to HTTP 405
func TestHttpJsonBadMethod(t *testing.T) {
httpjson := genMockHttpJson(validJSON, 200)
httpjson.Services[0].Method = "NOT_A_REAL_METHOD"
httpjsons := genMockHttpJsons(validJSON, 200)

var acc testutil.Accumulator
err := httpjson.Gather(&acc)

assert.NotNil(t, err)
// 2 error lines for (2 urls) * (1 falied service)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 2)
for _, httpjson := range httpjsons {
httpjson.Method = "NOT_A_REAL_METHOD"
err := httpjson.Gather(&acc)

assert.NotNil(t, err)
// 2 error lines for (2 urls) * (1 falied service)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 2)
}
// (2 measurements) * (2 servers) * (1 successful service)
assert.Equal(t, 4, len(acc.Points))
assert.Equal(t, 0, len(acc.Points))
}

// Test response to malformed JSON
func TestHttpJsonBadJson(t *testing.T) {
httpjson := genMockHttpJson(invalidJSON, 200)
httpjsons := genMockHttpJsons(invalidJSON, 200)

var acc testutil.Accumulator
err := httpjson.Gather(&acc)
for _, httpjson := range httpjsons {
err := httpjson.Gather(&acc)

assert.NotNil(t, err)
// 4 error lines for (2 urls) * (2 services)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 4)
assert.NotNil(t, err)
// 4 error lines for (2 urls) * (2 services)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 2)
}
assert.Equal(t, 0, len(acc.Points))
}

// Test response to empty string as response objectgT
func TestHttpJsonEmptyResponse(t *testing.T) {
httpjson := genMockHttpJson(empty, 200)
httpjsons := genMockHttpJsons(empty, 200)

var acc testutil.Accumulator
err := httpjson.Gather(&acc)
for _, httpjson := range httpjsons {
err := httpjson.Gather(&acc)

assert.NotNil(t, err)
// 4 error lines for (2 urls) * (2 services)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 4)
assert.NotNil(t, err)
// 4 error lines for (2 urls) * (2 services)
assert.Equal(t, len(strings.Split(err.Error(), "\n")), 2)
}
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)
httpjsons := genMockHttpJsons(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 {
for _, httpjson := range httpjsons {
err := httpjson.Gather(&acc)
require.NoError(t, err)

if httpjson.Name == "other_webapp" {
assert.Equal(t, 4, len(acc.Points))
for _, srv := range httpjson.Servers {
// Override response time
for _, p := range acc.Points {
p.Fields["response_time"] = 1.0
}
require.NoError(t,
acc.ValidateTaggedValue(
fmt.Sprintf("%s_value", service.Name),
15.0,
acc.ValidateTaggedFieldsValue(
fmt.Sprintf("httpjson_%s", httpjson.Name),
map[string]interface{}{
"value": 15.0,
"response_time": 1.0,
},
map[string]string{"server": srv, "role": "master", "build": "123"},
),
)
}
} else {
assert.Equal(t, 2, len(acc.Points))
}
}
}

0 comments on commit 6273b0a

Please sign in to comment.