mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-06 17:57:51 +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
|
||||
// are `<<` and `>>`.
|
||||
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.
|
||||
|
|
@ -80,6 +83,13 @@ type NameMapping struct {
|
|||
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
|
||||
// API results. It's assumed that the same metrics can be used
|
||||
// to aggregate across different resources.
|
||||
|
|
|
|||
|
|
@ -104,6 +104,8 @@ type metricNamer struct {
|
|||
seriesMatchers []*ReMatcher
|
||||
|
||||
ResourceConverter
|
||||
|
||||
options config.Options
|
||||
}
|
||||
|
||||
// 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) {
|
||||
//test := prom.Selector()
|
||||
//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) {
|
||||
|
|
@ -208,6 +210,7 @@ func NamersFromConfig(cfg []config.DiscoveryRule, mapper apimeta.RESTMapper) ([]
|
|||
nameAs: nameAs,
|
||||
seriesMatchers: seriesMatchers,
|
||||
ResourceConverter: resConv,
|
||||
options: rule.Options,
|
||||
}
|
||||
|
||||
namers[i] = namer
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/selection"
|
||||
|
||||
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
|
||||
|
|
@ -40,7 +41,7 @@ type MetricsQuery interface {
|
|||
// where we need to scope down more specifically than just the group-resource
|
||||
// (e.g. container metrics).
|
||||
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.
|
||||
|
|
@ -136,13 +137,13 @@ func (q *metricsQuery) Build(series string, resource schema.GroupResource, names
|
|||
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{}
|
||||
|
||||
// Build up the query parts from the selector.
|
||||
queryParts = append(queryParts, q.createQueryPartsFromSelector(metricSelector)...)
|
||||
|
||||
if namespace != "" {
|
||||
if namespace != "" && options.DetatchFromNamespace != true {
|
||||
namespaceLbl, err := q.resConverter.LabelForResource(NsGroupResource)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"testing"
|
||||
|
||||
prom "github.com/directxman12/k8s-prometheus-adapter/pkg/client"
|
||||
"github.com/directxman12/k8s-prometheus-adapter/pkg/config"
|
||||
pmodel "github.com/prometheus/common/model"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
|
@ -261,6 +262,7 @@ func TestBuildExternalSelector(t *testing.T) {
|
|||
groupBy string
|
||||
groupBySlice []string
|
||||
metricSelector labels.Selector
|
||||
options config.Options
|
||||
|
||||
check checkFunc
|
||||
}{
|
||||
|
|
@ -340,6 +342,36 @@ func TestBuildExternalSelector(t *testing.T) {
|
|||
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",
|
||||
|
||||
|
|
@ -384,7 +416,7 @@ func TestBuildExternalSelector(t *testing.T) {
|
|||
|
||||
for _, tc := range tests {
|
||||
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)
|
||||
|
||||
if err := tc.check(selector, err); err != nil {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue