feat(inputs.prometheus): Add option to limit body length (#14661)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@me.com> Co-authored-by: Josh Powers <powersj@fastmail.com>
This commit is contained in:
parent
f9f2adf3ae
commit
534289f3b4
|
|
@ -83,6 +83,11 @@ See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
|
||||||
## Default is 60 seconds.
|
## Default is 60 seconds.
|
||||||
# pod_scrape_interval = 60
|
# pod_scrape_interval = 60
|
||||||
|
|
||||||
|
## Content length limit
|
||||||
|
## When set, telegraf will drop responses with length larger than the configured value.
|
||||||
|
## Default is "0KB" which means unlimited.
|
||||||
|
# content_length_limit = "0KB"
|
||||||
|
|
||||||
## Restricts Kubernetes monitoring to a single namespace
|
## Restricts Kubernetes monitoring to a single namespace
|
||||||
## ex: monitor_kubernetes_pods_namespace = "default"
|
## ex: monitor_kubernetes_pods_namespace = "default"
|
||||||
# monitor_kubernetes_pods_namespace = ""
|
# monitor_kubernetes_pods_namespace = ""
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,8 @@ type Prometheus struct {
|
||||||
|
|
||||||
HTTPHeaders map[string]string `toml:"http_headers"`
|
HTTPHeaders map[string]string `toml:"http_headers"`
|
||||||
|
|
||||||
ResponseTimeout config.Duration `toml:"response_timeout" deprecated:"1.26.0;use 'timeout' instead"`
|
ResponseTimeout config.Duration `toml:"response_timeout" deprecated:"1.26.0;use 'timeout' instead"`
|
||||||
|
ContentLengthLimit config.Size `toml:"content_length_limit"`
|
||||||
|
|
||||||
MetricVersion int `toml:"metric_version"`
|
MetricVersion int `toml:"metric_version"`
|
||||||
|
|
||||||
|
|
@ -437,9 +438,28 @@ func (p *Prometheus) gatherURL(u URLAndAddress, acc telegraf.Accumulator) error
|
||||||
return fmt.Errorf("%q returned HTTP status %q", u.URL, resp.Status)
|
return fmt.Errorf("%q returned HTTP status %q", u.URL, resp.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := io.ReadAll(resp.Body)
|
var body []byte
|
||||||
if err != nil {
|
if p.ContentLengthLimit != 0 {
|
||||||
return fmt.Errorf("error reading body: %w", err)
|
limit := int64(p.ContentLengthLimit)
|
||||||
|
|
||||||
|
// To determine whether io.ReadAll() ended due to EOF or reached the specified limit,
|
||||||
|
// read up to the specified limit plus one extra byte, and then make a decision based
|
||||||
|
// on the length of the result.
|
||||||
|
lr := io.LimitReader(resp.Body, limit+1)
|
||||||
|
|
||||||
|
body, err = io.ReadAll(lr)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading body: %w", err)
|
||||||
|
}
|
||||||
|
if int64(len(body)) > limit {
|
||||||
|
p.Log.Infof("skipping %s: content length exceeded maximum body size (%d)", u.URL, limit)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body, err = io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error reading body: %w", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the metrics
|
// Parse the metrics
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,26 @@ func TestPrometheusGeneratesMetricsSlowEndpointHitTheTimeoutNewConfigParameter(t
|
||||||
require.ErrorContains(t, err, "error making HTTP request to \""+ts.URL+"/metrics\"")
|
require.ErrorContains(t, err, "error making HTTP request to \""+ts.URL+"/metrics\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrometheusContentLengthLimit(t *testing.T) {
|
||||||
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
_, err := fmt.Fprintln(w, sampleTextFormat)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
|
p := &Prometheus{
|
||||||
|
Log: testutil.Logger{},
|
||||||
|
URLs: []string{ts.URL},
|
||||||
|
URLTag: "url",
|
||||||
|
ContentLengthLimit: 1,
|
||||||
|
}
|
||||||
|
require.NoError(t, p.Init())
|
||||||
|
|
||||||
|
var acc testutil.Accumulator
|
||||||
|
require.NoError(t, acc.GatherError(p.Gather))
|
||||||
|
require.Empty(t, acc.Metrics)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPrometheusGeneratesSummaryMetricsV2(t *testing.T) {
|
func TestPrometheusGeneratesSummaryMetricsV2(t *testing.T) {
|
||||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
_, err := fmt.Fprintln(w, sampleSummaryTextFormat)
|
_, err := fmt.Fprintln(w, sampleSummaryTextFormat)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,11 @@
|
||||||
## Default is 60 seconds.
|
## Default is 60 seconds.
|
||||||
# pod_scrape_interval = 60
|
# pod_scrape_interval = 60
|
||||||
|
|
||||||
|
## Content length limit
|
||||||
|
## When set, telegraf will drop responses with length larger than the configured value.
|
||||||
|
## Default is "0KB" which means unlimited.
|
||||||
|
# content_length_limit = "0KB"
|
||||||
|
|
||||||
## Restricts Kubernetes monitoring to a single namespace
|
## Restricts Kubernetes monitoring to a single namespace
|
||||||
## ex: monitor_kubernetes_pods_namespace = "default"
|
## ex: monitor_kubernetes_pods_namespace = "default"
|
||||||
# monitor_kubernetes_pods_namespace = ""
|
# monitor_kubernetes_pods_namespace = ""
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue