Move template functionality out of target.
The target implementation and interface contain methods only serving a specific purpose of the templates. They were moved to the template as they operate on more fundamental target data.
This commit is contained in:
parent
dbc08d390e
commit
1a2d57b45c
|
@ -19,7 +19,6 @@ import (
|
|||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -53,8 +52,6 @@ const (
|
|||
var (
|
||||
errIngestChannelFull = errors.New("ingestion channel full")
|
||||
|
||||
localhostRepresentations = []string{"127.0.0.1", "localhost"}
|
||||
|
||||
targetIntervalLength = prometheus.NewSummaryVec(
|
||||
prometheus.SummaryOpts{
|
||||
Namespace: namespace,
|
||||
|
@ -118,17 +115,11 @@ type Target interface {
|
|||
URL() string
|
||||
// Used to populate the `instance` label in metrics.
|
||||
InstanceIdentifier() string
|
||||
// The URL as seen from other hosts. References to localhost are resolved
|
||||
// to the address of the prometheus server.
|
||||
GlobalURL() string
|
||||
// Return the labels describing the targets. These are the base labels
|
||||
// as well as internal labels.
|
||||
Labels() clientmodel.LabelSet
|
||||
fullLabels() clientmodel.LabelSet
|
||||
// Return the target's base labels.
|
||||
BaseLabels() clientmodel.LabelSet
|
||||
// Return the target's base labels without job and instance label. That's
|
||||
// useful for display purposes.
|
||||
BaseLabelsWithoutJobAndInstance() clientmodel.LabelSet
|
||||
// Start scraping the target in regular intervals.
|
||||
RunScraper(storage.SampleAppender)
|
||||
// Stop scraping, synchronous.
|
||||
|
@ -195,7 +186,6 @@ type target struct {
|
|||
|
||||
// The status object for the target. It is only set once on initialization.
|
||||
status *TargetStatus
|
||||
|
||||
// The HTTP client used to scrape the target's endpoint.
|
||||
httpClient *http.Client
|
||||
|
||||
|
@ -419,66 +409,43 @@ func (t *target) InstanceIdentifier() string {
|
|||
return t.url.Host
|
||||
}
|
||||
|
||||
// GlobalURL implements Target.
|
||||
func (t *target) GlobalURL() string {
|
||||
url := t.URL()
|
||||
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
glog.Warningf("Couldn't get hostname: %s, returning target.URL()", err)
|
||||
return url
|
||||
}
|
||||
for _, localhostRepresentation := range localhostRepresentations {
|
||||
url = strings.Replace(url, "//"+localhostRepresentation, "//"+hostname, 1)
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
// Labels implements Target.
|
||||
func (t *target) Labels() clientmodel.LabelSet {
|
||||
// fullLabels implements Target.
|
||||
func (t *target) fullLabels() clientmodel.LabelSet {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
ls := clientmodel.LabelSet{}
|
||||
lset := make(clientmodel.LabelSet, len(t.baseLabels)+2)
|
||||
for ln, lv := range t.baseLabels {
|
||||
ls[ln] = lv
|
||||
lset[ln] = lv
|
||||
}
|
||||
ls[clientmodel.MetricsPathLabel] = clientmodel.LabelValue(t.url.Path)
|
||||
ls[clientmodel.AddressLabel] = clientmodel.LabelValue(t.url.Host)
|
||||
return ls
|
||||
lset[clientmodel.MetricsPathLabel] = clientmodel.LabelValue(t.url.Path)
|
||||
lset[clientmodel.AddressLabel] = clientmodel.LabelValue(t.url.Host)
|
||||
return lset
|
||||
}
|
||||
|
||||
// BaseLabels implements Target.
|
||||
func (t *target) BaseLabels() clientmodel.LabelSet {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
return t.baseLabels
|
||||
}
|
||||
|
||||
// BaseLabelsWithoutJobAndInstance implements Target.
|
||||
//
|
||||
// TODO(fabxc): This method does not have to be part of the interface. Implement this
|
||||
// as a template filter func for the single use case.
|
||||
func (t *target) BaseLabelsWithoutJobAndInstance() clientmodel.LabelSet {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
ls := clientmodel.LabelSet{}
|
||||
lset := make(clientmodel.LabelSet, len(t.baseLabels))
|
||||
for ln, lv := range t.baseLabels {
|
||||
if ln != clientmodel.JobLabel && ln != clientmodel.InstanceLabel {
|
||||
ls[ln] = lv
|
||||
}
|
||||
lset[ln] = lv
|
||||
}
|
||||
return ls
|
||||
return lset
|
||||
}
|
||||
|
||||
func (t *target) recordScrapeHealth(sampleAppender storage.SampleAppender, timestamp clientmodel.Timestamp, scrapeDuration time.Duration) {
|
||||
healthMetric := clientmodel.Metric{}
|
||||
durationMetric := clientmodel.Metric{}
|
||||
for label, value := range t.BaseLabels() {
|
||||
t.RLock()
|
||||
healthMetric := make(clientmodel.Metric, len(t.baseLabels)+1)
|
||||
durationMetric := make(clientmodel.Metric, len(t.baseLabels)+1)
|
||||
|
||||
healthMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeHealthMetricName)
|
||||
durationMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeDurationMetricName)
|
||||
|
||||
for label, value := range t.baseLabels {
|
||||
healthMetric[label] = value
|
||||
durationMetric[label] = value
|
||||
}
|
||||
healthMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeHealthMetricName)
|
||||
durationMetric[clientmodel.MetricNameLabel] = clientmodel.LabelValue(scrapeDurationMetricName)
|
||||
t.RUnlock()
|
||||
|
||||
healthValue := clientmodel.SampleValue(0)
|
||||
if t.status.State() == Healthy {
|
||||
|
|
|
@ -44,13 +44,6 @@ func TestBaseLabels(t *testing.T) {
|
|||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("want base labels %v, got %v", want, got)
|
||||
}
|
||||
delete(want, clientmodel.JobLabel)
|
||||
delete(want, clientmodel.InstanceLabel)
|
||||
|
||||
got = target.BaseLabelsWithoutJobAndInstance()
|
||||
if !reflect.DeepEqual(want, got) {
|
||||
t.Errorf("want base labels %v, got %v", want, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTargetScrapeUpdatesState(t *testing.T) {
|
||||
|
|
|
@ -215,7 +215,7 @@ func (tm *TargetManager) updateTargetGroup(tgroup *config.TargetGroup, cfg *conf
|
|||
// to build up.
|
||||
wg.Add(1)
|
||||
go func(t Target) {
|
||||
match.Update(cfg, t.Labels())
|
||||
match.Update(cfg, t.fullLabels())
|
||||
wg.Done()
|
||||
}(tnew)
|
||||
newTargets[i] = match
|
||||
|
|
|
@ -48,7 +48,7 @@
|
|||
{{range $pool}}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{.GlobalURL}}">{{.URL}}</a>
|
||||
<a href="{{.URL | globalURL}}">{{.URL}}</a>
|
||||
</td>
|
||||
<td>
|
||||
<span class="alert alert-{{index $stateToClass .Status.State}} target_status_alert">
|
||||
|
@ -56,7 +56,7 @@
|
|||
</span>
|
||||
</td>
|
||||
<td>
|
||||
{{.BaseLabelsWithoutJobAndInstance}}
|
||||
{{stripLabels .BaseLabels "job" "instance"}}
|
||||
</td>
|
||||
<td>
|
||||
{{if .Status.LastScrape.IsZero}}Never{{else}}{{since .Status.LastScrape}} ago{{end}}
|
||||
|
|
43
web/web.go
43
web/web.go
|
@ -29,10 +29,14 @@ import (
|
|||
"github.com/golang/glog"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
clientmodel "github.com/prometheus/client_golang/model"
|
||||
|
||||
"github.com/prometheus/prometheus/web/api"
|
||||
"github.com/prometheus/prometheus/web/blob"
|
||||
)
|
||||
|
||||
var localhostRepresentations = []string{"127.0.0.1", "localhost"}
|
||||
|
||||
// Commandline flags.
|
||||
var (
|
||||
listenAddress = flag.String("web.listen-address", ":9090", "Address to listen on for the web interface, API, and telemetry.")
|
||||
|
@ -150,28 +154,53 @@ func getConsoles(pathPrefix string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func getTemplate(name string, pathPrefix string) (t *template.Template, err error) {
|
||||
t = template.New("_base")
|
||||
func getTemplate(name string, pathPrefix string) (*template.Template, error) {
|
||||
t := template.New("_base")
|
||||
var err error
|
||||
|
||||
t.Funcs(template.FuncMap{
|
||||
"since": time.Since,
|
||||
"getConsoles": func() string { return getConsoles(pathPrefix) },
|
||||
"pathPrefix": func() string { return pathPrefix },
|
||||
"stripLabels": func(lset clientmodel.LabelSet, labels ...clientmodel.LabelName) clientmodel.LabelSet {
|
||||
for _, ln := range labels {
|
||||
delete(lset, ln)
|
||||
}
|
||||
return lset
|
||||
},
|
||||
"globalURL": func(url string) string {
|
||||
hostname, err := os.Hostname()
|
||||
if err != nil {
|
||||
glog.Warningf("Couldn't get hostname: %s, returning target.URL()", err)
|
||||
return url
|
||||
}
|
||||
for _, localhostRepresentation := range localhostRepresentations {
|
||||
url = strings.Replace(url, "//"+localhostRepresentation, "//"+hostname, 1)
|
||||
}
|
||||
return url
|
||||
},
|
||||
})
|
||||
|
||||
file, err := getTemplateFile("_base")
|
||||
if err != nil {
|
||||
glog.Error("Could not read base template: ", err)
|
||||
glog.Errorln("Could not read base template:", err)
|
||||
return nil, err
|
||||
}
|
||||
t.Parse(file)
|
||||
t, err = t.Parse(file)
|
||||
if err != nil {
|
||||
glog.Errorln("Could not parse base template:", err)
|
||||
}
|
||||
|
||||
file, err = getTemplateFile(name)
|
||||
if err != nil {
|
||||
glog.Error("Could not read base template: ", err)
|
||||
glog.Error("Could not read template %d: ", name, err)
|
||||
return nil, err
|
||||
}
|
||||
t.Parse(file)
|
||||
return
|
||||
t, err = t.Parse(file)
|
||||
if err != nil {
|
||||
glog.Errorf("Could not parse template %s: %s", name, err)
|
||||
}
|
||||
return t, err
|
||||
}
|
||||
|
||||
func executeTemplate(w http.ResponseWriter, name string, data interface{}, pathPrefix string) {
|
||||
|
|
Loading…
Reference in New Issue