mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-07 22:25:03 +00:00
Adds Support for Cross-Namespace Metrics
This commit is contained in:
parent
03bc47e9fb
commit
718cb2400e
4 changed files with 51 additions and 5 deletions
|
|
@ -38,6 +38,9 @@ type DiscoveryRule struct {
|
||||||
// `.GroupBy` is the comma-separated expected group-by label names. The delimeters
|
// `.GroupBy` is the comma-separated expected group-by label names. The delimeters
|
||||||
// are `<<` and `>>`.
|
// are `<<` and `>>`.
|
||||||
MetricsQuery string `yaml:"metricsQuery,omitempty"`
|
MetricsQuery string `yaml:"metricsQuery,omitempty"`
|
||||||
|
// Options specifies additional parameters that are taken into account
|
||||||
|
// when configuring a rule. These can be used to fine-tune the retrieval of metrics
|
||||||
|
Options Options `yaml:"options,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// RegexFilter is a filter that matches positively or negatively against a regex.
|
// RegexFilter is a filter that matches positively or negatively against a regex.
|
||||||
|
|
@ -80,6 +83,13 @@ type NameMapping struct {
|
||||||
As string `yaml:"as"`
|
As string `yaml:"as"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Option describes a set of customisations for retrieving metrics
|
||||||
|
type Options struct {
|
||||||
|
// option to allow cross-namespace metrics. Used to determine whether to
|
||||||
|
// append the namespace as a label selector when retrieving metrics
|
||||||
|
DetatchFromNamespace bool `yaml:"detachFromNamespace,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// ResourceRules describe the rules for querying resource metrics
|
// ResourceRules describe the rules for querying resource metrics
|
||||||
// API results. It's assumed that the same metrics can be used
|
// API results. It's assumed that the same metrics can be used
|
||||||
// to aggregate across different resources.
|
// to aggregate across different resources.
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,8 @@ type metricNamer struct {
|
||||||
seriesMatchers []*ReMatcher
|
seriesMatchers []*ReMatcher
|
||||||
|
|
||||||
ResourceConverter
|
ResourceConverter
|
||||||
|
|
||||||
|
options config.Options
|
||||||
}
|
}
|
||||||
|
|
||||||
// queryTemplateArgs are the arguments for the metrics query template.
|
// queryTemplateArgs are the arguments for the metrics query template.
|
||||||
|
|
@ -133,7 +135,7 @@ func (n *metricNamer) QueryForSeries(series string, resource schema.GroupResourc
|
||||||
func (n *metricNamer) QueryForExternalSeries(series string, namespace string, metricSelector labels.Selector) (prom.Selector, error) {
|
func (n *metricNamer) QueryForExternalSeries(series string, namespace string, metricSelector labels.Selector) (prom.Selector, error) {
|
||||||
//test := prom.Selector()
|
//test := prom.Selector()
|
||||||
//return test, nil
|
//return test, nil
|
||||||
return n.metricsQuery.BuildExternal(series, namespace, "", []string{}, metricSelector)
|
return n.metricsQuery.BuildExternal(series, namespace, "", []string{}, metricSelector, n.options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *metricNamer) MetricNameForSeries(series prom.Series) (string, error) {
|
func (n *metricNamer) MetricNameForSeries(series prom.Series) (string, error) {
|
||||||
|
|
@ -208,6 +210,7 @@ func NamersFromConfig(cfg []config.DiscoveryRule, mapper apimeta.RESTMapper) ([]
|
||||||
nameAs: nameAs,
|
nameAs: nameAs,
|
||||||
seriesMatchers: seriesMatchers,
|
seriesMatchers: seriesMatchers,
|
||||||
ResourceConverter: resConv,
|
ResourceConverter: resConv,
|
||||||
|
options: rule.Options,
|
||||||
}
|
}
|
||||||
|
|
||||||
namers[i] = namer
|
namers[i] = namer
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/selection"
|
"k8s.io/apimachinery/pkg/selection"
|
||||||
|
|
||||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||||
|
"github.com/directxman12/k8s-prometheus-adapter/pkg/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MetricsQuery represents a compiled metrics query for some set of
|
// MetricsQuery represents a compiled metrics query for some set of
|
||||||
|
|
@ -40,7 +41,7 @@ type MetricsQuery interface {
|
||||||
// where we need to scope down more specifically than just the group-resource
|
// where we need to scope down more specifically than just the group-resource
|
||||||
// (e.g. container metrics).
|
// (e.g. container metrics).
|
||||||
Build(series string, groupRes schema.GroupResource, namespace string, extraGroupBy []string, resourceNames ...string) (prom.Selector, error)
|
Build(series string, groupRes schema.GroupResource, namespace string, extraGroupBy []string, resourceNames ...string) (prom.Selector, error)
|
||||||
BuildExternal(seriesName string, namespace string, groupBy string, groupBySlice []string, metricSelector labels.Selector) (prom.Selector, error)
|
BuildExternal(seriesName string, namespace string, groupBy string, groupBySlice []string, metricSelector labels.Selector, options config.Options) (prom.Selector, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetricsQuery constructs a new MetricsQuery by compiling the given Go template.
|
// NewMetricsQuery constructs a new MetricsQuery by compiling the given Go template.
|
||||||
|
|
@ -136,13 +137,13 @@ func (q *metricsQuery) Build(series string, resource schema.GroupResource, names
|
||||||
return prom.Selector(queryBuff.String()), nil
|
return prom.Selector(queryBuff.String()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *metricsQuery) BuildExternal(seriesName string, namespace string, groupBy string, groupBySlice []string, metricSelector labels.Selector) (prom.Selector, error) {
|
func (q *metricsQuery) BuildExternal(seriesName string, namespace string, groupBy string, groupBySlice []string, metricSelector labels.Selector, options config.Options) (prom.Selector, error) {
|
||||||
queryParts := []queryPart{}
|
queryParts := []queryPart{}
|
||||||
|
|
||||||
// Build up the query parts from the selector.
|
// Build up the query parts from the selector.
|
||||||
queryParts = append(queryParts, q.createQueryPartsFromSelector(metricSelector)...)
|
queryParts = append(queryParts, q.createQueryPartsFromSelector(metricSelector)...)
|
||||||
|
|
||||||
if namespace != "" {
|
if namespace != "" && options.DetatchFromNamespace != true {
|
||||||
namespaceLbl, err := q.resConverter.LabelForResource(NsGroupResource)
|
namespaceLbl, err := q.resConverter.LabelForResource(NsGroupResource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||||
|
"github.com/directxman12/k8s-prometheus-adapter/pkg/config"
|
||||||
pmodel "github.com/prometheus/common/model"
|
pmodel "github.com/prometheus/common/model"
|
||||||
labels "k8s.io/apimachinery/pkg/labels"
|
labels "k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
|
@ -261,6 +262,7 @@ func TestBuildExternalSelector(t *testing.T) {
|
||||||
groupBy string
|
groupBy string
|
||||||
groupBySlice []string
|
groupBySlice []string
|
||||||
metricSelector labels.Selector
|
metricSelector labels.Selector
|
||||||
|
options config.Options
|
||||||
|
|
||||||
check checkFunc
|
check checkFunc
|
||||||
}{
|
}{
|
||||||
|
|
@ -340,6 +342,36 @@ func TestBuildExternalSelector(t *testing.T) {
|
||||||
hasSelector(`foo="bar",namespaces="default"`),
|
hasSelector(`foo="bar",namespaces="default"`),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "single LabelMatchers value with namespace - detached namespace",
|
||||||
|
|
||||||
|
mq: mustNewQuery(`<<.LabelMatchers>>`),
|
||||||
|
namespace: "default",
|
||||||
|
options: config.Options{DetatchFromNamespace: true},
|
||||||
|
metricSelector: labels.NewSelector().Add(
|
||||||
|
*mustNewLabelRequirement("foo", selection.Equals, []string{"bar"}),
|
||||||
|
),
|
||||||
|
|
||||||
|
check: checks(
|
||||||
|
hasError(nil),
|
||||||
|
hasSelector(`foo="bar"`),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single LabelMatchers value with namespace - explicit attached namespace",
|
||||||
|
|
||||||
|
mq: mustNewQuery(`<<.LabelMatchers>>`),
|
||||||
|
namespace: "default",
|
||||||
|
options: config.Options{DetatchFromNamespace: false},
|
||||||
|
metricSelector: labels.NewSelector().Add(
|
||||||
|
*mustNewLabelRequirement("foo", selection.Equals, []string{"bar"}),
|
||||||
|
),
|
||||||
|
|
||||||
|
check: checks(
|
||||||
|
hasError(nil),
|
||||||
|
hasSelector(`foo="bar",namespaces="default"`),
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "multiple LabelMatchers value",
|
name: "multiple LabelMatchers value",
|
||||||
|
|
||||||
|
|
@ -384,7 +416,7 @@ func TestBuildExternalSelector(t *testing.T) {
|
||||||
|
|
||||||
for _, tc := range tests {
|
for _, tc := range tests {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
selector, err := tc.mq.BuildExternal(tc.series, tc.namespace, tc.groupBy, tc.groupBySlice, tc.metricSelector)
|
selector, err := tc.mq.BuildExternal(tc.series, tc.namespace, tc.groupBy, tc.groupBySlice, tc.metricSelector, tc.options)
|
||||||
t.Logf("selector: '%v'", selector)
|
t.Logf("selector: '%v'", selector)
|
||||||
|
|
||||||
if err := tc.check(selector, err); err != nil {
|
if err := tc.check(selector, err); err != nil {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue