mirror of
https://github.com/zalando-incubator/kube-metrics-adapter.git
synced 2025-01-03 07:40:09 +00:00
Add support for traffic weight specification
Signed-off-by: Lucas Thiesen <lucas.thiesen@zalando.de>
This commit is contained in:
@ -3,6 +3,7 @@ package collector
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -11,7 +12,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
HostnameMetricType = "hostname-rps"
|
HostnameMetricType = "hostname-rps"
|
||||||
HostnameRPSQuery = `scalar(sum(rate(%s{host=~"%s"}[1m])))`
|
HostnameRPSQuery = `scalar(sum(rate(%s{host=~"%s"}[1m])) * %.4f)`
|
||||||
)
|
)
|
||||||
|
|
||||||
type HostnameCollectorPlugin struct {
|
type HostnameCollectorPlugin struct {
|
||||||
@ -51,19 +52,37 @@ func (p *HostnameCollectorPlugin) NewCollector(
|
|||||||
// RPS data from a specific hostname from prometheus. The idea
|
// RPS data from a specific hostname from prometheus. The idea
|
||||||
// of the copy is to not modify the original config struct.
|
// of the copy is to not modify the original config struct.
|
||||||
confCopy := *config
|
confCopy := *config
|
||||||
hostnames := config.Config["hostname"]
|
//hostnames := config.Config["hostnames"]
|
||||||
|
//weights := config.Config["weights"]
|
||||||
|
|
||||||
if ok, err := regexp.MatchString("^[a-zA-Z0-9.,-]+$", hostnames); !ok || err != nil {
|
if _, ok := config.Config["hostnames"]; !ok {
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf("hostname is not specified, unable to create collector")
|
||||||
"hostname is not specified or invalid format, unable to create collector",
|
}
|
||||||
)
|
hostnames := strings.Split(config.Config["hostnames"], ",")
|
||||||
|
for _, h := range hostnames {
|
||||||
|
if ok, err := regexp.MatchString("^[a-zA-Z0-9.-]+$", h); !ok || err != nil {
|
||||||
|
return nil, fmt.Errorf(
|
||||||
|
"Invalid hostname format, unable to create collector: %s",
|
||||||
|
h,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
weight := 1.0
|
||||||
|
if w, ok := config.Config["weight"]; ok {
|
||||||
|
num, err := strconv.ParseFloat(w, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Could not parse weight annotation, unable to create collector: %s", w)
|
||||||
|
}
|
||||||
|
weight = num / 100.0
|
||||||
}
|
}
|
||||||
|
|
||||||
confCopy.Config = map[string]string{
|
confCopy.Config = map[string]string{
|
||||||
"query": fmt.Sprintf(
|
"query": fmt.Sprintf(
|
||||||
HostnameRPSQuery,
|
HostnameRPSQuery,
|
||||||
p.metricName,
|
p.metricName,
|
||||||
strings.Replace(strings.Replace(hostnames, ",", "|", -1), ".", "_", -1),
|
strings.Replace(strings.Join(hostnames, "|"), ".", "_", -1),
|
||||||
|
weight,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,22 +68,28 @@ func TestHostnamePluginNewCollector(tt *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Valid hostname no prom query config",
|
"Valid hostname no prom query config",
|
||||||
&MetricConfig{Config: map[string]string{"hostname": "foo.bar.baz"}},
|
&MetricConfig{Config: map[string]string{"hostnames": "foo.bar.baz"}},
|
||||||
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz"}[1m])))`,
|
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz"}[1m])) * 1.0000)`,
|
||||||
|
true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Valid hostname no prom query config",
|
||||||
|
&MetricConfig{Config: map[string]string{"hostnames": "foo.bar.baz", "weight": "42"}},
|
||||||
|
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz"}[1m])) * 0.4200)`,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Multiple valid hostnames no prom query config",
|
"Multiple valid hostnames no prom query config",
|
||||||
&MetricConfig{Config: map[string]string{"hostname": "foo.bar.baz,foz.bax.bas"}},
|
&MetricConfig{Config: map[string]string{"hostnames": "foo.bar.baz,foz.bax.bas"}},
|
||||||
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz|foz_bax_bas"}[1m])))`,
|
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz|foz_bax_bas"}[1m])) * 1.0000)`,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"Valid hostname with prom query config",
|
"Valid hostname with prom query config",
|
||||||
&MetricConfig{
|
&MetricConfig{
|
||||||
Config: map[string]string{"hostname": "foo.bar.baz", "query": "some_other_query"},
|
Config: map[string]string{"hostnames": "foo.bar.baz", "query": "some_other_query"},
|
||||||
},
|
},
|
||||||
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz"}[1m])))`,
|
`scalar(sum(rate(a_valid_one{host=~"foo_bar_baz"}[1m])) * 1.0000)`,
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
@ -169,7 +175,7 @@ func TestHostnameCollectorInterval(t *testing.T) {
|
|||||||
}
|
}
|
||||||
c, err := plugin.NewCollector(
|
c, err := plugin.NewCollector(
|
||||||
&autoscalingv2.HorizontalPodAutoscaler{},
|
&autoscalingv2.HorizontalPodAutoscaler{},
|
||||||
&MetricConfig{Config: map[string]string{"hostname": "foo.bar.baz"}},
|
&MetricConfig{Config: map[string]string{"hostnames": "foo.bar.baz"}},
|
||||||
interval,
|
interval,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -179,11 +185,12 @@ func TestHostnameCollectorInterval(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHostnameCollectorAndCollectorFabricInteraction(t *testing.T) {
|
func TestHostnameCollectorAndCollectorFabricInteraction(t *testing.T) {
|
||||||
expectedQuery := `scalar(sum(rate(a_metric{host=~"just_testing_com"}[1m])))`
|
expectedQuery := `scalar(sum(rate(a_metric{host=~"just_testing_com"}[1m])) * 0.4200)`
|
||||||
hpa := &autoscalingv2.HorizontalPodAutoscaler{
|
hpa := &autoscalingv2.HorizontalPodAutoscaler{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"metric-config.external.foo.hostname-rps/hostname": "just.testing.com",
|
"metric-config.external.foo.hostname-rps/hostnames": "just.testing.com",
|
||||||
|
"metric-config.external.foo.hostname-rps/weight": "42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
|
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
|
||||||
@ -222,13 +229,14 @@ func TestHostnameCollectorAndCollectorFabricInteraction(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHostnamePrometheusCollectorInteraction(t *testing.T) {
|
func TestHostnamePrometheusCollectorInteraction(t *testing.T) {
|
||||||
hostnameQuery := `scalar(sum(rate(a_metric{host=~"just_testing_com"}[1m])))`
|
hostnameQuery := `scalar(sum(rate(a_metric{host=~"just_testing_com"}[1m])) * 0.4200)`
|
||||||
promQuery := "sum(rate(rps[1m]))"
|
promQuery := "sum(rate(rps[1m]))"
|
||||||
hpa := &autoscalingv2.HorizontalPodAutoscaler{
|
hpa := &autoscalingv2.HorizontalPodAutoscaler{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
"metric-config.external.foo.hostname-rps/hostname": "just.testing.com",
|
"metric-config.external.foo.hostname-rps/hostnames": "just.testing.com",
|
||||||
"metric-config.external.bar.prometheus/query": promQuery,
|
"metric-config.external.foo.hostname-rps/weight": "42",
|
||||||
|
"metric-config.external.bar.prometheus/query": promQuery,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
|
Spec: autoscalingv2.HorizontalPodAutoscalerSpec{
|
||||||
|
Reference in New Issue
Block a user