Skip to content

Commit

Permalink
Merge pull request prometheus#1946 from prometheus/ipv6
Browse files Browse the repository at this point in the history
Fix IPv6 scraping
  • Loading branch information
fabxc authored Sep 6, 2016
2 parents 2b45d51 + a15237a commit fec3b54
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 72 deletions.
3 changes: 2 additions & 1 deletion retrieval/discovery/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package discovery

import (
"fmt"
"net"
"strings"
"time"

Expand Down Expand Up @@ -217,7 +218,7 @@ func (ad *AzureDiscovery) refresh() (*config.TargetGroup, error) {
for _, ip := range *networkInterface.Properties.IPConfigurations {
if ip.Properties.PrivateIPAddress != nil {
labels[azureLabelMachinePrivateIP] = model.LabelValue(*ip.Properties.PrivateIPAddress)
address := fmt.Sprintf("%s:%d", *ip.Properties.PrivateIPAddress, ad.port)
address := net.JoinHostPort(*ip.Properties.PrivateIPAddress, fmt.Sprintf("%d", ad.port))
labels[model.AddressLabel] = model.LabelValue(address)
ch <- target{labelSet: labels, err: nil}
return
Expand Down
5 changes: 3 additions & 2 deletions retrieval/discovery/consul/consul.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package consul

import (
"fmt"
"net"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -238,9 +239,9 @@ func (srv *consulService) watch(ctx context.Context, ch chan<- []*config.TargetG
// since the service may be registered remotely through a different node
var addr string
if node.ServiceAddress != "" {
addr = fmt.Sprintf("%s:%d", node.ServiceAddress, node.ServicePort)
addr = net.JoinHostPort(node.ServiceAddress, fmt.Sprintf("%d", node.ServicePort))
} else {
addr = fmt.Sprintf("%s:%d", node.Address, node.ServicePort)
addr = net.JoinHostPort(node.Address, fmt.Sprintf("%d", node.ServicePort))
}

tgroup.Targets = append(tgroup.Targets, model.LabelSet{
Expand Down
9 changes: 6 additions & 3 deletions retrieval/discovery/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ func (dd *Discovery) refresh(ctx context.Context, name string, ch chan<- []*conf
}

tg := &config.TargetGroup{}
hostPort := func(a string, p int) model.LabelValue {
return model.LabelValue(net.JoinHostPort(a, fmt.Sprintf("%d", p)))
}

for _, record := range response.Answer {
target := model.LabelValue("")
Expand All @@ -141,11 +144,11 @@ func (dd *Discovery) refresh(ctx context.Context, name string, ch chan<- []*conf
// Remove the final dot from rooted DNS names to make them look more usual.
addr.Target = strings.TrimRight(addr.Target, ".")

target = model.LabelValue(fmt.Sprintf("%s:%d", addr.Target, addr.Port))
target = hostPort(addr.Target, int(addr.Port))
case *dns.A:
target = model.LabelValue(fmt.Sprintf("%s:%d", addr.A, dd.port))
target = hostPort(addr.A.String(), dd.port)
case *dns.AAAA:
target = model.LabelValue(fmt.Sprintf("%s:%d", addr.AAAA, dd.port))
target = hostPort(addr.AAAA.String(), dd.port)
default:
log.Warnf("%q is not a valid SRV record", record)
continue
Expand Down
3 changes: 2 additions & 1 deletion retrieval/discovery/ec2.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package discovery

import (
"fmt"
"net"
"strings"
"time"

Expand Down Expand Up @@ -112,7 +113,7 @@ func (ed *EC2Discovery) refresh() (*config.TargetGroup, error) {
ec2LabelInstanceID: model.LabelValue(*inst.InstanceId),
}
labels[ec2LabelPrivateIP] = model.LabelValue(*inst.PrivateIpAddress)
addr := fmt.Sprintf("%s:%d", *inst.PrivateIpAddress, ed.port)
addr := net.JoinHostPort(*inst.PrivateIpAddress, fmt.Sprintf("%d", ed.port))
labels[model.AddressLabel] = model.LabelValue(addr)

if inst.PublicIpAddress != nil {
Expand Down
2 changes: 1 addition & 1 deletion retrieval/discovery/kubernetes/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (d *nodeDiscovery) updateNodesTargetGroup() *config.TargetGroup {

kubeletPort := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)

address := fmt.Sprintf("%s:%d", defaultNodeAddress.String(), kubeletPort)
address := net.JoinHostPort(defaultNodeAddress.String(), fmt.Sprintf("%d", kubeletPort))

t := model.LabelSet{
model.AddressLabel: model.LabelValue(address),
Expand Down
2 changes: 1 addition & 1 deletion retrieval/discovery/kubernetes/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ func (d *serviceDiscovery) updateServiceTargetGroup(service *Service, eps *Endpo
if len(ipAddr) == net.IPv6len {
ipAddr = "[" + ipAddr + "]"
}
address := fmt.Sprintf("%s:%d", ipAddr, epPort)
address := net.JoinHostPort(ipAddr, fmt.Sprintf("%d", epPort))

t := model.LabelSet{
model.AddressLabel: model.LabelValue(address),
Expand Down
3 changes: 2 additions & 1 deletion retrieval/discovery/marathon/marathon.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"io/ioutil"
"math/rand"
"net"
"net/http"
"time"

Expand Down Expand Up @@ -229,5 +230,5 @@ func targetsForApp(app *App) []model.LabelSet {
}

func targetForTask(task *Task) string {
return fmt.Sprintf("%s:%d", task.Host, task.Ports[0])
return net.JoinHostPort(task.Host, fmt.Sprintf("%d", task.Ports[0]))
}
3 changes: 2 additions & 1 deletion retrieval/discovery/nerve.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package discovery
import (
"encoding/json"
"fmt"
"net"
"sync"
"time"

Expand Down Expand Up @@ -133,7 +134,7 @@ func parseNerveMember(data []byte, path string) (*model.LabelSet, error) {
labels := model.LabelSet{}
labels[nervePathLabel] = model.LabelValue(path)
labels[model.AddressLabel] = model.LabelValue(
fmt.Sprintf("%s:%d", member.Host, member.Port))
net.JoinHostPort(member.Host, fmt.Sprintf("%d", member.Port)))

labels[nerveEndpointLabelPrefix+"_host"] = model.LabelValue(member.Host)
labels[nerveEndpointLabelPrefix+"_port"] = model.LabelValue(fmt.Sprintf("%d", member.Port))
Expand Down
3 changes: 2 additions & 1 deletion retrieval/discovery/serverset.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package discovery
import (
"encoding/json"
"fmt"
"net"
"strconv"
"sync"
"time"
Expand Down Expand Up @@ -143,7 +144,7 @@ func parseServersetMember(data []byte, path string) (*model.LabelSet, error) {
labels := model.LabelSet{}
labels[serversetPathLabel] = model.LabelValue(path)
labels[model.AddressLabel] = model.LabelValue(
fmt.Sprintf("%s:%d", member.ServiceEndpoint.Host, member.ServiceEndpoint.Port))
net.JoinHostPort(member.ServiceEndpoint.Host, fmt.Sprintf("%d", member.ServiceEndpoint.Port)))

labels[serversetEndpointLabelPrefix+"_host"] = model.LabelValue(member.ServiceEndpoint.Host)
labels[serversetEndpointLabelPrefix+"_port"] = model.LabelValue(fmt.Sprintf("%d", member.ServiceEndpoint.Port))
Expand Down
145 changes: 85 additions & 60 deletions retrieval/targetmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ package retrieval

import (
"fmt"
"net"
"sort"
"strings"
"sync"
Expand Down Expand Up @@ -417,79 +418,103 @@ func providersFromConfig(cfg *config.ScrapeConfig) map[string]TargetProvider {
return providers
}

// targetsFromGroup builds targets based on the given TargetGroup and config.
// Panics if target group is nil.
func targetsFromGroup(tg *config.TargetGroup, cfg *config.ScrapeConfig) ([]*Target, error) {
targets := make([]*Target, 0, len(tg.Targets))

for i, labels := range tg.Targets {
for k, v := range cfg.Params {
if len(v) > 0 {
labels[model.LabelName(model.ParamLabelPrefix+k)] = model.LabelValue(v[0])
}
}
// Copy labels into the labelset for the target if they are not
// set already. Apply the labelsets in order of decreasing precedence.
labelsets := []model.LabelSet{
tg.Labels,
{
model.SchemeLabel: model.LabelValue(cfg.Scheme),
model.MetricsPathLabel: model.LabelValue(cfg.MetricsPath),
model.JobLabel: model.LabelValue(cfg.JobName),
},
}
for _, lset := range labelsets {
for ln, lv := range lset {
if _, ok := labels[ln]; !ok {
labels[ln] = lv
}
}
// populateLabels builds a label set from the given label set and scrape configuration.
// It returns a label set before relabeling was applied as the second return value.
// Returns a nil label set if the target is dropped during relabeling.
func populateLabels(lset model.LabelSet, cfg *config.ScrapeConfig) (res, orig model.LabelSet, err error) {
if _, ok := lset[model.AddressLabel]; !ok {
return nil, nil, fmt.Errorf("no address")
}
// Copy labels into the labelset for the target if they are not
// set already. Apply the labelsets in order of decreasing precedence.
scrapeLabels := model.LabelSet{
model.SchemeLabel: model.LabelValue(cfg.Scheme),
model.MetricsPathLabel: model.LabelValue(cfg.MetricsPath),
model.JobLabel: model.LabelValue(cfg.JobName),
}
for ln, lv := range scrapeLabels {
if _, ok := lset[ln]; !ok {
lset[ln] = lv
}

if _, ok := labels[model.AddressLabel]; !ok {
return nil, fmt.Errorf("instance %d in target group %s has no address", i, tg)
}
// Encode scrape query parameters as labels.
for k, v := range cfg.Params {
if len(v) > 0 {
lset[model.LabelName(model.ParamLabelPrefix+k)] = model.LabelValue(v[0])
}
}

preRelabelLabels := labels
preRelabelLabels := lset
lset = relabel.Process(lset, cfg.RelabelConfigs...)

labels := relabel.Process(labels, cfg.RelabelConfigs...)
// Check if the target was dropped.
if lset == nil {
return nil, nil, nil
}

// Check if the target was dropped.
if labels == nil {
continue
// addPort checks whether we should add a default port to the address.
// If the address is not valid, we don't append a port either.
addPort := func(s string) bool {
// If we can split, a port exists and we don't have to add one.
if _, _, err := net.SplitHostPort(s); err == nil {
return false
}
// If no port was provided, infer it based on the used scheme.
addr := string(labels[model.AddressLabel])
if !strings.Contains(addr, ":") {
switch labels[model.SchemeLabel] {
case "http", "":
addr = fmt.Sprintf("%s:80", addr)
case "https":
addr = fmt.Sprintf("%s:443", addr)
default:
return nil, fmt.Errorf("invalid scheme: %q", cfg.Scheme)
}
labels[model.AddressLabel] = model.LabelValue(addr)
// If adding a port makes it valid, the previous error
// was not due to an invalid address and we can append a port.
_, _, err := net.SplitHostPort(s + ":1234")
return err == nil
}
// If it's an address with no trailing port, infer it based on the used scheme.
if addr := string(lset[model.AddressLabel]); addPort(addr) {
// Addresses reaching this point are already wrapped in [] if necessary.
switch lset[model.SchemeLabel] {
case "http", "":
addr = addr + ":80"
case "https":
addr = addr + ":443"
default:
return nil, nil, fmt.Errorf("invalid scheme: %q", cfg.Scheme)
}
if err := config.CheckTargetAddress(labels[model.AddressLabel]); err != nil {
return nil, err
lset[model.AddressLabel] = model.LabelValue(addr)
}
if err := config.CheckTargetAddress(lset[model.AddressLabel]); err != nil {
return nil, nil, err
}

// Meta labels are deleted after relabelling. Other internal labels propagate to
// the target which decides whether they will be part of their label set.
for ln := range lset {
if strings.HasPrefix(string(ln), model.MetaLabelPrefix) {
delete(lset, ln)
}
}

for ln := range labels {
// Meta labels are deleted after relabelling. Other internal labels propagate to
// the target which decides whether they will be part of their label set.
if strings.HasPrefix(string(ln), model.MetaLabelPrefix) {
delete(labels, ln)
// Default the instance label to the target address.
if _, ok := lset[model.InstanceLabel]; !ok {
lset[model.InstanceLabel] = lset[model.AddressLabel]
}
return lset, preRelabelLabels, nil
}

// targetsFromGroup builds targets based on the given TargetGroup and config.
func targetsFromGroup(tg *config.TargetGroup, cfg *config.ScrapeConfig) ([]*Target, error) {
targets := make([]*Target, 0, len(tg.Targets))

for i, lset := range tg.Targets {
// Combine target labels with target group labels.
for ln, lv := range tg.Labels {
if _, ok := lset[ln]; !ok {
lset[ln] = lv
}
}

if _, ok := labels[model.InstanceLabel]; !ok {
labels[model.InstanceLabel] = labels[model.AddressLabel]
labels, origLabels, err := populateLabels(lset, cfg)
if err != nil {
return nil, fmt.Errorf("instance %d in group %s: %s", i, tg, err)
}
if labels != nil {
targets = append(targets, NewTarget(labels, origLabels, cfg.Params))
}

targets = append(targets, NewTarget(labels, preRelabelLabels, cfg.Params))
}

return targets, nil
}

Expand Down
Loading

0 comments on commit fec3b54

Please sign in to comment.