Skip to content

Commit

Permalink
Merge remote-tracking branch 'prometheus/main' into add-unit
Browse files Browse the repository at this point in the history
Signed-off-by: Arianna Vespri <[email protected]>
  • Loading branch information
vesari committed Feb 29, 2024
2 parents 1755cb6 + 52e512c commit 89f4253
Show file tree
Hide file tree
Showing 18 changed files with 356 additions and 211 deletions.
6 changes: 3 additions & 3 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,14 @@ workflows:
matrix:
parameters:
go_version:
- "1.20"
- "1.21"
- "1.22"
- test-assets:
name: assets-go-<< matrix.go_version >>
matrix:
parameters:
go_version:
- "1.21"
- "1.22"
- style:
name: style
go_version: "1.21"
go_version: "1.22"
2 changes: 1 addition & 1 deletion .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
- name: install Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: 1.21.x
go-version: 1.22.x
- name: Install snmp_exporter/generator dependencies
run: sudo apt-get update && sudo apt-get -y install libsnmp-dev
if: github.repository == 'prometheus/snmp_exporter'
Expand Down
4 changes: 2 additions & 2 deletions Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ SKIP_GOLANGCI_LINT :=
GOLANGCI_LINT :=
GOLANGCI_LINT_OPTS ?=
GOLANGCI_LINT_VERSION ?= v1.55.2
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64.
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64/arm64.
# windows isn't included here because of the path separator being different.
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386))
ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386 arm64))
# If we're in CI and there is an Actions file, that means the linter
# is being run in Actions, so we don't need to run it here.
ifneq (,$(SKIP_GOLANGCI_LINT))
Expand Down
2 changes: 1 addition & 1 deletion assets/go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module github.com/prometheus/common/assets

go 1.20
go 1.21
38 changes: 38 additions & 0 deletions config/http_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,9 @@ type HTTPClientConfig struct {
// The omitempty flag is not set, because it would be hidden from the
// marshalled configuration when set to false.
EnableHTTP2 bool `yaml:"enable_http2" json:"enable_http2"`
// Host optionally overrides the Host header to send.
// If empty, the host from the URL will be used.
Host string `yaml:"host,omitempty" json:"host,omitempty"`
// Proxy configuration.
ProxyConfig `yaml:",inline"`
}
Expand Down Expand Up @@ -427,6 +430,7 @@ type httpClientOptions struct {
http2Enabled bool
idleConnTimeout time.Duration
userAgent string
host string
}

// HTTPClientOption defines an option that can be applied to the HTTP client.
Expand Down Expand Up @@ -467,6 +471,13 @@ func WithUserAgent(ua string) HTTPClientOption {
}
}

// WithHost allows setting the host header.
func WithHost(host string) HTTPClientOption {
return func(opts *httpClientOptions) {
opts.host = host
}
}

// NewClient returns a http.Client using the specified http.RoundTripper.
func newClient(rt http.RoundTripper) *http.Client {
return &http.Client{Transport: rt}
Expand Down Expand Up @@ -568,6 +579,10 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HT
rt = NewUserAgentRoundTripper(opts.userAgent, rt)
}

if opts.host != "" {
rt = NewHostRoundTripper(opts.host, rt)
}

// Return a new configured RoundTripper.
return rt, nil
}
Expand Down Expand Up @@ -1164,11 +1179,21 @@ type userAgentRoundTripper struct {
rt http.RoundTripper
}

type hostRoundTripper struct {
host string
rt http.RoundTripper
}

// NewUserAgentRoundTripper adds the user agent every request header.
func NewUserAgentRoundTripper(userAgent string, rt http.RoundTripper) http.RoundTripper {
return &userAgentRoundTripper{userAgent, rt}
}

// NewHostRoundTripper sets the [http.Request.Host] of every request.
func NewHostRoundTripper(host string, rt http.RoundTripper) http.RoundTripper {
return &hostRoundTripper{host, rt}
}

func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
req = cloneRequest(req)
req.Header.Set("User-Agent", rt.userAgent)
Expand All @@ -1181,6 +1206,19 @@ func (rt *userAgentRoundTripper) CloseIdleConnections() {
}
}

func (rt *hostRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
req = cloneRequest(req)
req.Host = rt.host
req.Header.Set("Host", rt.host)
return rt.rt.RoundTrip(req)
}

func (rt *hostRoundTripper) CloseIdleConnections() {
if ci, ok := rt.rt.(closeIdler); ok {
ci.CloseIdleConnections()
}
}

func (c HTTPClientConfig) String() string {
b, err := yaml.Marshal(c)
if err != nil {
Expand Down
28 changes: 27 additions & 1 deletion config/http_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
"testing"
"time"

yaml "gopkg.in/yaml.v2"
"gopkg.in/yaml.v2"
)

const (
Expand Down Expand Up @@ -1671,6 +1671,32 @@ func TestOAuth2UserAgent(t *testing.T) {
}
}

func TestHost(t *testing.T) {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Host != "localhost.localdomain" {
t.Fatalf("Expected Host header in request to be 'localhost.localdomain', got '%s'", r.Host)
}

w.Header().Add("Content-Type", "application/json")
}))
defer ts.Close()

config := DefaultHTTPClientConfig

rt, err := NewRoundTripperFromConfig(config, "test_host", WithHost("localhost.localdomain"))
if err != nil {
t.Fatal(err)
}

client := http.Client{
Transport: rt,
}
_, err = client.Get(ts.URL)
if err != nil {
t.Fatal(err)
}
}

func TestOAuth2WithFile(t *testing.T) {
var expectedAuth string
ts := newTestOAuthServer(t, &expectedAuth)
Expand Down
14 changes: 7 additions & 7 deletions expfmt/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,29 @@ func ResponseFormat(h http.Header) Format {

mediatype, params, err := mime.ParseMediaType(ct)
if err != nil {
return FmtUnknown
return fmtUnknown
}

const textType = "text/plain"

switch mediatype {
case ProtoType:
if p, ok := params["proto"]; ok && p != ProtoProtocol {
return FmtUnknown
return fmtUnknown
}
if e, ok := params["encoding"]; ok && e != "delimited" {
return FmtUnknown
return fmtUnknown
}
return FmtProtoDelim
return fmtProtoDelim

case textType:
if v, ok := params["version"]; ok && v != TextVersion {
return FmtUnknown
return fmtUnknown
}
return FmtText
return fmtText
}

return FmtUnknown
return fmtUnknown
}

// NewDecoder returns a new decoder based on the given input format.
Expand Down
14 changes: 7 additions & 7 deletions expfmt/decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,27 +421,27 @@ func testDiscriminatorHTTPHeader(t testing.TB) {
}{
{
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="delimited"`},
output: FmtProtoDelim,
output: fmtProtoDelim,
},
{
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="illegal"; encoding="delimited"`},
output: FmtUnknown,
output: fmtUnknown,
},
{
input: map[string]string{"Content-Type": `application/vnd.google.protobuf; proto="io.prometheus.client.MetricFamily"; encoding="illegal"`},
output: FmtUnknown,
output: fmtUnknown,
},
{
input: map[string]string{"Content-Type": `text/plain; version=0.0.4`},
output: FmtText,
output: fmtText,
},
{
input: map[string]string{"Content-Type": `text/plain`},
output: FmtText,
output: fmtText,
},
{
input: map[string]string{"Content-Type": `text/plain; version=0.0.3`},
output: FmtUnknown,
output: fmtUnknown,
},
}

Expand Down Expand Up @@ -547,7 +547,7 @@ func TestTextDecoderWithBufioReader(t *testing.T) {

var decoded bool
r := bufio.NewReader(strings.NewReader(example))
dec := NewDecoder(r, FmtText)
dec := NewDecoder(r, fmtText)
for {
var mf dto.MetricFamily
if err := dec.Decode(&mf); err != nil {
Expand Down
34 changes: 20 additions & 14 deletions expfmt/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,18 +76,18 @@ func Negotiate(h http.Header) Format {
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
switch ac.Params["encoding"] {
case "delimited":
return FmtProtoDelim + escapingScheme
return fmtProtoDelim + escapingScheme
case "text":
return FmtProtoText + escapingScheme
return fmtProtoText + escapingScheme
case "compact-text":
return FmtProtoCompact + escapingScheme
return fmtProtoCompact + escapingScheme
}
}
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
return FmtText + escapingScheme
return fmtText + escapingScheme
}
}
return FmtText + escapingScheme
return fmtText + escapingScheme
}

// NegotiateIncludingOpenMetrics works like Negotiate but includes
Expand All @@ -109,26 +109,26 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
if ac.Type+"/"+ac.SubType == ProtoType && ac.Params["proto"] == ProtoProtocol {
switch ac.Params["encoding"] {
case "delimited":
return FmtProtoDelim + escapingScheme
return fmtProtoDelim + escapingScheme
case "text":
return FmtProtoText + escapingScheme
return fmtProtoText + escapingScheme
case "compact-text":
return FmtProtoCompact + escapingScheme
return fmtProtoCompact + escapingScheme
}
}
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
return FmtText + escapingScheme
return fmtText + escapingScheme
}
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
switch ver {
case OpenMetricsVersion_1_0_0:
return FmtOpenMetrics_1_0_0 + escapingScheme
return fmtOpenMetrics_1_0_0 + escapingScheme
default:
return FmtOpenMetrics_0_0_1 + escapingScheme
return fmtOpenMetrics_0_0_1 + escapingScheme
}
}
}
return FmtText + escapingScheme
return fmtText + escapingScheme
}

// NewEncoder returns a new encoder based on content type negotiation. All
Expand All @@ -139,7 +139,13 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
// interface is kept for backwards compatibility.
// In cases where the Format does not allow for UTF-8 names, the global
// NameEscapingScheme will be applied.
func NewEncoder(w io.Writer, format Format, options ...ToOpenMetricsOption) Encoder {
//
// NewEncoder can be called with additional options to customize the OpenMetrics text output.
// For example:
// NewEncoder(w, FmtOpenMetrics_1_0_0, WithCreatedLines())
//
// Extra options are ignored for all other formats.
func NewEncoder(w io.Writer, format Format, options ...EncoderOption) Encoder {
escapingScheme := format.ToEscapingScheme()

switch format.FormatType() {
Expand Down Expand Up @@ -178,7 +184,7 @@ func NewEncoder(w io.Writer, format Format, options ...ToOpenMetricsOption) Enco
case TypeOpenMetrics:
return encoderCloser{
encode: func(v *dto.MetricFamily) error {
_, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme), options...)
_, err := MetricFamilyToOpenMetrics(w, model.EscapeMetricFamily(v, escapingScheme)) // , options...?
return err
},
close: func() error {
Expand Down
Loading

0 comments on commit 89f4253

Please sign in to comment.