Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set accept header for prometheus client scraping #17291

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ https://github.com/elastic/beats/compare/v7.0.0-alpha2...master[Check the HEAD d
- Check if CCR feature is available on Elasticsearch cluster before attempting to call CCR APIs from `elasticsearch/ccr` metricset. {issue}16511[16511] {pull}17073[17073]
- Use max in k8s overview dashboard aggregations. {pull}17015[17015]
- Fix Disk Used and Disk Usage visualizations in the Metricbeat System dashboards. {issue}12435[12435] {pull}17272[17272]
- Fix missing Accept header for Prometheus and OpenMetrics module. {issue}16870[16870] {pull}17291[17291]

*Packetbeat*

Expand Down
27 changes: 19 additions & 8 deletions metricbeat/helper/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import (
type HTTP struct {
hostData mb.HostData
client *http.Client // HTTP client that is reused across requests.
headers map[string]string
headers http.Header
name string
uri string
method string
Expand All @@ -58,16 +58,20 @@ func NewHTTP(base mb.BaseMetricSet) (*HTTP, error) {

// newHTTPWithConfig creates a new http helper from some configuration
func newHTTPFromConfig(config Config, name string, hostData mb.HostData) (*HTTP, error) {
headers := http.Header{}
if config.Headers == nil {
config.Headers = map[string]string{}
}
for k, v := range config.Headers {
headers.Set(k, v)
}

if config.BearerTokenFile != "" {
header, err := getAuthHeaderFromToken(config.BearerTokenFile)
if err != nil {
return nil, err
}
config.Headers["Authorization"] = header
headers.Set("Authorization", header)
}

tlsConfig, err := tlscommon.LoadTLSConfig(config.TLS)
Expand Down Expand Up @@ -103,7 +107,7 @@ func newHTTPFromConfig(config Config, name string, hostData mb.HostData) (*HTTP,
},
Timeout: config.Timeout,
},
headers: config.Headers,
headers: headers,
method: "GET",
uri: hostData.SanitizedURI,
body: nil,
Expand All @@ -124,14 +128,11 @@ func (h *HTTP) FetchResponse() (*http.Response, error) {
if err != nil {
return nil, errors.Wrap(err, "failed to create HTTP request")
}
req.Header = h.headers
if h.hostData.User != "" || h.hostData.Password != "" {
req.SetBasicAuth(h.hostData.User, h.hostData.Password)
}

for k, v := range h.headers {
req.Header.Set(k, v)
}

resp, err := h.client.Do(req)
if err != nil {
return nil, fmt.Errorf("error making http request: %v", err)
Expand All @@ -142,7 +143,17 @@ func (h *HTTP) FetchResponse() (*http.Response, error) {

// SetHeader sets HTTP headers to use in requests
func (h *HTTP) SetHeader(key, value string) {
h.headers[key] = value
h.headers.Set(key, value)
}

// SetHeaderDefault sets HTTP header as default
//
// Note: This will only set the header when the header is not already set.
func (h *HTTP) SetHeaderDefault(key, value string) {
c := h.headers.Get(key)
if c == "" {
h.headers.Set(key, value)
}
}

// SetMethod sets HTTP method to use in requests
Expand Down
28 changes: 28 additions & 0 deletions metricbeat/helper/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,34 @@ func TestAuthentication(t *testing.T) {
assert.Equal(t, http.StatusOK, response.StatusCode, "response status code")
}

func TestSetHeader(t *testing.T) {
cfg := defaultConfig()
cfg.Headers = map[string]string{
"Override": "default",
}

h, err := newHTTPFromConfig(cfg, "test", mb.HostData{})
require.NoError(t, err)

h.SetHeader("Override", "overridden")
v := h.headers.Get("override")
assert.Equal(t, "overridden", v)
}

func TestSetHeaderDefault(t *testing.T) {
cfg := defaultConfig()
cfg.Headers = map[string]string{
"Override": "default",
}

h, err := newHTTPFromConfig(cfg, "test", mb.HostData{})
require.NoError(t, err)

h.SetHeaderDefault("Override", "overridden")
v := h.headers.Get("override")
assert.Equal(t, "default", v)
}

func TestOverUnixSocket(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skipf("unix domain socket aren't supported under Windows")
Expand Down
5 changes: 4 additions & 1 deletion metricbeat/helper/prometheus/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import (
"github.com/elastic/beats/v7/metricbeat/mb"
)

const acceptHeader = `application/openmetrics-text; version=0.0.1,text/plain;version=0.0.4;q=0.5,*/*;q=0.1`

// Prometheus helper retrieves prometheus formatted metrics
type Prometheus interface {
// GetFamilies requests metric families from prometheus endpoint and returns them
Expand All @@ -55,10 +57,11 @@ type httpfetcher interface {
// NewPrometheusClient creates new prometheus helper
func NewPrometheusClient(base mb.BaseMetricSet) (Prometheus, error) {
http, err := helper.NewHTTP(base)

if err != nil {
return nil, err
}

http.SetHeaderDefault("Accept", acceptHeader)
return &prometheus{http, base.Logger()}, nil
}

Expand Down