Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions prometheus/push/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import (
"net/http"
"net/url"
"strings"
"time"

"github.com/prometheus/common/expfmt"
"github.com/prometheus/common/model"
Expand Down Expand Up @@ -133,6 +134,19 @@ func (p *Pusher) PushContext(ctx context.Context) error {
return p.push(ctx, http.MethodPut)
}

// PushWithTimeout is like PushContext but overrides the the provided
// context with a separate timeout. When a job fails due to a
// higher-level context being canceled (for example, a global timeout)
// it is easy to reuse that context to push metrics, which fails
// immediately and metrics pertaining to the original failure will be
// lost. Use this method for an additional grace period beyond the
// original context's deadline.
func (p *Pusher) PushWithTimeout(ctx context.Context, grace time.Duration) error {
ctx, cancel := context.WithTimeout(context.WithoutCancel(ctx), grace)
defer cancel()
return p.PushContext(ctx)
}

// Add works like push, but only previously pushed metrics with the same name
// (and the same job and other grouping labels) will be replaced. (It uses HTTP
// method “POST” to push to the Pushgateway.)
Expand Down
14 changes: 14 additions & 0 deletions prometheus/push/push_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ package push

import (
"bytes"
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"testing"
"time"

"github.com/prometheus/common/expfmt"

Expand Down Expand Up @@ -306,4 +308,16 @@ func TestPush(t *testing.T) {
if lastHeader == nil || lastHeader.Get("Authorization") == "" {
t.Error("empty Authorization header")
}

// Make sure a canceled context fails, and a reset cancelation
// timeout works.
canceled, cancel := context.WithCancel(t.Context())
cancel()
if err := New(pgwOK.URL, "test-timeout").PushContext(canceled); !errors.Is(err, context.Canceled) {
t.Errorf("expected canceled push to have failed with %v, not %v", context.Canceled, err)
}

if err := New(pgwOK.URL, "test-timeout").PushWithTimeout(canceled, time.Hour); err != nil {
t.Errorf("expected uncanceled push to have succeeded, not %v", err)
}
}
Loading