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/client_golang
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.2.1
Choose a base ref
...
head repository: prometheus/client_golang
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.3.0
Choose a head ref

Commits on Oct 18, 2019

  1. Remove old reference to basicMetricVec

    Contrary to the code comment, I see no `basicMetricVec` implementation.
    Grep'ing this project shows this is the only reference. So I suspect
    it's an outdated comment and can be removed to minimize confusion.
    
    I'm unclear whether other parts of that comment are also incorrect and
    need updating.
    
    Signed-off-by: Jeff Widman <jeff@jeffwidman.com>
    jeffwidman committed Oct 18, 2019
    Copy the full SHA
    0dc0c21 View commit details
  2. Merge pull request #666 from jeffwidman/patch-1

    Remove old reference to basicMetricVec
    beorn7 authored Oct 18, 2019
    Copy the full SHA
    1b4c821 View commit details

Commits on Oct 21, 2019

  1. rmeove Krasi from the maintainers.

    Signed-off-by: Krasi Georgiev <8903888+krasi-georgiev@users.noreply.github.com>
    krasi-georgiev committed Oct 21, 2019
    Copy the full SHA
    6453c28 View commit details

Commits on Oct 22, 2019

  1. Merge pull request #667 from krasi-georgiev/maintainers

    remove Krasi from the maintainers.
    beorn7 authored Oct 22, 2019
    Copy the full SHA
    49d8fa7 View commit details
  2. add graphite tags

    Signed-off-by: kamaev <timurkamaev@protonmail.com>
    kamaev committed Oct 22, 2019
    Copy the full SHA
    c333d15 View commit details
  3. fix tests

    Signed-off-by: kamaev <timurkamaev@protonmail.com>
    kamaev committed Oct 22, 2019
    Copy the full SHA
    06342cf View commit details

Commits on Oct 24, 2019

  1. Merge pull request #668 from kamaev/master

    Send Graphite metrics with tags
    beorn7 authored Oct 24, 2019
    Copy the full SHA
    333f01c View commit details

Commits on Nov 28, 2019

  1. Fix link to writing exporters guide

    Signed-off-by: Dean Coakley <dean.s.coakley@gmail.com>
    Dean-Coakley authored Nov 28, 2019
    Copy the full SHA
    508fc33 View commit details
  2. Merge pull request #686 from Dean-Coakley/patch-2

    Fix link to writing exporters guide
    beorn7 authored Nov 28, 2019
    Copy the full SHA
    f65e153 View commit details

Commits on Dec 4, 2019

  1. Fix typo

    Signed-off-by: beorn7 <beorn@grafana.com>
    beorn7 committed Dec 4, 2019
    Copy the full SHA
    9097a2c View commit details

Commits on Dec 9, 2019

  1. api client examples: avoid shadowing package with variable

    Signed-off-by: Beni Cherniavsky-Paskin <cben@redhat.com>
    cben committed Dec 9, 2019
    Copy the full SHA
    38c6752 View commit details
  2. Merge pull request #695 from cben/api-client-examples-shadowing

    api client examples: avoid shadowing package with variable
    beorn7 authored Dec 9, 2019
    Copy the full SHA
    0da4c3a View commit details
  3. Improve doc comment for NewGaugeFunc

    - Simplify confusing wording about concurrency safety.
    - Add link to example for info metric.
    
    Signed-off-by: beorn7 <beorn@grafana.com>
    beorn7 committed Dec 9, 2019
    Copy the full SHA
    de74638 View commit details

Commits on Dec 10, 2019

  1. Merge pull request #697 from prometheus/beorn7/doc

    Improve doc comment for NewGaugeFunc
    beorn7 authored Dec 10, 2019
    Copy the full SHA
    99d85f4 View commit details
  2. First pass unravel

    Signed-off-by: Joe Elliott <number101010@gmail.com>
    joe-elliott committed Dec 10, 2019
    Copy the full SHA
    7f42799 View commit details
  3. Refactor ~worked. All tests passing except one

    Signed-off-by: Joe Elliott <number101010@gmail.com>
    joe-elliott committed Dec 10, 2019
    Copy the full SHA
    393adc9 View commit details

Commits on Dec 11, 2019

  1. Fixed TestDoGetFallback test

    Signed-off-by: Joe Elliott <number101010@gmail.com>
    joe-elliott committed Dec 11, 2019
    Copy the full SHA
    bd85842 View commit details
  2. Moved warnings into apiclient

    Signed-off-by: Joe Elliott <number101010@gmail.com>
    joe-elliott committed Dec 11, 2019
    Copy the full SHA
    88792b1 View commit details

Commits on Dec 13, 2019

  1. Merge pull request #699 from joe-elliott/http-client-warnings

    Return Prometheus Warnings
    beorn7 authored Dec 13, 2019
    Copy the full SHA
    e7776d2 View commit details

Commits on Dec 20, 2019

  1. Update dependencies

    Signed-off-by: beorn7 <beorn@grafana.com>
    beorn7 committed Dec 20, 2019
    Copy the full SHA
    780f6ab View commit details
  2. Cut v1.3.0

    Signed-off-by: beorn7 <beorn@grafana.com>
    beorn7 committed Dec 20, 2019
    Copy the full SHA
    339a70f View commit details
  3. Merge pull request #700 from prometheus/beorn7/release

    Update dependencies and cut v1.3.0
    beorn7 authored Dec 20, 2019
    Copy the full SHA
    c42bebe View commit details
Showing with 455 additions and 225 deletions.
  1. +5 −0 CHANGELOG.md
  2. +1 −2 MAINTAINERS.md
  3. +1 −1 README.md
  4. +1 −1 VERSION
  5. +4 −31 api/client.go
  6. +0 −72 api/client_test.go
  7. +66 −22 api/prometheus/v1/api.go
  8. +162 −41 api/prometheus/v1/api_test.go
  9. +6 −6 api/prometheus/v1/example_test.go
  10. +5 −5 go.mod
  11. +13 −12 go.sum
  12. +6 −3 prometheus/gauge.go
  13. +46 −15 prometheus/graphite/bridge.go
  14. +137 −12 prometheus/graphite/bridge_test.go
  15. +1 −1 prometheus/histogram.go
  16. +1 −1 prometheus/vec.go
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.3.0 / 2019-12-21

* [FEATURE] Support tags in Graphite bridge. #668
* [BUGFIX] API client: Actually return Prometheus warnings. #699

## 1.2.1 / 2019-10-17

* [BUGFIX] Fix regression in the implementation of `Registerer.Unregister`. #663
3 changes: 1 addition & 2 deletions MAINTAINERS.md
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
* Krasi Georgiev <kgeorgie@redhat.com> @krasi-georgiev for `api/...`
* Björn Rabenstein <beorn@grafana.com> @beorn7 for everything else
* Björn Rabenstein <beorn@grafana.com> @beorn7
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ This is the [Go](http://golang.org) client library for
instrumenting application code, and one for creating clients that talk to the
Prometheus HTTP API.

__This library requires Go1.9 or later.__ The mimimum required patch releases for older Go versions are Go1.9.7 and Go1.10.3.
__This library requires Go1.9 or later.__ The minimum required patch releases for older Go versions are Go1.9.7 and Go1.10.3.

## Important note about releases and stability

2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.1
1.3.0
35 changes: 4 additions & 31 deletions api/client.go
Original file line number Diff line number Diff line change
@@ -25,8 +25,6 @@ import (
"time"
)

type Warnings []string

// DefaultRoundTripper is used if no RoundTripper is set in Config.
var DefaultRoundTripper http.RoundTripper = &http.Transport{
Proxy: http.ProxyFromEnvironment,
@@ -57,32 +55,7 @@ func (cfg *Config) roundTripper() http.RoundTripper {
// Client is the interface for an API client.
type Client interface {
URL(ep string, args map[string]string) *url.URL
Do(context.Context, *http.Request) (*http.Response, []byte, Warnings, error)
}

// DoGetFallback will attempt to do the request as-is, and on a 405 it will fallback to a GET request.
func DoGetFallback(c Client, ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error) {
req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(args.Encode()))
if err != nil {
return nil, nil, nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, body, warnings, err := c.Do(ctx, req)
if resp != nil && resp.StatusCode == http.StatusMethodNotAllowed {
u.RawQuery = args.Encode()
req, err = http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return nil, nil, warnings, err
}

} else {
if err != nil {
return resp, body, warnings, err
}
return resp, body, warnings, nil
}
return c.Do(ctx, req)
Do(context.Context, *http.Request) (*http.Response, []byte, error)
}

// NewClient returns a new Client.
@@ -120,7 +93,7 @@ func (c *httpClient) URL(ep string, args map[string]string) *url.URL {
return &u
}

func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, Warnings, error) {
func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, error) {
if ctx != nil {
req = req.WithContext(ctx)
}
@@ -132,7 +105,7 @@ func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response,
}()

if err != nil {
return nil, nil, nil, err
return nil, nil, err
}

var body []byte
@@ -152,5 +125,5 @@ func (c *httpClient) Do(ctx context.Context, req *http.Request) (*http.Response,
case <-done:
}

return resp, body, nil, err
return resp, body, err
}
72 changes: 0 additions & 72 deletions api/client_test.go
Original file line number Diff line number Diff line change
@@ -14,10 +14,7 @@
package api

import (
"context"
"encoding/json"
"net/http"
"net/http/httptest"
"net/url"
"testing"
)
@@ -114,72 +111,3 @@ func TestClientURL(t *testing.T) {
}
}
}

func TestDoGetFallback(t *testing.T) {
v := url.Values{"a": []string{"1", "2"}}

type testResponse struct {
Values string
Method string
}

// Start a local HTTP server.
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
req.ParseForm()
r := &testResponse{
Values: req.Form.Encode(),
Method: req.Method,
}

body, _ := json.Marshal(r)

if req.Method == http.MethodPost {
if req.URL.Path == "/blockPost" {
http.Error(w, string(body), http.StatusMethodNotAllowed)
return
}
}

w.Write(body)
}))
// Close the server when test finishes.
defer server.Close()

u, err := url.Parse(server.URL)
if err != nil {
t.Fatal(err)
}
client := &httpClient{client: *(server.Client())}

// Do a post, and ensure that the post succeeds.
_, b, _, err := DoGetFallback(client, context.TODO(), u, v)
if err != nil {
t.Fatalf("Error doing local request: %v", err)
}
resp := &testResponse{}
if err := json.Unmarshal(b, resp); err != nil {
t.Fatal(err)
}
if resp.Method != http.MethodPost {
t.Fatalf("Mismatch method")
}
if resp.Values != v.Encode() {
t.Fatalf("Mismatch in values")
}

// Do a fallbcak to a get.
u.Path = "/blockPost"
_, b, _, err = DoGetFallback(client, context.TODO(), u, v)
if err != nil {
t.Fatalf("Error doing local request: %v", err)
}
if err := json.Unmarshal(b, resp); err != nil {
t.Fatal(err)
}
if resp.Method != http.MethodGet {
t.Fatalf("Mismatch method")
}
if resp.Values != v.Encode() {
t.Fatalf("Mismatch in values")
}
}
88 changes: 66 additions & 22 deletions api/prometheus/v1/api.go
Original file line number Diff line number Diff line change
@@ -21,7 +21,9 @@ import (
"fmt"
"math"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"unsafe"

@@ -228,15 +230,15 @@ type API interface {
// Flags returns the flag values that Prometheus was launched with.
Flags(ctx context.Context) (FlagsResult, error)
// LabelNames returns all the unique label names present in the block in sorted order.
LabelNames(ctx context.Context) ([]string, api.Warnings, error)
LabelNames(ctx context.Context) ([]string, Warnings, error)
// LabelValues performs a query for the values of the given label.
LabelValues(ctx context.Context, label string) (model.LabelValues, api.Warnings, error)
LabelValues(ctx context.Context, label string) (model.LabelValues, Warnings, error)
// Query performs a query for the given time.
Query(ctx context.Context, query string, ts time.Time) (model.Value, api.Warnings, error)
Query(ctx context.Context, query string, ts time.Time) (model.Value, Warnings, error)
// QueryRange performs a query for the given range.
QueryRange(ctx context.Context, query string, r Range) (model.Value, api.Warnings, error)
QueryRange(ctx context.Context, query string, r Range) (model.Value, Warnings, error)
// Series finds series by label matchers.
Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, api.Warnings, error)
Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, Warnings, error)
// Snapshot creates a snapshot of all current data into snapshots/<datetime>-<rand>
// under the TSDB's data directory and returns the directory as response.
Snapshot(ctx context.Context, skipHead bool) (SnapshotResult, error)
@@ -515,11 +517,15 @@ func (qr *queryResult) UnmarshalJSON(b []byte) error {
//
// It is safe to use the returned API from multiple goroutines.
func NewAPI(c api.Client) API {
return &httpAPI{client: apiClient{c}}
return &httpAPI{
client: &apiClientImpl{
client: c,
},
}
}

type httpAPI struct {
client api.Client
client apiClient
}

func (h *httpAPI) Alerts(ctx context.Context) (AlertsResult, error) {
@@ -624,7 +630,7 @@ func (h *httpAPI) Flags(ctx context.Context) (FlagsResult, error) {
return res, json.Unmarshal(body, &res)
}

func (h *httpAPI) LabelNames(ctx context.Context) ([]string, api.Warnings, error) {
func (h *httpAPI) LabelNames(ctx context.Context) ([]string, Warnings, error) {
u := h.client.URL(epLabels, nil)
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
@@ -638,7 +644,7 @@ func (h *httpAPI) LabelNames(ctx context.Context) ([]string, api.Warnings, error
return labelNames, w, json.Unmarshal(body, &labelNames)
}

func (h *httpAPI) LabelValues(ctx context.Context, label string) (model.LabelValues, api.Warnings, error) {
func (h *httpAPI) LabelValues(ctx context.Context, label string) (model.LabelValues, Warnings, error) {
u := h.client.URL(epLabelValues, map[string]string{"name": label})
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
@@ -652,7 +658,7 @@ func (h *httpAPI) LabelValues(ctx context.Context, label string) (model.LabelVal
return labelValues, w, json.Unmarshal(body, &labelValues)
}

func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time) (model.Value, api.Warnings, error) {
func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time) (model.Value, Warnings, error) {
u := h.client.URL(epQuery, nil)
q := u.Query()

@@ -661,7 +667,7 @@ func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time) (model.
q.Set("time", formatTime(ts))
}

_, body, warnings, err := api.DoGetFallback(h.client, ctx, u, q)
_, body, warnings, err := h.client.DoGetFallback(ctx, u, q)
if err != nil {
return nil, warnings, err
}
@@ -670,7 +676,7 @@ func (h *httpAPI) Query(ctx context.Context, query string, ts time.Time) (model.
return model.Value(qres.v), warnings, json.Unmarshal(body, &qres)
}

func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range) (model.Value, api.Warnings, error) {
func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range) (model.Value, Warnings, error) {
u := h.client.URL(epQueryRange, nil)
q := u.Query()

@@ -679,7 +685,7 @@ func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range) (model.
q.Set("end", formatTime(r.End))
q.Set("step", strconv.FormatFloat(r.Step.Seconds(), 'f', -1, 64))

_, body, warnings, err := api.DoGetFallback(h.client, ctx, u, q)
_, body, warnings, err := h.client.DoGetFallback(ctx, u, q)
if err != nil {
return nil, warnings, err
}
@@ -689,7 +695,7 @@ func (h *httpAPI) QueryRange(ctx context.Context, query string, r Range) (model.
return model.Value(qres.v), warnings, json.Unmarshal(body, &qres)
}

func (h *httpAPI) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, api.Warnings, error) {
func (h *httpAPI) Series(ctx context.Context, matches []string, startTime time.Time, endTime time.Time) ([]model.LabelSet, Warnings, error) {
u := h.client.URL(epSeries, nil)
q := u.Query()

@@ -796,10 +802,19 @@ func (h *httpAPI) TargetsMetadata(ctx context.Context, matchTarget string, metri
return res, json.Unmarshal(body, &res)
}

// Warnings is an array of non critical errors
type Warnings []string

// apiClient wraps a regular client and processes successful API responses.
// Successful also includes responses that errored at the API level.
type apiClient struct {
api.Client
type apiClient interface {
URL(ep string, args map[string]string) *url.URL
Do(context.Context, *http.Request) (*http.Response, []byte, Warnings, error)
DoGetFallback(ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error)
}

type apiClientImpl struct {
client api.Client
}

type apiResponse struct {
@@ -825,17 +840,21 @@ func errorTypeAndMsgFor(resp *http.Response) (ErrorType, string) {
return ErrBadResponse, fmt.Sprintf("bad response code %d", resp.StatusCode)
}

func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, api.Warnings, error) {
resp, body, warnings, err := c.Client.Do(ctx, req)
func (h *apiClientImpl) URL(ep string, args map[string]string) *url.URL {
return h.client.URL(ep, args)
}

func (h *apiClientImpl) Do(ctx context.Context, req *http.Request) (*http.Response, []byte, Warnings, error) {
resp, body, err := h.client.Do(ctx, req)
if err != nil {
return resp, body, warnings, err
return resp, body, nil, err
}

code := resp.StatusCode

if code/100 != 2 && !apiError(code) {
errorType, errorMsg := errorTypeAndMsgFor(resp)
return resp, body, warnings, &Error{
return resp, body, nil, &Error{
Type: errorType,
Msg: errorMsg,
Detail: string(body),
@@ -846,7 +865,7 @@ func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, [

if http.StatusNoContent != code {
if jsonErr := json.Unmarshal(body, &result); jsonErr != nil {
return resp, body, warnings, &Error{
return resp, body, nil, &Error{
Type: ErrBadResponse,
Msg: jsonErr.Error(),
}
@@ -867,10 +886,35 @@ func (c apiClient) Do(ctx context.Context, req *http.Request) (*http.Response, [
}
}

return resp, []byte(result.Data), warnings, err
return resp, []byte(result.Data), result.Warnings, err

}

// DoGetFallback will attempt to do the request as-is, and on a 405 it will fallback to a GET request.
func (h *apiClientImpl) DoGetFallback(ctx context.Context, u *url.URL, args url.Values) (*http.Response, []byte, Warnings, error) {
req, err := http.NewRequest(http.MethodPost, u.String(), strings.NewReader(args.Encode()))
if err != nil {
return nil, nil, nil, err
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

resp, body, warnings, err := h.Do(ctx, req)
if resp != nil && resp.StatusCode == http.StatusMethodNotAllowed {
u.RawQuery = args.Encode()
req, err = http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return nil, nil, warnings, err
}

} else {
if err != nil {
return resp, body, warnings, err
}
return resp, body, warnings, nil
}
return h.Do(ctx, req)
}

func formatTime(t time.Time) string {
return strconv.FormatFloat(float64(t.Unix())+float64(t.Nanosecond())/1e9, 'f', -1, 64)
}
Loading