Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: prometheus/common
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v0.55.0
Choose a base ref
...
head repository: prometheus/common
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v0.56.0
Choose a head ref

Commits on Jun 27, 2024

  1. Don't always fetch a OAuth2 token, if the secret from a file didn't c…

    …hange
    
    When configuring a OAuth2 client using the `client_secret_file`
    configuration option, the original intent of the code was to *not*
    forcefully refetch a token if the content of the file didn't change.
    
    However, both the test and the implementation had 2 typos and a new
    token token was fetched on every request through the HTTP client.
    
    Signed-off-by: Jonathan Ballet <jon@multani.info>
    multani committed Jun 27, 2024
    Copy the full SHA
    249682f View commit details

Commits on Jun 28, 2024

  1. Merge pull request #647 from multani/fix-oauth2-secret-file-refresh

    Don't always fetch a OAuth2 token, if the secret from a file didn't change
    roidelapluie authored Jun 28, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    8742f09 View commit details

Commits on Jul 14, 2024

  1. remove dependency to github.com/prometheus/client_golang in sigv4

    Replace promhttp.RoundTripperFunc with local version.
    
    Signed-off-by: Saeed Rasooli <saeed.gnu@gmail.com>
    ilius authored Jul 14, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    3e6afe2 View commit details
  2. Bump github.com/aws/aws-sdk-go from 1.54.7 to 1.54.11 in /sigv4 (#661)

    Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.54.7 to 1.54.11.
    - [Release notes](https://github.com/aws/aws-sdk-go/releases)
    - [Commits](aws/aws-sdk-go@v1.54.7...v1.54.11)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/aws/aws-sdk-go
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Jul 14, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    8e3075b View commit details

Commits on Jul 15, 2024

  1. Revert "Unexport Format strings"

    This reverts commit 05d7387.
    
    Signed-off-by: SuperQ <superq@gmail.com>
    SuperQ committed Jul 15, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    SuperQ Ben Kochie
    Copy the full SHA
    279f076 View commit details
  2. Deprecate format strings

    Add deprecation notice to format strings to allow transition to new
    functionality.
    
    Signed-off-by: SuperQ <superq@gmail.com>
    SuperQ committed Jul 15, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    SuperQ Ben Kochie
    Copy the full SHA
    c3e8247 View commit details
  3. Update common Prometheus files (#664)

    Signed-off-by: prombot <prometheus-team@googlegroups.com>
    prombot authored Jul 15, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1d53a04 View commit details
  4. Merge pull request #665 from prometheus/superq/revert_unexport

    Revert #576 and add deprecation notice
    Arthur Silva Sens authored Jul 15, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    4cf22c5 View commit details

Commits on Jul 16, 2024

  1. Bump golang.org/x/net from 0.26.0 to 0.27.0 (#667)

    Signed-off-by: Ben Kochie <superq@gmail.com>
    dependabot[bot] authored Jul 16, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    0b924af View commit details

Commits on Jul 17, 2024

  1. use basic string in IsValidLegacyMetricName

    Parameter didn't even match the function name.
    
    Signed-off-by: Owen Williams <owen.williams@grafana.com>
    ywwg committed Jul 17, 2024
    Copy the full SHA
    a9acdc7 View commit details

Commits on Jul 23, 2024

  1. Merge pull request #668 from ywwg/owilliams/param

    use basic string in IsValidLegacyMetricName
    beorn7 authored Jul 23, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    a3eaa75 View commit details

Commits on Aug 6, 2024

  1. Update common Prometheus files

    Signed-off-by: prombot <prometheus-team@googlegroups.com>
    prombot committed Aug 6, 2024
    Copy the full SHA
    6eac2f4 View commit details
  2. Merge pull request #672 from prometheus/repo_sync

    Synchronize common files from prometheus/prometheus
    ArthurSens authored Aug 6, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    3f9e4f8 View commit details

Commits on Aug 11, 2024

  1. Update common Prometheus files (#674)

    Signed-off-by: prombot <prometheus-team@googlegroups.com>
    prombot authored Aug 11, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    d235298 View commit details
  2. Bump github.com/aws/aws-sdk-go from 1.54.19 to 1.55.5 in /sigv4 (#671)

    Bumps [github.com/aws/aws-sdk-go](https://github.com/aws/aws-sdk-go) from 1.54.19 to 1.55.5.
    - [Release notes](https://github.com/aws/aws-sdk-go/releases)
    - [Commits](aws/aws-sdk-go@v1.54.19...v1.55.5)
    
    ---
    updated-dependencies:
    - dependency-name: github.com/aws/aws-sdk-go
      dependency-type: direct:production
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    dependabot[bot] authored Aug 11, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    430dbfe View commit details
  3. sigv4: support nil body (#673)

    Fixes #562
    Fixes #465
    
    Signed-off-by: Julien Pivotto <roidelapluie@o11y.eu>
    roidelapluie authored Aug 11, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    1dade5b View commit details

Commits on Aug 12, 2024

  1. Fix overflows of untyped int constants on 32-bit

    9223372036 as an untyped int constant will overflow on 32-bit archs.
    
    math.MaxInt64 is an untyped int constant (1<<63 - 1), and will thus also
    overflow on 32-bit if not cast to an int64.
    
    Signed-off-by: Daniel Swarbrick <daniel.swarbrick@gmail.com>
    dswarbrick committed Aug 12, 2024

    Verified

    This commit was signed with the committer’s verified signature.
    dswarbrick Daniel Swarbrick
    Copy the full SHA
    008d7b8 View commit details

Commits on Aug 13, 2024

  1. Merge pull request #675 from dswarbrick/fix-32bit-overflows

    Fix overflows of untyped int constants on 32-bit
    beorn7 authored Aug 13, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    79c0459 View commit details

Commits on Aug 14, 2024

  1. Update client_golang (#676)

    Update `github.com/prometheus/client_golang` to the latest release.
    
    Signed-off-by: SuperQ <superq@gmail.com>
    SuperQ authored Aug 14, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    2cac84e View commit details

Commits on Aug 20, 2024

  1. Update golangci lint (#679)

    * Update common Prometheus files
    
    Signed-off-by: prombot <prometheus-team@googlegroups.com>
    
    * Fix golint ci
    
    Signed-off-by: Julien <roidelapluie@o11y.eu>
    
    ---------
    
    Signed-off-by: prombot <prometheus-team@googlegroups.com>
    Signed-off-by: Julien <roidelapluie@o11y.eu>
    Co-authored-by: prombot <prometheus-team@googlegroups.com>
    roidelapluie and prombot authored Aug 20, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    cd4bcc0 View commit details

Commits on Aug 21, 2024

  1. expfmt: Add UTF-8 syntax support in text_parse.go (#670)

    Update expfmt/text_parse.go to support the new UTF-8 syntax
    
    ---------
    
    Signed-off-by: Federico Torres <federico.torres@grafana.com>
    fedetorres93 authored Aug 21, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    8968b6c View commit details

Commits on Aug 22, 2024

  1. Update common Prometheus files

    Signed-off-by: prombot <prometheus-team@googlegroups.com>
    prombot committed Aug 22, 2024
    Copy the full SHA
    29a2d2c View commit details

Commits on Aug 23, 2024

  1. Merge pull request #681 from prometheus/repo_sync

    Synchronize common files from prometheus/prometheus
    ArthurSens authored Aug 23, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    19d0796 View commit details

Commits on Aug 26, 2024

  1. Provide a method for explicitly checking label names for legacy valid…

    …ity. (#682)
    
    This is needed in Prometheus for modes when legacy validation has been explicitly requested but UTF-8 is otherwise enabled.
    
    Signed-off-by: Owen Williams <owen.williams@grafana.com>
    ywwg authored Aug 26, 2024

    Verified

    This commit was created on github.com and signed with GitHub’s verified signature.
    Copy the full SHA
    6623230 View commit details
8 changes: 4 additions & 4 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -24,16 +24,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Install Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
uses: actions/setup-go@0a12ed9d6a96ab950c8f026ed9f722fe0da7ef32 # v5.0.2
with:
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'
- name: Lint
uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v6.0.1
uses: golangci/golangci-lint-action@aaa42aa0628b4ae2578232a66b541047968fac86 # v6.1.0
with:
args: --verbose
version: v1.59.1
version: v1.60.2
2 changes: 1 addition & 1 deletion Makefile.common
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_
SKIP_GOLANGCI_LINT :=
GOLANGCI_LINT :=
GOLANGCI_LINT_OPTS ?=
GOLANGCI_LINT_VERSION ?= v1.59.1
GOLANGCI_LINT_VERSION ?= v1.60.2
# 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))
2 changes: 1 addition & 1 deletion config/http_config.go
Original file line number Diff line number Diff line change
@@ -964,7 +964,7 @@ func (rt *oauth2RoundTripper) RoundTrip(req *http.Request) (*http.Response, erro
}

rt.mtx.Lock()
rt.lastSecret = secret
rt.lastSecret = newSecret
rt.lastRT.Source = source
if rt.client != nil {
rt.client.CloseIdleConnections()
6 changes: 4 additions & 2 deletions config/http_config_test.go
Original file line number Diff line number Diff line change
@@ -1630,7 +1630,8 @@ endpoint_params:
t.Fatalf("Got unmarshalled config %v, expected %v", unmarshalledConfig, expectedConfig)
}

rt := NewOAuth2RoundTripper(NewInlineSecret(string(expectedConfig.ClientSecret)), &expectedConfig, http.DefaultTransport, &defaultHTTPClientOptions)
secret := NewInlineSecret(string(expectedConfig.ClientSecret))
rt := NewOAuth2RoundTripper(secret, &expectedConfig, http.DefaultTransport, &defaultHTTPClientOptions)

client := http.Client{
Transport: rt,
@@ -1800,7 +1801,8 @@ endpoint_params:
t.Fatalf("Got unmarshalled config %v, expected %v", unmarshalledConfig, expectedConfig)
}

rt := NewOAuth2RoundTripper(NewInlineSecret(string(expectedConfig.ClientSecret)), &expectedConfig, http.DefaultTransport, &defaultHTTPClientOptions)
secret := NewFileSecret(expectedConfig.ClientSecretFile)
rt := NewOAuth2RoundTripper(secret, &expectedConfig, http.DefaultTransport, &defaultHTTPClientOptions)

client := http.Client{
Transport: rt,
14 changes: 7 additions & 7 deletions expfmt/decode.go
Original file line number Diff line number Diff line change
@@ -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.
16 changes: 8 additions & 8 deletions expfmt/decode_test.go
Original file line number Diff line number Diff line change
@@ -423,7 +423,7 @@ func TestProtoMultiMessageDecoder(t *testing.T) {
}

buf := bytes.NewReader(data)
decoder := NewDecoder(buf, fmtProtoDelim)
decoder := NewDecoder(buf, FmtProtoDelim)
var metrics []*dto.MetricFamily
for {
var mf dto.MetricFamily
@@ -448,27 +448,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,
},
}

@@ -574,7 +574,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 {
24 changes: 12 additions & 12 deletions expfmt/encode.go
Original file line number Diff line number Diff line change
@@ -77,18 +77,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
@@ -110,26 +110,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
38 changes: 19 additions & 19 deletions expfmt/encode_test.go
Original file line number Diff line number Diff line change
@@ -222,56 +222,56 @@ func TestEncode(t *testing.T) {
// 1: Untyped ProtoDelim
{
metric: metric1,
format: fmtProtoDelim,
format: FmtProtoDelim,
},
// 2: Untyped fmtProtoCompact
// 2: Untyped FmtProtoCompact
{
metric: metric1,
format: fmtProtoCompact,
format: FmtProtoCompact,
},
// 3: Untyped fmtProtoText
// 3: Untyped FmtProtoText
{
metric: metric1,
format: fmtProtoText,
format: FmtProtoText,
},
// 4: Untyped fmtText
// 4: Untyped FmtText
{
metric: metric1,
format: fmtText,
format: FmtText,
expOut: `# TYPE foo_metric untyped
foo_metric 1.234
`,
},
// 5: Untyped fmtOpenMetrics_0_0_1
// 5: Untyped FmtOpenMetrics_0_0_1
{
metric: metric1,
format: fmtOpenMetrics_0_0_1,
format: FmtOpenMetrics_0_0_1,
expOut: `# TYPE foo_metric unknown
foo_metric 1.234
`,
},
// 6: Untyped fmtOpenMetrics_1_0_0
// 6: Untyped FmtOpenMetrics_1_0_0
{
metric: metric1,
format: fmtOpenMetrics_1_0_0,
format: FmtOpenMetrics_1_0_0,
expOut: `# TYPE foo_metric unknown
foo_metric 1.234
`,
},
// 7: Simple Counter fmtOpenMetrics_0_0_1 unit opted in
// 7: Simple Counter FmtOpenMetrics_0_0_1 unit opted in
{
metric: metric1,
format: fmtOpenMetrics_0_0_1,
format: FmtOpenMetrics_0_0_1,
options: []EncoderOption{WithUnit()},
expOut: `# TYPE foo_metric_seconds unknown
# UNIT foo_metric_seconds seconds
foo_metric_seconds 1.234
`,
},
// 8: Simple Counter fmtOpenMetrics_1_0_0 unit opted out
// 8: Simple Counter FmtOpenMetrics_1_0_0 unit opted out
{
metric: metric1,
format: fmtOpenMetrics_1_0_0,
format: FmtOpenMetrics_1_0_0,
expOut: `# TYPE foo_metric unknown
foo_metric 1.234
`,
@@ -310,7 +310,7 @@ foo_metric 1.234

func TestEscapedEncode(t *testing.T) {
var buff bytes.Buffer
delimEncoder := NewEncoder(&buff, fmtProtoDelim+"; escaping=underscores")
delimEncoder := NewEncoder(&buff, FmtProtoDelim+"; escaping=underscores")
metric := &dto.MetricFamily{
Name: proto.String("foo.metric"),
Type: dto.MetricType_UNTYPED.Enum(),
@@ -346,7 +346,7 @@ func TestEscapedEncode(t *testing.T) {

buff.Reset()

compactEncoder := NewEncoder(&buff, fmtProtoCompact)
compactEncoder := NewEncoder(&buff, FmtProtoCompact)
err = compactEncoder.Encode(metric)
if err != nil {
t.Errorf("unexpected error during encode: %s", err.Error())
@@ -359,7 +359,7 @@ func TestEscapedEncode(t *testing.T) {

buff.Reset()

protoTextEncoder := NewEncoder(&buff, fmtProtoText)
protoTextEncoder := NewEncoder(&buff, FmtProtoText)
err = protoTextEncoder.Encode(metric)
if err != nil {
t.Errorf("unexpected error during encode: %s", err.Error())
@@ -372,7 +372,7 @@ func TestEscapedEncode(t *testing.T) {

buff.Reset()

textEncoder := NewEncoder(&buff, fmtText)
textEncoder := NewEncoder(&buff, FmtText)
err = textEncoder.Encode(metric)
if err != nil {
t.Errorf("unexpected error during encode: %s", err.Error())
53 changes: 30 additions & 23 deletions expfmt/expfmt.go
Original file line number Diff line number Diff line change
@@ -32,24 +32,31 @@ type Format string
// it on the wire, new content-type strings will have to be agreed upon and
// added here.
const (
TextVersion = "0.0.4"
ProtoType = `application/vnd.google.protobuf`
ProtoProtocol = `io.prometheus.client.MetricFamily`
protoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
TextVersion = "0.0.4"
ProtoType = `application/vnd.google.protobuf`
ProtoProtocol = `io.prometheus.client.MetricFamily`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead.
ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
OpenMetricsType = `application/openmetrics-text`
OpenMetricsVersion_0_0_1 = "0.0.1"
OpenMetricsVersion_1_0_0 = "1.0.0"

// The Content-Type values for the different wire protocols. Note that these
// values are now unexported. If code was relying on comparisons to these
// constants, instead use FormatType().
fmtUnknown Format = `<unknown>`
fmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
fmtProtoDelim Format = protoFmt + ` encoding=delimited`
fmtProtoText Format = protoFmt + ` encoding=text`
fmtProtoCompact Format = protoFmt + ` encoding=compact-text`
fmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
fmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
// The Content-Type values for the different wire protocols. Do not do direct
// comparisons to these constants, instead use the comparison functions.
// Deprecated: Use expfmt.NewFormat(expfmt.TypeUnknown) instead.
FmtUnknown Format = `<unknown>`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeTextPlain) instead.
FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoDelim) instead.
FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoText) instead.
FmtProtoText Format = ProtoFmt + ` encoding=text`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeProtoCompact) instead.
FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead.
FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
// Deprecated: Use expfmt.NewFormat(expfmt.TypeOpenMetrics) instead.
FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
)

const (
@@ -79,30 +86,30 @@ const (
func NewFormat(t FormatType) Format {
switch t {
case TypeProtoCompact:
return fmtProtoCompact
return FmtProtoCompact
case TypeProtoDelim:
return fmtProtoDelim
return FmtProtoDelim
case TypeProtoText:
return fmtProtoText
return FmtProtoText
case TypeTextPlain:
return fmtText
return FmtText
case TypeOpenMetrics:
return fmtOpenMetrics_1_0_0
return FmtOpenMetrics_1_0_0
default:
return fmtUnknown
return FmtUnknown
}
}

// NewOpenMetricsFormat generates a new OpenMetrics format matching the
// specified version number.
func NewOpenMetricsFormat(version string) (Format, error) {
if version == OpenMetricsVersion_0_0_1 {
return fmtOpenMetrics_0_0_1, nil
return FmtOpenMetrics_0_0_1, nil
}
if version == OpenMetricsVersion_1_0_0 {
return fmtOpenMetrics_1_0_0, nil
return FmtOpenMetrics_1_0_0, nil
}
return fmtUnknown, fmt.Errorf("unknown open metrics version string")
return FmtUnknown, fmt.Errorf("unknown open metrics version string")
}

// FormatType deduces an overall FormatType for the given format.
14 changes: 7 additions & 7 deletions expfmt/expfmt_test.go
Original file line number Diff line number Diff line change
@@ -28,27 +28,27 @@ func TestToFormatType(t *testing.T) {
expected FormatType
}{
{
format: fmtProtoCompact,
format: FmtProtoCompact,
expected: TypeProtoCompact,
},
{
format: fmtProtoDelim,
format: FmtProtoDelim,
expected: TypeProtoDelim,
},
{
format: fmtProtoText,
format: FmtProtoText,
expected: TypeProtoText,
},
{
format: fmtOpenMetrics_1_0_0,
format: FmtOpenMetrics_1_0_0,
expected: TypeOpenMetrics,
},
{
format: fmtText,
format: FmtText,
expected: TypeTextPlain,
},
{
format: fmtOpenMetrics_0_0_1,
format: FmtOpenMetrics_0_0_1,
expected: TypeOpenMetrics,
},
{
@@ -104,7 +104,7 @@ func TestToEscapingScheme(t *testing.T) {
expected model.EscapingScheme
}{
{
format: fmtProtoCompact,
format: FmtProtoCompact,
expected: model.ValueEncodingEscaping,
},
{
2 changes: 1 addition & 1 deletion expfmt/openmetrics_create.go
Original file line number Diff line number Diff line change
@@ -477,7 +477,7 @@ func writeOpenMetricsNameAndLabelPairs(
if name != "" {
// If the name does not pass the legacy validity check, we must put the
// metric name inside the braces, quoted.
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
if !model.IsValidLegacyMetricName(name) {
metricInsideBraces = true
err := w.WriteByte(separator)
written++
4 changes: 2 additions & 2 deletions expfmt/text_create.go
Original file line number Diff line number Diff line change
@@ -354,7 +354,7 @@ func writeNameAndLabelPairs(
if name != "" {
// If the name does not pass the legacy validity check, we must put the
// metric name inside the braces.
if !model.IsValidLegacyMetricName(model.LabelValue(name)) {
if !model.IsValidLegacyMetricName(name) {
metricInsideBraces = true
err := w.WriteByte(separator)
written++
@@ -498,7 +498,7 @@ func writeInt(w enhancedWriter, i int64) (int, error) {
// writeName writes a string as-is if it complies with the legacy naming
// scheme, or escapes it in double quotes if not.
func writeName(w enhancedWriter, name string) (int, error) {
if model.IsValidLegacyMetricName(model.LabelValue(name)) {
if model.IsValidLegacyMetricName(name) {
return w.WriteString(name)
}
var written int
152 changes: 131 additions & 21 deletions expfmt/text_parse.go
Original file line number Diff line number Diff line change
@@ -22,9 +22,9 @@ import (
"math"
"strconv"
"strings"
"unicode/utf8"

dto "github.com/prometheus/client_model/go"

"google.golang.org/protobuf/proto"

"github.com/prometheus/common/model"
@@ -60,6 +60,7 @@ type TextParser struct {
currentMF *dto.MetricFamily
currentMetric *dto.Metric
currentLabelPair *dto.LabelPair
currentLabelPairs []*dto.LabelPair // Temporarily stores label pairs while parsing a metric line.

// The remaining member variables are only used for summaries/histograms.
currentLabels map[string]string // All labels including '__name__' but excluding 'quantile'/'le'
@@ -74,6 +75,7 @@ type TextParser struct {
// count and sum of that summary/histogram.
currentIsSummaryCount, currentIsSummarySum bool
currentIsHistogramCount, currentIsHistogramSum bool
currentMetricIsInsideBraces bool
}

// TextToMetricFamilies reads 'in' as the simple and flat text-based exchange
@@ -137,12 +139,14 @@ func (p *TextParser) reset(in io.Reader) {
}
p.currentQuantile = math.NaN()
p.currentBucket = math.NaN()
p.currentMF = nil
}

// startOfLine represents the state where the next byte read from p.buf is the
// start of a line (or whitespace leading up to it).
func (p *TextParser) startOfLine() stateFn {
p.lineCount++
p.currentMetricIsInsideBraces = false
if p.skipBlankTab(); p.err != nil {
// This is the only place that we expect to see io.EOF,
// which is not an error but the signal that we are done.
@@ -158,6 +162,9 @@ func (p *TextParser) startOfLine() stateFn {
return p.startComment
case '\n':
return p.startOfLine // Empty line, start the next one.
case '{':
p.currentMetricIsInsideBraces = true
return p.readingLabels
}
return p.readingMetricName
}
@@ -275,6 +282,8 @@ func (p *TextParser) startLabelName() stateFn {
return nil // Unexpected end of input.
}
if p.currentByte == '}' {
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
p.currentLabelPairs = nil
if p.skipBlankTab(); p.err != nil {
return nil // Unexpected end of input.
}
@@ -287,6 +296,38 @@ func (p *TextParser) startLabelName() stateFn {
p.parseError(fmt.Sprintf("invalid label name for metric %q", p.currentMF.GetName()))
return nil
}
if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
return nil // Unexpected end of input.
}
if p.currentByte != '=' {
if p.currentMetricIsInsideBraces {
if p.currentMF != nil && p.currentMF.GetName() != p.currentToken.String() {
p.parseError(fmt.Sprintf("multiple metric names %s %s", p.currentMF.GetName(), p.currentToken.String()))
return nil
}
switch p.currentByte {
case ',':
p.setOrCreateCurrentMF()
p.currentMetric = &dto.Metric{}
return p.startLabelName
case '}':
p.setOrCreateCurrentMF()
p.currentMetric = &dto.Metric{}
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
p.currentLabelPairs = nil
if p.skipBlankTab(); p.err != nil {
return nil // Unexpected end of input.
}
return p.readingValue
default:
p.parseError(fmt.Sprintf("unexpected end of metric name %q", p.currentByte))
return nil
}
}
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
p.currentLabelPairs = nil
return nil
}
p.currentLabelPair = &dto.LabelPair{Name: proto.String(p.currentToken.String())}
if p.currentLabelPair.GetName() == string(model.MetricNameLabel) {
p.parseError(fmt.Sprintf("label name %q is reserved", model.MetricNameLabel))
@@ -296,23 +337,17 @@ func (p *TextParser) startLabelName() stateFn {
// labels to 'real' labels.
if !(p.currentMF.GetType() == dto.MetricType_SUMMARY && p.currentLabelPair.GetName() == model.QuantileLabel) &&
!(p.currentMF.GetType() == dto.MetricType_HISTOGRAM && p.currentLabelPair.GetName() == model.BucketLabel) {
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPair)
}
if p.skipBlankTabIfCurrentBlankTab(); p.err != nil {
return nil // Unexpected end of input.
}
if p.currentByte != '=' {
p.parseError(fmt.Sprintf("expected '=' after label name, found %q", p.currentByte))
return nil
p.currentLabelPairs = append(p.currentLabelPairs, p.currentLabelPair)
}
// Check for duplicate label names.
labels := make(map[string]struct{})
for _, l := range p.currentMetric.Label {
for _, l := range p.currentLabelPairs {
lName := l.GetName()
if _, exists := labels[lName]; !exists {
labels[lName] = struct{}{}
} else {
p.parseError(fmt.Sprintf("duplicate label names for metric %q", p.currentMF.GetName()))
p.currentLabelPairs = nil
return nil
}
}
@@ -345,6 +380,7 @@ func (p *TextParser) startLabelValue() stateFn {
if p.currentQuantile, p.err = parseFloat(p.currentLabelPair.GetValue()); p.err != nil {
// Create a more helpful error message.
p.parseError(fmt.Sprintf("expected float as value for 'quantile' label, got %q", p.currentLabelPair.GetValue()))
p.currentLabelPairs = nil
return nil
}
} else {
@@ -371,12 +407,19 @@ func (p *TextParser) startLabelValue() stateFn {
return p.startLabelName

case '}':
if p.currentMF == nil {
p.parseError("invalid metric name")
return nil
}
p.currentMetric.Label = append(p.currentMetric.Label, p.currentLabelPairs...)
p.currentLabelPairs = nil
if p.skipBlankTab(); p.err != nil {
return nil // Unexpected end of input.
}
return p.readingValue
default:
p.parseError(fmt.Sprintf("unexpected end of label value %q", p.currentLabelPair.GetValue()))
p.currentLabelPairs = nil
return nil
}
}
@@ -585,6 +628,8 @@ func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
p.currentToken.WriteByte(p.currentByte)
case 'n':
p.currentToken.WriteByte('\n')
case '"':
p.currentToken.WriteByte('"')
default:
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
return
@@ -610,13 +655,45 @@ func (p *TextParser) readTokenUntilNewline(recognizeEscapeSequence bool) {
// but not into p.currentToken.
func (p *TextParser) readTokenAsMetricName() {
p.currentToken.Reset()
// A UTF-8 metric name must be quoted and may have escaped characters.
quoted := false
escaped := false
if !isValidMetricNameStart(p.currentByte) {
return
}
for {
p.currentToken.WriteByte(p.currentByte)
for p.err == nil {
if escaped {
switch p.currentByte {
case '\\':
p.currentToken.WriteByte(p.currentByte)
case 'n':
p.currentToken.WriteByte('\n')
case '"':
p.currentToken.WriteByte('"')
default:
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
return
}
escaped = false
} else {
switch p.currentByte {
case '"':
quoted = !quoted
if !quoted {
p.currentByte, p.err = p.buf.ReadByte()
return
}
case '\n':
p.parseError(fmt.Sprintf("metric name %q contains unescaped new-line", p.currentToken.String()))
return
case '\\':
escaped = true
default:
p.currentToken.WriteByte(p.currentByte)
}
}
p.currentByte, p.err = p.buf.ReadByte()
if p.err != nil || !isValidMetricNameContinuation(p.currentByte) {
if !isValidMetricNameContinuation(p.currentByte, quoted) || (!quoted && p.currentByte == ' ') {
return
}
}
@@ -628,13 +705,45 @@ func (p *TextParser) readTokenAsMetricName() {
// but not into p.currentToken.
func (p *TextParser) readTokenAsLabelName() {
p.currentToken.Reset()
// A UTF-8 label name must be quoted and may have escaped characters.
quoted := false
escaped := false
if !isValidLabelNameStart(p.currentByte) {
return
}
for {
p.currentToken.WriteByte(p.currentByte)
for p.err == nil {
if escaped {
switch p.currentByte {
case '\\':
p.currentToken.WriteByte(p.currentByte)
case 'n':
p.currentToken.WriteByte('\n')
case '"':
p.currentToken.WriteByte('"')
default:
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
return
}
escaped = false
} else {
switch p.currentByte {
case '"':
quoted = !quoted
if !quoted {
p.currentByte, p.err = p.buf.ReadByte()
return
}
case '\n':
p.parseError(fmt.Sprintf("label name %q contains unescaped new-line", p.currentToken.String()))
return
case '\\':
escaped = true
default:
p.currentToken.WriteByte(p.currentByte)
}
}
p.currentByte, p.err = p.buf.ReadByte()
if p.err != nil || !isValidLabelNameContinuation(p.currentByte) {
if !isValidLabelNameContinuation(p.currentByte, quoted) || (!quoted && p.currentByte == '=') {
return
}
}
@@ -660,6 +769,7 @@ func (p *TextParser) readTokenAsLabelValue() {
p.currentToken.WriteByte('\n')
default:
p.parseError(fmt.Sprintf("invalid escape sequence '\\%c'", p.currentByte))
p.currentLabelPairs = nil
return
}
escaped = false
@@ -718,19 +828,19 @@ func (p *TextParser) setOrCreateCurrentMF() {
}

func isValidLabelNameStart(b byte) bool {
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_'
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || b == '"'
}

func isValidLabelNameContinuation(b byte) bool {
return isValidLabelNameStart(b) || (b >= '0' && b <= '9')
func isValidLabelNameContinuation(b byte, quoted bool) bool {
return isValidLabelNameStart(b) || (b >= '0' && b <= '9') || (quoted && utf8.ValidString(string(b)))
}

func isValidMetricNameStart(b byte) bool {
return isValidLabelNameStart(b) || b == ':'
}

func isValidMetricNameContinuation(b byte) bool {
return isValidLabelNameContinuation(b) || b == ':'
func isValidMetricNameContinuation(b byte, quoted bool) bool {
return isValidLabelNameContinuation(b, quoted) || b == ':'
}

func isBlankOrTab(b byte) bool {
251 changes: 250 additions & 1 deletion expfmt/text_parse_test.go
Original file line number Diff line number Diff line change
@@ -385,6 +385,215 @@ request_duration_microseconds_count 2693
},
},
},
// 5: Quoted metric name and quoted label name with dots.
{
in: `
# HELP "my.noncompliant.metric" help text
# TYPE "my.noncompliant.metric" counter
{"my.noncompliant.metric","label.name"="value"} 1
`,
out: []*dto.MetricFamily{
{
Name: proto.String("my.noncompliant.metric"),
Help: proto.String("help text"),
Type: dto.MetricType_COUNTER.Enum(),
Metric: []*dto.Metric{
{
Label: []*dto.LabelPair{
{
Name: proto.String("label.name"),
Value: proto.String("value"),
},
},
Counter: &dto.Counter{
Value: proto.Float64(1),
},
},
},
},
},
},
// 6: Metric family with dots in name.
{
in: `
# HELP "name.with.dots" boring help
# TYPE "name.with.dots" counter
{"name.with.dots",labelname="val1",basename="basevalue"} 42.0
{"name.with.dots",labelname="val2",basename="basevalue"} 0.23 1234567890
`,
out: []*dto.MetricFamily{
{
Name: proto.String("name.with.dots"),
Help: proto.String("boring help"),
Type: dto.MetricType_COUNTER.Enum(),
Metric: []*dto.Metric{
{
Label: []*dto.LabelPair{
{
Name: proto.String("labelname"),
Value: proto.String("val1"),
},
{
Name: proto.String("basename"),
Value: proto.String("basevalue"),
},
},
Counter: &dto.Counter{
Value: proto.Float64(42),
},
},
{
Label: []*dto.LabelPair{
{
Name: proto.String("labelname"),
Value: proto.String("val2"),
},
{
Name: proto.String("basename"),
Value: proto.String("basevalue"),
},
},
Counter: &dto.Counter{
Value: proto.Float64(.23),
},
TimestampMs: proto.Int64(1234567890),
},
},
},
},
},
// 7: Metric family with dots in name, no labels.
{
in: `
# HELP "name.with.dots" boring help
# TYPE "name.with.dots" counter
{"name.with.dots"} 42.0
{"name.with.dots"} 0.23 1234567890
`,
out: []*dto.MetricFamily{
{
Name: proto.String("name.with.dots"),
Help: proto.String("boring help"),
Type: dto.MetricType_COUNTER.Enum(),
Metric: []*dto.Metric{
{
Counter: &dto.Counter{
Value: proto.Float64(42),
},
},
{
Counter: &dto.Counter{
Value: proto.Float64(.23),
},
TimestampMs: proto.Int64(1234567890),
},
},
},
},
},
// 8: Quoted metric name and quoted label names with dots and asterisks, special characters in label values.
{
in: `# HELP "gauge.name" gauge\ndoc\nstr\"ing
# TYPE "gauge.name" gauge
{"gauge.name","name.1"="val with\nnew line","name*2"="val with \\backslash and \"quotes\""} +Inf
{"gauge.name","name.1"="Björn","name*2"="佖佥"} 3.14e+42
`,
out: []*dto.MetricFamily{
{
Name: proto.String("gauge.name"),
Help: proto.String("gauge\ndoc\nstr\"ing"),
Type: dto.MetricType_GAUGE.Enum(),
Metric: []*dto.Metric{
{
Label: []*dto.LabelPair{
{
Name: proto.String("name.1"),
Value: proto.String("val with\nnew line"),
},
{
Name: proto.String("name*2"),
Value: proto.String("val with \\backslash and \"quotes\""),
},
},
Gauge: &dto.Gauge{
Value: proto.Float64(math.Inf(+1)),
},
},
{
Label: []*dto.LabelPair{
{
Name: proto.String("name.1"),
Value: proto.String("Björn"),
},
{
Name: proto.String("name*2"),
Value: proto.String("佖佥"),
},
},
Gauge: &dto.Gauge{
Value: proto.Float64(3.14e42),
},
},
},
},
},
},
// 9: Various escaped special characters in metric and label names.
{
in: `
# HELP "my\"noncompliant\nmetric\\" help text
# TYPE "my\"noncompliant\nmetric\\" counter
{"my\"noncompliant\nmetric\\","label\"name\n"="value"} 1
`,
out: []*dto.MetricFamily{
{
Name: proto.String("my\"noncompliant\nmetric\\"),
Help: proto.String("help text"),
Type: dto.MetricType_COUNTER.Enum(),
Metric: []*dto.Metric{
{
Label: []*dto.LabelPair{
{
Name: proto.String("label\"name\n"),
Value: proto.String("value"),
},
},
Counter: &dto.Counter{
Value: proto.Float64(1),
},
},
},
},
},
},
// 10: Quoted metric name, not the first element in the label set.
{
in: `
# HELP "my.noncompliant.metric" help text
# TYPE "my.noncompliant.metric" counter
{labelname="value", "my.noncompliant.metric"} 1
`,
out: []*dto.MetricFamily{
{
Name: proto.String("my.noncompliant.metric"),
Help: proto.String("help text"),
Type: dto.MetricType_COUNTER.Enum(),
Metric: []*dto.Metric{
{
Label: []*dto.LabelPair{
{
Name: proto.String("labelname"),
Value: proto.String("value"),
},
},
Counter: &dto.Counter{
Value: proto.Float64(1),
},
},
},
},
},
},
}

for i, scenario := range scenarios {
@@ -641,8 +850,48 @@ metric{quantile="0x1p-3"} 3.14
in: `metric{label="bla",label="bla"} 3.14`,
err: "text format parsing error in line 1: duplicate label names for metric",
},
// 34: Multiple quoted metric names.
{
in: `{"one.name","another.name"} 3.14`,
err: "text format parsing error in line 1: multiple metric names",
},
// 35: Invalid escape sequence in quoted metric name.
{
in: `{"a\xc5z",label="bla"} 3.14`,
err: "text format parsing error in line 1: invalid escape sequence",
},
// 36: Unexpected end of quoted metric name.
{
in: `{"metric.name".label="bla"} 3.14`,
err: "text format parsing error in line 1: unexpected end of metric name",
},
// 37: Invalid escape sequence in quoted metric name.
{
in: `
# TYPE "metric.name\t" counter
{"metric.name\t",label="bla"} 3.14
`,
err: "text format parsing error in line 2: invalid escape sequence",
},
// 38: Newline in quoted metric name.
{
in: `
# TYPE "metric
name" counter
{"metric
name",label="bla"} 3.14
`,
err: `text format parsing error in line 2: metric name "metric" contains unescaped new-line`,
},
// 39: Newline in quoted label name.
{
in: `
{"metric.name","new
line"="bla"} 3.14
`,
err: `text format parsing error in line 2: label name "new" contains unescaped new-line`,
},
}

for i, scenario := range scenarios {
_, err := parser.TextToMetricFamilies(strings.NewReader(scenario.in))
if err == nil {
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ require (
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f
github.com/prometheus/client_model v0.6.1
github.com/stretchr/testify v1.9.0
golang.org/x/net v0.26.0
golang.org/x/net v0.27.0
golang.org/x/oauth2 v0.21.0
google.golang.org/protobuf v1.34.2
gopkg.in/yaml.v2 v2.4.0
@@ -20,16 +20,16 @@ require (
require (
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.19.1 // indirect
github.com/prometheus/client_golang v1.20.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
17 changes: 9 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -4,8 +4,8 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -19,6 +19,7 @@ github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2E
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@@ -30,8 +31,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
@@ -44,12 +45,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc=
github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
4 changes: 2 additions & 2 deletions helpers/templates/time_test.go
Original file line number Diff line number Diff line change
@@ -89,7 +89,7 @@ func TestHumanizeTimestamp(t *testing.T) {
{name: "negative", input: -1, expected: "1969-12-31 23:59:59 +0000 UTC"},
{name: "one", input: 1, expected: "1970-01-01 00:00:01 +0000 UTC"},
{name: "past", input: 1234567, expected: "1970-01-15 06:56:07 +0000 UTC"},
{name: "future", input: 9223372036, expected: "2262-04-11 23:47:16 +0000 UTC"},
{name: "future", input: int64(9223372036), expected: "2262-04-11 23:47:16 +0000 UTC"},
// Uint
{name: "zero", input: uint64(0), expected: "1970-01-01 00:00:00 +0000 UTC"},
{name: "one", input: uint64(1), expected: "1970-01-01 00:00:01 +0000 UTC"},
@@ -118,6 +118,6 @@ func TestHumanizeTimestamp(t *testing.T) {
}

func TestHumanizeTimestampError(t *testing.T) {
_, err := HumanizeTimestamp(math.MaxInt64)
_, err := HumanizeTimestamp(int64(math.MaxInt64))
require.Error(t, err)
}
27 changes: 18 additions & 9 deletions model/labels.go
Original file line number Diff line number Diff line change
@@ -97,26 +97,35 @@ var LabelNameRE = regexp.MustCompile("^[a-zA-Z_][a-zA-Z0-9_]*$")
// therewith.
type LabelName string

// IsValid returns true iff name matches the pattern of LabelNameRE for legacy
// names, and iff it's valid UTF-8 if NameValidationScheme is set to
// UTF8Validation. For the legacy matching, it does not use LabelNameRE for the
// check but a much faster hardcoded implementation.
// IsValid returns true iff the name matches the pattern of LabelNameRE when
// NameValidationScheme is set to LegacyValidation, or valid UTF-8 if
// NameValidationScheme is set to UTF8Validation.
func (ln LabelName) IsValid() bool {
if len(ln) == 0 {
return false
}
switch NameValidationScheme {
case LegacyValidation:
for i, b := range ln {
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
return false
}
}
return ln.IsValidLegacy()
case UTF8Validation:
return utf8.ValidString(string(ln))
default:
panic(fmt.Sprintf("Invalid name validation scheme requested: %d", NameValidationScheme))
}
}

// IsValidLegacy returns true iff name matches the pattern of LabelNameRE for
// legacy names. It does not use LabelNameRE for the check but a much faster
// hardcoded implementation.
func (ln LabelName) IsValidLegacy() bool {
if len(ln) == 0 {
return false
}
for i, b := range ln {
if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || b == '_' || (b >= '0' && b <= '9' && i > 0)) {
return false
}
}
return true
}

20 changes: 10 additions & 10 deletions model/metric.go
Original file line number Diff line number Diff line change
@@ -161,7 +161,7 @@ func (m Metric) FastFingerprint() Fingerprint {
func IsValidMetricName(n LabelValue) bool {
switch NameValidationScheme {
case LegacyValidation:
return IsValidLegacyMetricName(n)
return IsValidLegacyMetricName(string(n))
case UTF8Validation:
if len(n) == 0 {
return false
@@ -176,7 +176,7 @@ func IsValidMetricName(n LabelValue) bool {
// legacy validation scheme regardless of the value of NameValidationScheme.
// This function, however, does not use MetricNameRE for the check but a much
// faster hardcoded implementation.
func IsValidLegacyMetricName(n LabelValue) bool {
func IsValidLegacyMetricName(n string) bool {
if len(n) == 0 {
return false
}
@@ -208,7 +208,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF
}

// If the name is nil, copy as-is, don't try to escape.
if v.Name == nil || IsValidLegacyMetricName(LabelValue(v.GetName())) {
if v.Name == nil || IsValidLegacyMetricName(v.GetName()) {
out.Name = v.Name
} else {
out.Name = proto.String(EscapeName(v.GetName(), scheme))
@@ -230,7 +230,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF

for _, l := range m.Label {
if l.GetName() == MetricNameLabel {
if l.Value == nil || IsValidLegacyMetricName(LabelValue(l.GetValue())) {
if l.Value == nil || IsValidLegacyMetricName(l.GetValue()) {
escaped.Label = append(escaped.Label, l)
continue
}
@@ -240,7 +240,7 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF
})
continue
}
if l.Name == nil || IsValidLegacyMetricName(LabelValue(l.GetName())) {
if l.Name == nil || IsValidLegacyMetricName(l.GetName()) {
escaped.Label = append(escaped.Label, l)
continue
}
@@ -256,10 +256,10 @@ func EscapeMetricFamily(v *dto.MetricFamily, scheme EscapingScheme) *dto.MetricF

func metricNeedsEscaping(m *dto.Metric) bool {
for _, l := range m.Label {
if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(LabelValue(l.GetValue())) {
if l.GetName() == MetricNameLabel && !IsValidLegacyMetricName(l.GetValue()) {
return true
}
if !IsValidLegacyMetricName(LabelValue(l.GetName())) {
if !IsValidLegacyMetricName(l.GetName()) {
return true
}
}
@@ -283,7 +283,7 @@ func EscapeName(name string, scheme EscapingScheme) string {
case NoEscaping:
return name
case UnderscoreEscaping:
if IsValidLegacyMetricName(LabelValue(name)) {
if IsValidLegacyMetricName(name) {
return name
}
for i, b := range name {
@@ -309,7 +309,7 @@ func EscapeName(name string, scheme EscapingScheme) string {
}
return escaped.String()
case ValueEncodingEscaping:
if IsValidLegacyMetricName(LabelValue(name)) {
if IsValidLegacyMetricName(name) {
return name
}
escaped.WriteString("U__")
@@ -452,6 +452,6 @@ func ToEscapingScheme(s string) (EscapingScheme, error) {
case EscapeValues:
return ValueEncodingEscaping, nil
default:
return NoEscaping, fmt.Errorf("unknown format scheme " + s)
return NoEscaping, fmt.Errorf("unknown format scheme %s", s)
}
}
4 changes: 2 additions & 2 deletions model/metric_test.go
Original file line number Diff line number Diff line change
@@ -595,10 +595,10 @@ func TestEscapeMetricFamily(t *testing.T) {
original := proto.Clone(scenario.input)
got := EscapeMetricFamily(scenario.input, scenario.scheme)
if !cmp.Equal(scenario.expected, got, cmpopts.IgnoreUnexported(unexportList...)) {
t.Errorf("unexpected difference in escaped output:" + cmp.Diff(scenario.expected, got, cmpopts.IgnoreUnexported(unexportList...)))
t.Errorf("unexpected difference in escaped output:\n%s", cmp.Diff(scenario.expected, got, cmpopts.IgnoreUnexported(unexportList...)))
}
if !cmp.Equal(scenario.input, original, cmpopts.IgnoreUnexported(unexportList...)) {
t.Errorf("input was mutated during escaping" + cmp.Diff(scenario.expected, got, cmpopts.IgnoreUnexported(unexportList...)))
t.Errorf("input was mutated during escaping:\n%s", cmp.Diff(scenario.expected, got, cmpopts.IgnoreUnexported(unexportList...)))
}
})
}
12 changes: 6 additions & 6 deletions sigv4/go.mod
Original file line number Diff line number Diff line change
@@ -5,28 +5,28 @@ go 1.20
replace github.com/prometheus/common => ../

require (
github.com/aws/aws-sdk-go v1.54.7
github.com/prometheus/client_golang v1.19.1
github.com/prometheus/common v0.53.0
github.com/aws/aws-sdk-go v1.55.5
github.com/prometheus/common v0.55.0
github.com/stretchr/testify v1.9.0
gopkg.in/yaml.v2 v2.4.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.20.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
21 changes: 11 additions & 10 deletions sigv4/go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
github.com/aws/aws-sdk-go v1.54.7 h1:k1wJ+NMOsXgq/Lsa0y1mS0DFoDeHFPcz2OjCq5H5Mjg=
github.com/aws/aws-sdk-go v1.54.7/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -15,6 +15,7 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
@@ -24,8 +25,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho=
github.com/prometheus/client_golang v1.20.0 h1:jBzTZ7B099Rg24tny+qngoynol8LtVYlA2bqx3vEloI=
github.com/prometheus/client_golang v1.20.0/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
@@ -34,12 +35,12 @@ github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjR
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
11 changes: 7 additions & 4 deletions sigv4/sigv4.go
Original file line number Diff line number Diff line change
@@ -110,11 +110,14 @@ func (rt *sigV4RoundTripper) RoundTrip(req *http.Request) (*http.Response, error
buf.Reset()
rt.pool.Put(buf)
}()
if _, err := io.Copy(buf, req.Body); err != nil {
return nil, err

if req.Body != nil {
if _, err := io.Copy(buf, req.Body); err != nil {
return nil, err
}
// Close the original body since we don't need it anymore.
_ = req.Body.Close()
}
// Close the original body since we don't need it anymore.
_ = req.Body.Close()

// Ensure our seeker is back at the start of the buffer once we return.
var seeker io.ReadSeeker = bytes.NewReader(buf.Bytes())
17 changes: 15 additions & 2 deletions sigv4/sigv4_test.go
Original file line number Diff line number Diff line change
@@ -23,10 +23,16 @@ import (
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
signer "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/stretchr/testify/require"
)

type RoundTripperFunc func(req *http.Request) (*http.Response, error)

// RoundTrip implements the RoundTripper interface.
func (rt RoundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
return rt(r)
}

func TestSigV4_Inferred_Region(t *testing.T) {
os.Setenv("AWS_ACCESS_KEY_ID", "secret")
os.Setenv("AWS_SECRET_ACCESS_KEY", "token")
@@ -50,7 +56,7 @@ func TestSigV4RoundTripper(t *testing.T) {

rt := &sigV4RoundTripper{
region: "us-east-2",
next: promhttp.RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
next: RoundTripperFunc(func(req *http.Request) (*http.Response, error) {
gotReq = req
return &http.Response{StatusCode: http.StatusOK}, nil
}),
@@ -101,4 +107,11 @@ func TestSigV4RoundTripper(t *testing.T) {

require.Equal(t, "/test/test", gotReq.URL.Path)
})

t.Run("No body", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, "https://example.com/test/test", nil)
require.NoError(t, err)
_, err = cli.Do(req)
require.NoError(t, err)
})
}