Skip to content

Commit 811a3a9

Browse files
committed
Merge pull request #99 from prometheus/beorn7/push-collector
Add functions to push individual collectors to a Pushgateway.
2 parents f5ccf20 + f3cda15 commit 811a3a9

File tree

3 files changed

+92
-26
lines changed

3 files changed

+92
-26
lines changed

prometheus/examples_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ import (
1818
"fmt"
1919
"math"
2020
"net/http"
21+
"os"
2122
"runtime"
2223
"sort"
24+
"time"
2325

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

@@ -498,3 +500,19 @@ func ExampleHistogram() {
498500
// >
499501
// >
500502
}
503+
504+
func ExamplePushCollectors() {
505+
hostname, _ := os.Hostname()
506+
completionTime := prometheus.NewGauge(prometheus.GaugeOpts{
507+
Name: "db_backup_last_completion_time",
508+
Help: "The timestamp of the last succesful completion of a DB backup.",
509+
})
510+
completionTime.Set(float64(time.Now().Unix()))
511+
if err := prometheus.PushCollectors(
512+
"db_backup", hostname,
513+
"http://pushgateway:9091",
514+
completionTime,
515+
); err != nil {
516+
fmt.Println("Could not push completion time to Pushgateway:", err)
517+
}
518+
}

prometheus/push.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2015 The Prometheus Authors
2+
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// you may not use this file except in compliance with the License.
4+
// You may obtain a copy of the License at
5+
//
6+
// http://www.apache.org/licenses/LICENSE-2.0
7+
//
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
// See the License for the specific language governing permissions and
12+
// limitations under the License.
13+
14+
// Copyright (c) 2013, The Prometheus Authors
15+
// All rights reserved.
16+
//
17+
// Use of this source code is governed by a BSD-style license that can be found
18+
// in the LICENSE file.
19+
20+
package prometheus
21+
22+
// Push triggers a metric collection by the default registry and pushes all
23+
// collected metrics to the Pushgateway specified by addr. See the Pushgateway
24+
// documentation for detailed implications of the job and instance
25+
// parameter. instance can be left empty. You can use just host:port or ip:port
26+
// as url, in which case 'http://' is added automatically. You can also include
27+
// the schema in the URL. However, do not include the '/metrics/jobs/...' part.
28+
//
29+
// Note that all previously pushed metrics with the same job and instance will
30+
// be replaced with the metrics pushed by this call. (It uses HTTP method 'PUT'
31+
// to push to the Pushgateway.)
32+
func Push(job, instance, url string) error {
33+
return defRegistry.Push(job, instance, url, "PUT")
34+
}
35+
36+
// PushAdd works like Push, but only previously pushed metrics with the same
37+
// name (and the same job and instance) will be replaced. (It uses HTTP method
38+
// 'POST' to push to the Pushgateway.)
39+
func PushAdd(job, instance, url string) error {
40+
return defRegistry.Push(job, instance, url, "POST")
41+
}
42+
43+
// PushCollectors works like Push, but it does not collect from the default
44+
// registry. Instead, it collects from the provided collectors. It is a
45+
// convenient way to push only a few metrics.
46+
func PushCollectors(job, instance, url string, collectors ...Collector) error {
47+
return pushCollectors(job, instance, url, "PUT", collectors...)
48+
}
49+
50+
// PushAddCollectors works like PushAdd, but it does not collect from the
51+
// default registry. Instead, it collects from the provided collectors. It is a
52+
// convenient way to push only a few metrics.
53+
func PushAddCollectors(job, instance, url string, collectors ...Collector) error {
54+
return pushCollectors(job, instance, url, "POST", collectors...)
55+
}
56+
57+
func pushCollectors(job, instance, url, method string, collectors ...Collector) error {
58+
r := newRegistry()
59+
for _, collector := range collectors {
60+
if _, err := r.Register(collector); err != nil {
61+
return err
62+
}
63+
}
64+
return r.Push(job, instance, url, method)
65+
}

prometheus/registry.go

Lines changed: 9 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func Unregister(c Collector) bool {
158158
// SetMetricFamilyInjectionHook sets a function that is called whenever metrics
159159
// are collected. The hook function must be set before metrics collection begins
160160
// (i.e. call SetMetricFamilyInjectionHook before setting the HTTP handler.) The
161-
// MetricFamily protobufs returned by the hook function are added to the
161+
// MetricFamily protobufs returned by the hook function areadded to the
162162
// delivered metrics. Each returned MetricFamily must have a unique name (also
163163
// taking into account the MetricFamilies created in the regular way).
164164
//
@@ -187,26 +187,6 @@ func EnableCollectChecks(b bool) {
187187
defRegistry.collectChecksEnabled = b
188188
}
189189

190-
// Push triggers a metric collection and pushes all collected metrics to the
191-
// Pushgateway specified by addr. See the Pushgateway documentation for detailed
192-
// implications of the job and instance parameter. instance can be left
193-
// empty. The Pushgateway will then use the client's IP number instead. Use just
194-
// host:port or ip:port ass addr. (Don't add 'http://' or any path.)
195-
//
196-
// Note that all previously pushed metrics with the same job and instance will
197-
// be replaced with the metrics pushed by this call. (It uses HTTP method 'PUT'
198-
// to push to the Pushgateway.)
199-
func Push(job, instance, addr string) error {
200-
return defRegistry.Push(job, instance, addr, "PUT")
201-
}
202-
203-
// PushAdd works like Push, but only previously pushed metrics with the same
204-
// name (and the same job and instance) will be replaced. (It uses HTTP method
205-
// 'POST' to push to the Pushgateway.)
206-
func PushAdd(job, instance, addr string) error {
207-
return defRegistry.Push(job, instance, addr, "POST")
208-
}
209-
210190
// encoder is a function that writes a dto.MetricFamily to an io.Writer in a
211191
// certain encoding. It returns the number of bytes written and any error
212192
// encountered. Note that ext.WriteDelimited and text.MetricFamilyToText are
@@ -346,10 +326,13 @@ func (r *registry) Unregister(c Collector) bool {
346326
return true
347327
}
348328

349-
func (r *registry) Push(job, instance, addr, method string) error {
350-
u := fmt.Sprintf("http://%s/metrics/jobs/%s", addr, url.QueryEscape(job))
329+
func (r *registry) Push(job, instance, pushURL, method string) error {
330+
if !strings.Contains(pushURL, "://") {
331+
pushURL = "http://" + pushURL
332+
}
333+
pushURL = fmt.Sprintf("%s/metrics/jobs/%s", pushURL, url.QueryEscape(job))
351334
if instance != "" {
352-
u += "/instances/" + url.QueryEscape(instance)
335+
pushURL += "/instances/" + url.QueryEscape(instance)
353336
}
354337
buf := r.getBuf()
355338
defer r.giveBuf(buf)
@@ -359,7 +342,7 @@ func (r *registry) Push(job, instance, addr, method string) error {
359342
}
360343
return err
361344
}
362-
req, err := http.NewRequest(method, u, buf)
345+
req, err := http.NewRequest(method, pushURL, buf)
363346
if err != nil {
364347
return err
365348
}
@@ -370,7 +353,7 @@ func (r *registry) Push(job, instance, addr, method string) error {
370353
}
371354
defer resp.Body.Close()
372355
if resp.StatusCode != 202 {
373-
return fmt.Errorf("unexpected status code %d while pushing to %s", resp.StatusCode, u)
356+
return fmt.Errorf("unexpected status code %d while pushing to %s", resp.StatusCode, pushURL)
374357
}
375358
return nil
376359
}

0 commit comments

Comments
 (0)