Record scrape health timeseries per target.

This commit is contained in:
Julius Volz 2013-04-16 17:22:10 +02:00
parent fdea26e359
commit 8c9e9632a8
3 changed files with 40 additions and 13 deletions

View file

@ -13,11 +13,16 @@
package model package model
// The label name used to indicate the metric name of a timeseries. const (
const MetricNameLabel = LabelName("name") // The label name indicating the metric name of a timeseries.
MetricNameLabel = LabelName("name")
// The label name used to indicate the job from which a timeseries was scraped. // The label name indicating the job from which a timeseries was scraped.
const JobLabel = LabelName("job") JobLabel = LabelName("job")
// The label name indicating the instance from which a timeseries was scraped.
InstanceLabel = LabelName("instance")
// The metric name for the synthetic health variable.
ScrapeHealthMetricName = LabelValue("up")
)
// A LabelName is a key for a LabelSet or Metric. It has a value associated // A LabelName is a key for a LabelSet or Metric. It has a value associated
// therewith. // therewith.

View file

@ -24,10 +24,6 @@ import (
"time" "time"
) )
const (
instance = "instance"
)
var ( var (
localhostRepresentations = []string{"http://127.0.0.1", "http://localhost"} localhostRepresentations = []string{"http://127.0.0.1", "http://localhost"}
) )
@ -140,14 +136,42 @@ func NewTarget(address string, deadline time.Duration, baseLabels model.LabelSet
return target return target
} }
func (t *target) recordScrapeHealth(results chan format.Result, timestamp time.Time, healthy bool) {
metric := model.Metric{}
for label, value := range t.baseLabels {
metric[label] = value
}
metric[model.MetricNameLabel] = model.ScrapeHealthMetricName
healthValue := model.SampleValue(0)
if healthy {
healthValue = model.SampleValue(1)
}
sample := model.Sample{
Metric: metric,
Timestamp: timestamp,
Value: healthValue,
}
results <- format.Result{
Err: nil,
Sample: sample,
}
}
func (t *target) Scrape(earliest time.Time, results chan format.Result) (err error) { func (t *target) Scrape(earliest time.Time, results chan format.Result) (err error) {
now := time.Now()
defer func() { defer func() {
futureState := t.state futureState := t.state
switch err { switch err {
case nil: case nil:
t.recordScrapeHealth(results, now, true)
futureState = ALIVE futureState = ALIVE
default: default:
t.recordScrapeHealth(results, now, false)
futureState = UNREACHABLE futureState = UNREACHABLE
} }
@ -162,8 +186,6 @@ func (t *target) Scrape(earliest time.Time, results chan format.Result) (err err
done <- true done <- true
}() }()
now := time.Now()
var resp *http.Response // Don't shadow "err" from the enclosing function. var resp *http.Response // Don't shadow "err" from the enclosing function.
resp, err = http.Get(t.Address()) resp, err = http.Get(t.Address())
if err != nil { if err != nil {
@ -179,7 +201,7 @@ func (t *target) Scrape(earliest time.Time, results chan format.Result) (err err
// XXX: This is a wart; we need to handle this more gracefully down the // XXX: This is a wart; we need to handle this more gracefully down the
// road, especially once we have service discovery support. // road, especially once we have service discovery support.
baseLabels := model.LabelSet{instance: model.LabelValue(t.Address())} baseLabels := model.LabelSet{model.InstanceLabel: model.LabelValue(t.Address())}
for baseLabel, baseValue := range t.baseLabels { for baseLabel, baseValue := range t.baseLabels {
baseLabels[baseLabel] = baseValue baseLabels[baseLabel] = baseValue
} }

View file

@ -25,7 +25,7 @@ func TestTargetScrapeUpdatesState(t *testing.T) {
state: UNKNOWN, state: UNKNOWN,
address: "bad schema", address: "bad schema",
} }
testTarget.Scrape(time.Time{}, make(chan format.Result)) testTarget.Scrape(time.Time{}, make(chan format.Result, 2))
if testTarget.state != UNREACHABLE { if testTarget.state != UNREACHABLE {
t.Errorf("Expected target state %v, actual: %v", UNREACHABLE, testTarget.state) t.Errorf("Expected target state %v, actual: %v", UNREACHABLE, testTarget.state)
} }