diff --git a/config/testdata/telegraf-agent.toml b/config/testdata/telegraf-agent.toml index a0add155b..bac0e4586 100644 --- a/config/testdata/telegraf-agent.toml +++ b/config/testdata/telegraf-agent.toml @@ -80,7 +80,7 @@ # Whether to report total system cpu stats or not totalcpu = true # Comment this line if you want the raw CPU time metrics - drop = ["cpu_time"] + fieldexclude = ["cpu_time"] # Read metrics about disk usage by mount point [[inputs.diskio]] @@ -121,23 +121,20 @@ # servers = ["socket:/run/haproxy/admin.sock"] # Read flattened metrics from one or more JSON HTTP endpoints -[[inputs.httpjson]] +[[inputs.http]] # a name for the service being polled - name = "webserver_stats" + name_override = "webserver_stats" # URL of each server in the service's cluster - servers = [ + urls = [ "http://localhost:9999/stats/", "http://localhost:9998/stats/", ] # HTTP method to use (case-sensitive) - method = "GET" + # method = "GET" - # HTTP parameters (all values must be strings) - [httpjson.parameters] - event_type = "cpu_spike" - threshold = "0.75" + data_format = "json" # Read metrics about disk IO by device [[inputs.diskio]] diff --git a/plugins/inputs/all/httpjson.go b/plugins/inputs/all/httpjson.go deleted file mode 100644 index fd67f20bb..000000000 --- a/plugins/inputs/all/httpjson.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build !custom || inputs || inputs.httpjson - -package all - -import _ "github.com/influxdata/telegraf/plugins/inputs/httpjson" // register plugin diff --git a/plugins/inputs/httpjson/README.md b/plugins/inputs/httpjson/README.md deleted file mode 100644 index a4e2e85d8..000000000 --- a/plugins/inputs/httpjson/README.md +++ /dev/null @@ -1,163 +0,0 @@ -# HTTP JSON Input Plugin - -**DEPRECATED in Telegraf v1.6: Use [HTTP input plugin][] as replacement** - -The httpjson plugin collects data from HTTP URLs which respond with JSON. It -flattens the JSON and finds all numeric values, treating them as floats. - -## Global configuration options - -In addition to the plugin-specific configuration settings, plugins support -additional global and plugin configuration settings. These settings are used to -modify metrics, tags, and field or create aliases and configure ordering, etc. -See the [CONFIGURATION.md][CONFIGURATION.md] for more details. - -[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins - -## Configuration - -```toml @sample.conf -# Read flattened metrics from one or more JSON HTTP endpoints -[[inputs.httpjson]] - ## NOTE This plugin only reads numerical measurements, strings and booleans - ## will be ignored. - - ## Name for the service being polled. Will be appended to the name of the - ## measurement e.g. "httpjson_webserver_stats". - ## - ## Deprecated (1.3.0): Use name_override, name_suffix, name_prefix instead. - name = "webserver_stats" - - ## URL of each server in the service's cluster - servers = [ - "http://localhost:9999/stats/", - "http://localhost:9998/stats/", - ] - ## Set response_timeout (default 5 seconds) - response_timeout = "5s" - - ## HTTP method to use: GET or POST (case-sensitive) - method = "GET" - - ## Tags to extract from top-level of JSON server response. - # tag_keys = [ - # "my_tag_1", - # "my_tag_2" - # ] - - ## Optional TLS Config - # tls_ca = "/etc/telegraf/ca.pem" - # tls_cert = "/etc/telegraf/cert.pem" - # tls_key = "/etc/telegraf/key.pem" - ## Use TLS but skip chain & host verification - # insecure_skip_verify = false - - ## HTTP Request Parameters (all values must be strings). For "GET" requests, data - ## will be included in the query. For "POST" requests, data will be included - ## in the request body as "x-www-form-urlencoded". - # [inputs.httpjson.parameters] - # event_type = "cpu_spike" - # threshold = "0.75" - - ## HTTP Request Headers (all values must be strings). - # [inputs.httpjson.headers] - # X-Auth-Token = "my-xauth-token" - # apiVersion = "v1" -``` - -## Metrics - -### Measurements & Fields - -- httpjson - - response_time (float): Response time in seconds - -Additional fields are dependant on the response of the remote service being -polled. - -### Tags - -- All measurements have the following tags: - - server: HTTP origin as defined in configuration as `servers`. - -Any top level keys listed under `tag_keys` in the configuration are added as -tags. Top level keys are defined as keys in the root level of the object in a -single object response, or in the root level of each object within an array of -objects. - -## Example Output - -This plugin understands responses containing a single JSON object, or a JSON -Array of Objects. - -**Object Output:** - -Given the following response body: - -```json -{ - "a": 0.5, - "b": { - "c": "some text", - "d": 0.1, - "e": 5 - }, - "service": "service01" -} -``` - -The following metric is produced: - -```text -httpjson,server=http://localhost:9999/stats/ b_d=0.1,a=0.5,b_e=5,response_time=0.001 -``` - -Note that only numerical values are extracted and the type is float. - -If `tag_keys` is included in the configuration: - -```toml -[[inputs.httpjson]] - tag_keys = ["service"] -``` - -Then the `service` tag will also be added: - -```text -httpjson,server=http://localhost:9999/stats/,service=service01 b_d=0.1,a=0.5,b_e=5,response_time=0.001 -``` - -**Array Output:** - -If the service returns an array of objects, one metric is be created for each -object: - -```json -[ - { - "service": "service01", - "a": 0.5, - "b": { - "c": "some text", - "d": 0.1, - "e": 5 - } - }, - { - "service": "service02", - "a": 0.6, - "b": { - "c": "some text", - "d": 0.2, - "e": 6 - } - } -] -``` - -```text -httpjson,server=http://localhost:9999/stats/,service=service01 a=0.5,b_d=0.1,b_e=5,response_time=0.003 -httpjson,server=http://localhost:9999/stats/,service=service02 a=0.6,b_d=0.2,b_e=6,response_time=0.003 -``` - -[HTTP input plugin]: ../http/README.md diff --git a/plugins/inputs/httpjson/httpjson.go b/plugins/inputs/httpjson/httpjson.go deleted file mode 100644 index 8ddbfb4af..000000000 --- a/plugins/inputs/httpjson/httpjson.go +++ /dev/null @@ -1,250 +0,0 @@ -//go:generate ../../../tools/readme_config_includer/generator -package httpjson - -import ( - "bytes" - _ "embed" - "fmt" - "io" - "net/http" - "net/url" - "strings" - "sync" - "time" - - "github.com/influxdata/telegraf" - "github.com/influxdata/telegraf/config" - "github.com/influxdata/telegraf/plugins/common/tls" - "github.com/influxdata/telegraf/plugins/inputs" - "github.com/influxdata/telegraf/plugins/parsers/json" -) - -//go:embed sample.conf -var sampleConfig string - -var ( - utf8BOM = []byte("\xef\xbb\xbf") -) - -// HTTPJSON struct -type HTTPJSON struct { - Name string `toml:"name" deprecated:"1.3.0;use 'name_override', 'name_suffix', 'name_prefix' instead"` - Servers []string - Method string - TagKeys []string - ResponseTimeout config.Duration - Parameters map[string]string - Headers map[string]string - tls.ClientConfig - - client HTTPClient -} - -type HTTPClient interface { - // Returns the result of an http request - // - // Parameters: - // req: HTTP request object - // - // Returns: - // http.Response: HTTP response object - // error : Any error that may have occurred - MakeRequest(req *http.Request) (*http.Response, error) - - SetHTTPClient(client *http.Client) - HTTPClient() *http.Client -} - -type RealHTTPClient struct { - client *http.Client -} - -func (c *RealHTTPClient) MakeRequest(req *http.Request) (*http.Response, error) { - return c.client.Do(req) -} - -func (c *RealHTTPClient) SetHTTPClient(client *http.Client) { - c.client = client -} - -func (c *RealHTTPClient) HTTPClient() *http.Client { - return c.client -} - -func (*HTTPJSON) SampleConfig() string { - return sampleConfig -} - -// Gathers data for all servers. -func (h *HTTPJSON) Gather(acc telegraf.Accumulator) error { - var wg sync.WaitGroup - - if h.client.HTTPClient() == nil { - tlsCfg, err := h.ClientConfig.TLSConfig() - if err != nil { - return err - } - tr := &http.Transport{ - ResponseHeaderTimeout: time.Duration(h.ResponseTimeout), - TLSClientConfig: tlsCfg, - } - client := &http.Client{ - Transport: tr, - Timeout: time.Duration(h.ResponseTimeout), - } - h.client.SetHTTPClient(client) - } - - for _, server := range h.Servers { - wg.Add(1) - go func(server string) { - defer wg.Done() - acc.AddError(h.gatherServer(acc, server)) - }(server) - } - - wg.Wait() - - return nil -} - -// Gathers data from a particular server -// Parameters: -// -// acc : The telegraf Accumulator to use -// serverURL: endpoint to send request to -// service : the service being queried -// -// Returns: -// -// error: Any error that may have occurred -func (h *HTTPJSON) gatherServer( - acc telegraf.Accumulator, - serverURL string, -) error { - resp, responseTime, err := h.sendRequest(serverURL) - if err != nil { - return err - } - - var msrmntName string - if h.Name == "" { - msrmntName = "httpjson" - } else { - msrmntName = "httpjson_" + h.Name - } - tags := map[string]string{ - "server": serverURL, - } - - parser := &json.Parser{ - MetricName: msrmntName, - TagKeys: h.TagKeys, - DefaultTags: tags, - } - if err := parser.Init(); err != nil { - return err - } - - metrics, err := parser.Parse([]byte(resp)) - if err != nil { - return err - } - - for _, metric := range metrics { - fields := make(map[string]interface{}) - for k, v := range metric.Fields() { - fields[k] = v - } - fields["response_time"] = responseTime - acc.AddFields(metric.Name(), fields, metric.Tags()) - } - return nil -} - -// Sends an HTTP request to the server using the HTTPJSON object's HTTPClient. -// This request can be either a GET or a POST. -// Parameters: -// -// serverURL: endpoint to send request to -// -// Returns: -// -// string: body of the response -// error : Any error that may have occurred -func (h *HTTPJSON) sendRequest(serverURL string) (string, float64, error) { - // Prepare URL - requestURL, err := url.Parse(serverURL) - if err != nil { - return "", -1, fmt.Errorf("Invalid server URL %q", serverURL) - } - - data := url.Values{} - switch { - case h.Method == "GET": - params := requestURL.Query() - for k, v := range h.Parameters { - params.Add(k, v) - } - requestURL.RawQuery = params.Encode() - - case h.Method == "POST": - requestURL.RawQuery = "" - for k, v := range h.Parameters { - data.Add(k, v) - } - } - - // Create + send request - req, err := http.NewRequest(h.Method, requestURL.String(), - strings.NewReader(data.Encode())) - if err != nil { - return "", -1, err - } - - // Add header parameters - for k, v := range h.Headers { - if strings.EqualFold(k, "host") { - req.Host = v - } else { - req.Header.Add(k, v) - } - } - - start := time.Now() - resp, err := h.client.MakeRequest(req) - if err != nil { - return "", -1, err - } - - defer resp.Body.Close() - responseTime := time.Since(start).Seconds() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return string(body), responseTime, err - } - body = bytes.TrimPrefix(body, utf8BOM) - - // Process response - if resp.StatusCode != http.StatusOK { - err = fmt.Errorf("Response from url %q has status code %d (%s), expected %d (%s)", - requestURL.String(), - resp.StatusCode, - http.StatusText(resp.StatusCode), - http.StatusOK, - http.StatusText(http.StatusOK)) - return string(body), responseTime, err - } - - return string(body), responseTime, err -} - -func init() { - inputs.Add("httpjson", func() telegraf.Input { - return &HTTPJSON{ - client: &RealHTTPClient{}, - ResponseTimeout: config.Duration(5 * time.Second), - } - }) -} diff --git a/plugins/inputs/httpjson/httpjson_test.go b/plugins/inputs/httpjson/httpjson_test.go deleted file mode 100644 index 8769fad9c..000000000 --- a/plugins/inputs/httpjson/httpjson_test.go +++ /dev/null @@ -1,580 +0,0 @@ -package httpjson - -import ( - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "testing" - - "github.com/stretchr/testify/require" - - "github.com/influxdata/telegraf/testutil" -) - -const validJSON = ` - { - "parent": { - "child": 3.0, - "ignored_child": "hi" - }, - "ignored_null": null, - "integer": 4, - "list": [3, 4], - "ignored_parent": { - "another_ignored_null": null, - "ignored_string": "hello, world!" - }, - "another_list": [4] - }` - -const validJSON2 = `{ - "user":{ - "hash_rate":0, - "expected_24h_rewards":0, - "total_rewards":0.000595109232, - "paid_rewards":0, - "unpaid_rewards":0.000595109232, - "past_24h_rewards":0, - "total_work":"5172625408", - "blocks_found":0 - }, - "workers":{ - "brminer.1":{ - "hash_rate":0, - "hash_rate_24h":0, - "valid_shares":"6176", - "stale_shares":"0", - "invalid_shares":"0", - "rewards":4.5506464e-5, - "rewards_24h":0, - "reset_time":1455409950 - }, - "brminer.2":{ - "hash_rate":0, - "hash_rate_24h":0, - "valid_shares":"0", - "stale_shares":"0", - "invalid_shares":"0", - "rewards":0, - "rewards_24h":0, - "reset_time":1455936726 - }, - "brminer.3":{ - "hash_rate":0, - "hash_rate_24h":0, - "valid_shares":"0", - "stale_shares":"0", - "invalid_shares":"0", - "rewards":0, - "rewards_24h":0, - "reset_time":1455936733 - } - }, - "pool":{ - "hash_rate":114100000, - "active_users":843, - "total_work":"5015346808842682368", - "pps_ratio":1.04, - "pps_rate":7.655e-9 - }, - "network":{ - "hash_rate":1426117703, - "block_number":944895, - "time_per_block":156, - "difficulty":51825.72835216, - "next_difficulty":51916.15249019, - "retarget_time":95053 - }, - "market":{ - "ltc_btc":0.00798, - "ltc_usd":3.37801, - "ltc_eur":3.113, - "ltc_gbp":2.32807, - "ltc_rub":241.796, - "ltc_cny":21.3883, - "btc_usd":422.852 - } -}` - -const validJSONTags = ` - { - "value": 15, - "role": "master", - "build": "123" - }` - -var expectedFields = map[string]interface{}{ - "parent_child": float64(3), - "list_0": float64(3), - "list_1": float64(4), - "another_list_0": float64(4), - "integer": float64(4), -} - -const invalidJSON = "I don't think this is JSON" - -const empty = "" - -type mockHTTPClient struct { - responseBody string - statusCode int -} - -// Mock implementation of MakeRequest. Usually returns an http.Response with -// hard-coded responseBody and statusCode. However, if the request uses a -// nonstandard method, it uses status code 405 (method not allowed) -func (c *mockHTTPClient) MakeRequest(req *http.Request) (*http.Response, error) { - resp := http.Response{} - resp.StatusCode = c.statusCode - - // basic error checking on request method - allowedMethods := []string{"GET", "HEAD", "POST", "PUT", "DELETE", "TRACE", "CONNECT"} - methodValid := false - for _, method := range allowedMethods { - if req.Method == method { - methodValid = true - break - } - } - - if !methodValid { - resp.StatusCode = 405 // Method not allowed - } - - resp.Body = io.NopCloser(strings.NewReader(c.responseBody)) - return &resp, nil -} - -func (c *mockHTTPClient) SetHTTPClient(_ *http.Client) { -} - -func (c *mockHTTPClient) HTTPClient() *http.Client { - return nil -} - -// Generates a pointer to an HTTPJSON object that uses a mock HTTP client. -// Parameters: -// -// response : Body of the response that the mock HTTP client should return -// statusCode: HTTP status code the mock HTTP client should return -// -// Returns: -// -// *HTTPJSON: Pointer to an HTTPJSON object that uses the generated mock HTTP client -func genMockHTTPJSON(response string, statusCode int) []*HTTPJSON { - return []*HTTPJSON{ - { - client: &mockHTTPClient{responseBody: response, statusCode: statusCode}, - 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", - }, - Headers: map[string]string{ - "X-Auth-Token": "the-first-parameter", - "apiVersion": "v1", - }, - }, - { - 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", - }, - Headers: map[string]string{ - "X-Auth-Token": "the-first-parameter", - "apiVersion": "v1", - }, - TagKeys: []string{ - "role", - "build", - }, - }, - } -} - -// Test that the proper values are ignored or collected -func TestHttpJson200(t *testing.T) { - httpjson := genMockHTTPJSON(validJSON, 200) - - for _, service := range httpjson { - var acc testutil.Accumulator - err := acc.GatherError(service.Gather) - require.NoError(t, err) - require.Equal(t, 12, acc.NFields()) - // Set responsetime - for _, p := range acc.Metrics { - p.Fields["response_time"] = 1.0 - } - - for _, srv := range service.Servers { - tags := map[string]string{"server": srv} - mname := "httpjson_" + service.Name - expectedFields["response_time"] = 1.0 - acc.AssertContainsTaggedFields(t, mname, expectedFields, tags) - } - } -} - -// Test that GET Parameters from the url string are applied properly -func TestHttpJsonGET_URL(t *testing.T) { - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - key := r.FormValue("api_key") - require.Equal(t, "mykey", key) - w.WriteHeader(http.StatusOK) - _, err := fmt.Fprintln(w, validJSON2) - require.NoError(t, err) - })) - defer ts.Close() - - a := HTTPJSON{ - Servers: []string{ts.URL + "?api_key=mykey"}, - Name: "", - Method: "GET", - client: &RealHTTPClient{client: &http.Client{}}, - } - - var acc testutil.Accumulator - err := acc.GatherError(a.Gather) - require.NoError(t, err) - - // remove response_time from gathered fields because it's non-deterministic - delete(acc.Metrics[0].Fields, "response_time") - - fields := map[string]interface{}{ - "market_btc_usd": float64(422.852), - "market_ltc_btc": float64(0.00798), - "market_ltc_cny": float64(21.3883), - "market_ltc_eur": float64(3.113), - "market_ltc_gbp": float64(2.32807), - "market_ltc_rub": float64(241.796), - "market_ltc_usd": float64(3.37801), - "network_block_number": float64(944895), - "network_difficulty": float64(51825.72835216), - "network_hash_rate": float64(1.426117703e+09), - "network_next_difficulty": float64(51916.15249019), - "network_retarget_time": float64(95053), - "network_time_per_block": float64(156), - "pool_active_users": float64(843), - "pool_hash_rate": float64(1.141e+08), - "pool_pps_rate": float64(7.655e-09), - "pool_pps_ratio": float64(1.04), - "user_blocks_found": float64(0), - "user_expected_24h_rewards": float64(0), - "user_hash_rate": float64(0), - "user_paid_rewards": float64(0), - "user_past_24h_rewards": float64(0), - "user_total_rewards": float64(0.000595109232), - "user_unpaid_rewards": float64(0.000595109232), - "workers_brminer.1_hash_rate": float64(0), - "workers_brminer.1_hash_rate_24h": float64(0), - "workers_brminer.1_reset_time": float64(1.45540995e+09), - "workers_brminer.1_rewards": float64(4.5506464e-05), - "workers_brminer.1_rewards_24h": float64(0), - "workers_brminer.2_hash_rate": float64(0), - "workers_brminer.2_hash_rate_24h": float64(0), - "workers_brminer.2_reset_time": float64(1.455936726e+09), - "workers_brminer.2_rewards": float64(0), - "workers_brminer.2_rewards_24h": float64(0), - "workers_brminer.3_hash_rate": float64(0), - "workers_brminer.3_hash_rate_24h": float64(0), - "workers_brminer.3_reset_time": float64(1.455936733e+09), - "workers_brminer.3_rewards": float64(0), - "workers_brminer.3_rewards_24h": float64(0), - } - - acc.AssertContainsFields(t, "httpjson", fields) -} - -// Test that GET Parameters are applied properly -func TestHttpJsonGET(t *testing.T) { - params := map[string]string{ - "api_key": "mykey", - } - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - key := r.FormValue("api_key") - require.Equal(t, "mykey", key) - w.WriteHeader(http.StatusOK) - _, err := fmt.Fprintln(w, validJSON2) - require.NoError(t, err) - })) - defer ts.Close() - - a := HTTPJSON{ - Servers: []string{ts.URL}, - Name: "", - Method: "GET", - Parameters: params, - client: &RealHTTPClient{client: &http.Client{}}, - } - - var acc testutil.Accumulator - err := acc.GatherError(a.Gather) - require.NoError(t, err) - - // remove response_time from gathered fields because it's non-deterministic - delete(acc.Metrics[0].Fields, "response_time") - - fields := map[string]interface{}{ - "market_btc_usd": float64(422.852), - "market_ltc_btc": float64(0.00798), - "market_ltc_cny": float64(21.3883), - "market_ltc_eur": float64(3.113), - "market_ltc_gbp": float64(2.32807), - "market_ltc_rub": float64(241.796), - "market_ltc_usd": float64(3.37801), - "network_block_number": float64(944895), - "network_difficulty": float64(51825.72835216), - "network_hash_rate": float64(1.426117703e+09), - "network_next_difficulty": float64(51916.15249019), - "network_retarget_time": float64(95053), - "network_time_per_block": float64(156), - "pool_active_users": float64(843), - "pool_hash_rate": float64(1.141e+08), - "pool_pps_rate": float64(7.655e-09), - "pool_pps_ratio": float64(1.04), - "user_blocks_found": float64(0), - "user_expected_24h_rewards": float64(0), - "user_hash_rate": float64(0), - "user_paid_rewards": float64(0), - "user_past_24h_rewards": float64(0), - "user_total_rewards": float64(0.000595109232), - "user_unpaid_rewards": float64(0.000595109232), - "workers_brminer.1_hash_rate": float64(0), - "workers_brminer.1_hash_rate_24h": float64(0), - "workers_brminer.1_reset_time": float64(1.45540995e+09), - "workers_brminer.1_rewards": float64(4.5506464e-05), - "workers_brminer.1_rewards_24h": float64(0), - "workers_brminer.2_hash_rate": float64(0), - "workers_brminer.2_hash_rate_24h": float64(0), - "workers_brminer.2_reset_time": float64(1.455936726e+09), - "workers_brminer.2_rewards": float64(0), - "workers_brminer.2_rewards_24h": float64(0), - "workers_brminer.3_hash_rate": float64(0), - "workers_brminer.3_hash_rate_24h": float64(0), - "workers_brminer.3_reset_time": float64(1.455936733e+09), - "workers_brminer.3_rewards": float64(0), - "workers_brminer.3_rewards_24h": float64(0), - } - - acc.AssertContainsFields(t, "httpjson", fields) -} - -// Test that POST Parameters are applied properly -func TestHttpJsonPOST(t *testing.T) { - params := map[string]string{ - "api_key": "mykey", - } - ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - body, err := io.ReadAll(r.Body) - require.NoError(t, err) - require.Equal(t, "api_key=mykey", string(body)) - w.WriteHeader(http.StatusOK) - _, err = fmt.Fprintln(w, validJSON2) - require.NoError(t, err) - })) - defer ts.Close() - - a := HTTPJSON{ - Servers: []string{ts.URL}, - Name: "", - Method: "POST", - Parameters: params, - client: &RealHTTPClient{client: &http.Client{}}, - } - - var acc testutil.Accumulator - err := acc.GatherError(a.Gather) - require.NoError(t, err) - - // remove response_time from gathered fields because it's non-deterministic - delete(acc.Metrics[0].Fields, "response_time") - - fields := map[string]interface{}{ - "market_btc_usd": float64(422.852), - "market_ltc_btc": float64(0.00798), - "market_ltc_cny": float64(21.3883), - "market_ltc_eur": float64(3.113), - "market_ltc_gbp": float64(2.32807), - "market_ltc_rub": float64(241.796), - "market_ltc_usd": float64(3.37801), - "network_block_number": float64(944895), - "network_difficulty": float64(51825.72835216), - "network_hash_rate": float64(1.426117703e+09), - "network_next_difficulty": float64(51916.15249019), - "network_retarget_time": float64(95053), - "network_time_per_block": float64(156), - "pool_active_users": float64(843), - "pool_hash_rate": float64(1.141e+08), - "pool_pps_rate": float64(7.655e-09), - "pool_pps_ratio": float64(1.04), - "user_blocks_found": float64(0), - "user_expected_24h_rewards": float64(0), - "user_hash_rate": float64(0), - "user_paid_rewards": float64(0), - "user_past_24h_rewards": float64(0), - "user_total_rewards": float64(0.000595109232), - "user_unpaid_rewards": float64(0.000595109232), - "workers_brminer.1_hash_rate": float64(0), - "workers_brminer.1_hash_rate_24h": float64(0), - "workers_brminer.1_reset_time": float64(1.45540995e+09), - "workers_brminer.1_rewards": float64(4.5506464e-05), - "workers_brminer.1_rewards_24h": float64(0), - "workers_brminer.2_hash_rate": float64(0), - "workers_brminer.2_hash_rate_24h": float64(0), - "workers_brminer.2_reset_time": float64(1.455936726e+09), - "workers_brminer.2_rewards": float64(0), - "workers_brminer.2_rewards_24h": float64(0), - "workers_brminer.3_hash_rate": float64(0), - "workers_brminer.3_hash_rate_24h": float64(0), - "workers_brminer.3_reset_time": float64(1.455936733e+09), - "workers_brminer.3_rewards": float64(0), - "workers_brminer.3_rewards_24h": float64(0), - } - - acc.AssertContainsFields(t, "httpjson", fields) -} - -// Test response to HTTP 500 -func TestHttpJson500(t *testing.T) { - httpjson := genMockHTTPJSON(validJSON, 500) - - var acc testutil.Accumulator - err := acc.GatherError(httpjson[0].Gather) - - require.Error(t, err) - require.Equal(t, 0, acc.NFields()) -} - -// Test response to HTTP 405 -func TestHttpJsonBadMethod(t *testing.T) { - httpjson := genMockHTTPJSON(validJSON, 200) - httpjson[0].Method = "NOT_A_REAL_METHOD" - - var acc testutil.Accumulator - err := acc.GatherError(httpjson[0].Gather) - - require.Error(t, err) - require.Equal(t, 0, acc.NFields()) -} - -// Test response to malformed JSON -func TestHttpJsonBadJson(t *testing.T) { - httpjson := genMockHTTPJSON(invalidJSON, 200) - - var acc testutil.Accumulator - err := acc.GatherError(httpjson[0].Gather) - - require.Error(t, err) - require.Equal(t, 0, acc.NFields()) -} - -// Test response to empty string as response object -func TestHttpJsonEmptyResponse(t *testing.T) { - httpjson := genMockHTTPJSON(empty, 200) - - var acc testutil.Accumulator - err := acc.GatherError(httpjson[0].Gather) - require.NoError(t, err) -} - -// Test that the proper values are ignored or collected -func TestHttpJson200Tags(t *testing.T) { - httpjson := genMockHTTPJSON(validJSONTags, 200) - - for _, service := range httpjson { - if service.Name == "other_webapp" { - var acc testutil.Accumulator - err := acc.GatherError(service.Gather) - // Set responsetime - for _, p := range acc.Metrics { - p.Fields["response_time"] = 1.0 - } - require.NoError(t, err) - require.Equal(t, 4, acc.NFields()) - for _, srv := range service.Servers { - tags := map[string]string{"server": srv, "role": "master", "build": "123"} - fields := map[string]interface{}{"value": float64(15), "response_time": float64(1)} - mname := "httpjson_" + service.Name - acc.AssertContainsTaggedFields(t, mname, fields, tags) - } - } - } -} - -const validJSONArrayTags = ` -[ - { - "value": 15, - "role": "master", - "build": "123" - }, - { - "value": 17, - "role": "slave", - "build": "456" - } -]` - -// Test that array data is collected correctly -func TestHttpJsonArray200Tags(t *testing.T) { - httpjson := genMockHTTPJSON(validJSONArrayTags, 200) - - for _, service := range httpjson { - if service.Name == "other_webapp" { - var acc testutil.Accumulator - err := acc.GatherError(service.Gather) - // Set responsetime - for _, p := range acc.Metrics { - p.Fields["response_time"] = 1.0 - } - require.NoError(t, err) - require.Equal(t, 8, acc.NFields()) - require.Equal(t, uint64(4), acc.NMetrics()) - - for _, m := range acc.Metrics { - if m.Tags["role"] == "master" { - require.Equal(t, "123", m.Tags["build"]) - require.Equal(t, float64(15), m.Fields["value"]) - require.Equal(t, float64(1), m.Fields["response_time"]) - require.Equal(t, "httpjson_"+service.Name, m.Measurement) - } else if m.Tags["role"] == "slave" { - require.Equal(t, "456", m.Tags["build"]) - require.Equal(t, float64(17), m.Fields["value"]) - require.Equal(t, float64(1), m.Fields["response_time"]) - require.Equal(t, "httpjson_"+service.Name, m.Measurement) - } else { - require.FailNow(t, "unknown metric") - } - } - } - } -} - -var jsonBOM = []byte("\xef\xbb\xbf[{\"value\":17}]") - -// TestHttpJsonBOM tests that UTF-8 JSON with a BOM can be parsed -func TestHttpJsonBOM(t *testing.T) { - httpjson := genMockHTTPJSON(string(jsonBOM), 200) - - for _, service := range httpjson { - if service.Name == "other_webapp" { - var acc testutil.Accumulator - err := acc.GatherError(service.Gather) - require.NoError(t, err) - } - } -} diff --git a/plugins/inputs/httpjson/sample.conf b/plugins/inputs/httpjson/sample.conf deleted file mode 100644 index 0a6f6ea3e..000000000 --- a/plugins/inputs/httpjson/sample.conf +++ /dev/null @@ -1,46 +0,0 @@ -# Read flattened metrics from one or more JSON HTTP endpoints -[[inputs.httpjson]] - ## NOTE This plugin only reads numerical measurements, strings and booleans - ## will be ignored. - - ## Name for the service being polled. Will be appended to the name of the - ## measurement e.g. "httpjson_webserver_stats". - ## - ## Deprecated (1.3.0): Use name_override, name_suffix, name_prefix instead. - name = "webserver_stats" - - ## URL of each server in the service's cluster - servers = [ - "http://localhost:9999/stats/", - "http://localhost:9998/stats/", - ] - ## Set response_timeout (default 5 seconds) - response_timeout = "5s" - - ## HTTP method to use: GET or POST (case-sensitive) - method = "GET" - - ## Tags to extract from top-level of JSON server response. - # tag_keys = [ - # "my_tag_1", - # "my_tag_2" - # ] - - ## Optional TLS Config - # tls_ca = "/etc/telegraf/ca.pem" - # tls_cert = "/etc/telegraf/cert.pem" - # tls_key = "/etc/telegraf/key.pem" - ## Use TLS but skip chain & host verification - # insecure_skip_verify = false - - ## HTTP Request Parameters (all values must be strings). For "GET" requests, data - ## will be included in the query. For "POST" requests, data will be included - ## in the request body as "x-www-form-urlencoded". - # [inputs.httpjson.parameters] - # event_type = "cpu_spike" - # threshold = "0.75" - - ## HTTP Request Headers (all values must be strings). - # [inputs.httpjson.headers] - # X-Auth-Token = "my-xauth-token" - # apiVersion = "v1"