Merge pull request #330 from prometheus/feature/interface/tabular-targets

Represent targets in a tabular interface.
This commit is contained in:
Matt T. Proud 2013-07-15 06:24:18 -07:00
commit 4781e2a578
6 changed files with 65 additions and 38 deletions

View file

@ -25,7 +25,7 @@ const (
// The base units for the exponential backoff. // The base units for the exponential backoff.
DEFAULT_BACKOFF_VALUE_UNIT = time.Second DEFAULT_BACKOFF_VALUE_UNIT = time.Second
// The maximum allowed backoff time. // The maximum allowed backoff time.
MAXIMUM_BACKOFF_VALUE = 30 * time.Minute MAXIMUM_BACKOFF_VALUE = 2 * time.Minute
) )
// scheduler is an interface that various scheduling strategies must fulfill // scheduler is an interface that various scheduling strategies must fulfill

View file

@ -97,7 +97,10 @@ type Target interface {
// time, but it should occur no sooner than it. // time, but it should occur no sooner than it.
// //
// Right now, this is used as the sorting key in TargetPool. // Right now, this is used as the sorting key in TargetPool.
scheduledFor() time.Time ScheduledFor() time.Time
// EstimatedTimeToExecute emits the amount of time until the next prospective
// scheduling opportunity for this target.
EstimatedTimeToExecute() time.Duration
// Return the last encountered scrape error, if any. // Return the last encountered scrape error, if any.
LastError() error LastError() error
// The address to which the Target corresponds. Out of all of the available // The address to which the Target corresponds. Out of all of the available
@ -176,11 +179,11 @@ func (t *target) recordScrapeHealth(results chan<- *extraction.Result, timestamp
} }
} }
func (t *target) Scrape(earliest time.Time, results chan<- *extraction.Result) (err error) { func (t *target) Scrape(earliest time.Time, results chan<- *extraction.Result) error {
now := time.Now() now := time.Now()
futureState := t.state futureState := t.state
err := t.scrape(now, results)
if err = t.scrape(now, results); err != nil { if err != nil {
t.recordScrapeHealth(results, now, false) t.recordScrapeHealth(results, now, false)
futureState = UNREACHABLE futureState = UNREACHABLE
} else { } else {
@ -249,23 +252,27 @@ func (t *target) scrape(timestamp time.Time, results chan<- *extraction.Result)
return processor.ProcessSingle(buf, results, processOptions) return processor.ProcessSingle(buf, results, processOptions)
} }
func (t target) State() TargetState { func (t *target) State() TargetState {
return t.state return t.state
} }
func (t target) scheduledFor() time.Time { func (t *target) ScheduledFor() time.Time {
return t.scheduler.ScheduledFor() return t.scheduler.ScheduledFor()
} }
func (t target) LastError() error { func (t *target) EstimatedTimeToExecute() time.Duration {
return t.scheduler.ScheduledFor().Sub(time.Now())
}
func (t *target) LastError() error {
return t.lastError return t.lastError
} }
func (t target) Address() string { func (t *target) Address() string {
return t.address return t.address
} }
func (t target) GlobalAddress() string { func (t *target) GlobalAddress() string {
address := t.address address := t.address
hostname, err := os.Hostname() hostname, err := os.Hostname()
if err != nil { if err != nil {
@ -278,7 +285,7 @@ func (t target) GlobalAddress() string {
return address return address
} }
func (t target) BaseLabels() clientmodel.LabelSet { func (t *target) BaseLabels() clientmodel.LabelSet {
return t.baseLabels return t.baseLabels
} }
@ -299,7 +306,7 @@ func (t targets) Len() int {
} }
func (t targets) Less(i, j int) bool { func (t targets) Less(i, j int) bool {
return t[i].scheduledFor().Before(t[j].scheduledFor()) return t[i].ScheduledFor().Before(t[j].ScheduledFor())
} }
func (t targets) Swap(i, j int) { func (t targets) Swap(i, j int) {

View file

@ -66,7 +66,7 @@ func (t fakeTarget) State() TargetState {
return ALIVE return ALIVE
} }
func (t *fakeTarget) scheduledFor() (time time.Time) { func (t *fakeTarget) ScheduledFor() (time time.Time) {
time = t.schedules[t.scheduleIndex] time = t.schedules[t.scheduleIndex]
t.scheduleIndex++ t.scheduleIndex++

View file

@ -146,7 +146,7 @@ func (p *TargetPool) runIteration(results chan<- *extraction.Result, interval ti
for _, target := range p.targets { for _, target := range p.targets {
now := time.Now() now := time.Now()
if target.scheduledFor().After(now) { if target.ScheduledFor().After(now) {
// None of the remaining targets are ready to be scheduled. Signal that // None of the remaining targets are ready to be scheduled. Signal that
// we're done processing them in this scrape iteration. // we're done processing them in this scrape iteration.
continue continue

View file

@ -1838,13 +1838,13 @@ func TestGetValueRangeAtIntervalOp(t *testing.T) {
var scenarios = []struct { var scenarios = []struct {
op getValueRangeAtIntervalOp op getValueRangeAtIntervalOp
in model.Values in Values
out model.Values out Values
}{ }{
// All values before the first range. // All values before the first range.
{ {
op: testOp, op: testOp,
in: model.Values{ in: Values{
{ {
Timestamp: testInstant.Add(-4 * time.Minute), Timestamp: testInstant.Add(-4 * time.Minute),
Value: 1, Value: 1,
@ -1854,12 +1854,12 @@ func TestGetValueRangeAtIntervalOp(t *testing.T) {
Value: 2, Value: 2,
}, },
}, },
out: model.Values{}, out: Values{},
}, },
// Values starting before first range, ending after last. // Values starting before first range, ending after last.
{ {
op: testOp, op: testOp,
in: model.Values{ in: Values{
{ {
Timestamp: testInstant.Add(-4 * time.Minute), Timestamp: testInstant.Add(-4 * time.Minute),
Value: 1, Value: 1,
@ -1917,7 +1917,7 @@ func TestGetValueRangeAtIntervalOp(t *testing.T) {
Value: 14, Value: 14,
}, },
}, },
out: model.Values{ out: Values{
{ {
Timestamp: testInstant.Add(-2 * time.Minute), Timestamp: testInstant.Add(-2 * time.Minute),
Value: 3, Value: 3,
@ -1959,17 +1959,17 @@ func TestGetValueRangeAtIntervalOp(t *testing.T) {
// Values starting after last range. // Values starting after last range.
{ {
op: testOp, op: testOp,
in: model.Values{ in: Values{
{ {
Timestamp: testInstant.Add(21 * time.Minute), Timestamp: testInstant.Add(21 * time.Minute),
Value: 14, Value: 14,
}, },
}, },
out: model.Values{}, out: Values{},
}, },
} }
for i, scenario := range scenarios { for i, scenario := range scenarios {
actual := model.Values{} actual := Values{}
for !scenario.op.Consumed() { for !scenario.op.Consumed() {
actual = append(actual, scenario.op.ExtractSamples(scenario.in)...) actual = append(actual, scenario.op.ExtractSamples(scenario.in)...)
} }

View file

@ -40,23 +40,43 @@
<h2>Targets</h2> <h2>Targets</h2>
<div class="grouping_box"> <div class="grouping_box">
<ul>
{{range $job, $pool := .TargetPools}} {{range $job, $pool := .TargetPools}}
<li>{{$job}} <h3>{{$job}}</h3>
<ul> <table>
<thead>
<tr>
<th>Endpoint</th>
<th>State</th>
<th>Base Labels</th>
<th>Next Retrieval</th>
<th>Error</th>
</tr>
</thead>
<tbody>
{{range $pool.Targets}} {{range $pool.Targets}}
<li> <tr>
<a href="{{.GlobalAddress}}">{{.Address}}</a> (State: {{.State}}, Base Labels: {{.BaseLabels}}) <td>
<a href="{{.GlobalAddress}}">{{.Address}}</a>
</td>
<td>
{{.State}}
</td>
<td>
{{.BaseLabels}}
</td>
<td>
{{.EstimatedTimeToExecute}}
</td>
<td>
{{if .LastError}} {{if .LastError}}
<br/> <span class="error_text">{{.LastError}}</span>
<span class="error_text"><b>Scrape error:</b> "{{.LastError}}"</span>
{{end}} {{end}}
</li> </td>
</tr>
{{end}} {{end}}
</ul> </tbody>
</li> </table>
{{end}} {{end}}
</ul>
</div> </div>
<h2>Curation</h2> <h2>Curation</h2>