diff --git a/pkg/kapis/monitoring/v1alpha3/register.go b/pkg/kapis/monitoring/v1alpha3/register.go index f1e778ce3..e180cb2ce 100644 --- a/pkg/kapis/monitoring/v1alpha3/register.go +++ b/pkg/kapis/monitoring/v1alpha3/register.go @@ -464,6 +464,38 @@ func AddToContainer(c *restful.Container, k8sClient kubernetes.Interface, monito Returns(http.StatusOK, respOK, monitoring.Metric{})). Produces(restful.MIME_JSON) + ws.Route(ws.GET("/targets/metadata"). + To(h.handleMetadataQuery). + Doc("Get metadata of metrics in the whole cluster."). + Metadata(restfulspec.KeyOpenAPITags, []string{constants.CustomMetricsTag}). + Writes(model.Metadata{}). + Returns(http.StatusOK, respOK, model.Metadata{})). + Produces(restful.MIME_JSON) + + ws.Route(ws.GET("/targets/labelsets"). + To(h.handleMetricLabelSetQuery). + Doc("List all available labels and values of a metric within a specific time span in the whole cluster."). + Param(ws.QueryParameter("metric", "The name of the metric").DataType("string").Required(true)). + Param(ws.QueryParameter("start", "Start time of query. It is a string with Unix time format, eg. 1559347200. ").DataType("string").Required(true)). + Param(ws.QueryParameter("end", "End time of query. It is a string with Unix time format, eg. 1561939200. ").DataType("string").Required(true)). + Metadata(restfulspec.KeyOpenAPITags, []string{constants.CustomMetricsTag}). + Writes(model.MetricLabelSet{}). + Returns(http.StatusOK, respOK, model.MetricLabelSet{})). + Produces(restful.MIME_JSON) + + ws.Route(ws.GET("/targets/query"). + To(h.handleAdhocQuery). + Doc("Make an ad-hoc query in the whole cluster."). + Param(ws.QueryParameter("expr", "The expression to be evaluated.").DataType("string").Required(false)). + Param(ws.QueryParameter("start", "Start time of query. Use **start** and **end** to retrieve metric data over a time span. It is a string with Unix time format, eg. 1559347200. ").DataType("string").Required(false)). + Param(ws.QueryParameter("end", "End time of query. Use **start** and **end** to retrieve metric data over a time span. It is a string with Unix time format, eg. 1561939200. ").DataType("string").Required(false)). + Param(ws.QueryParameter("step", "Time interval. Retrieve metric data at a fixed interval within the time range of start and end. It requires both **start** and **end** are provided. The format is [0-9]+[smhdwy]. Defaults to 10m (i.e. 10 min).").DataType("string").DefaultValue("10m").Required(false)). + Param(ws.QueryParameter("time", "A timestamp in Unix time format. Retrieve metric data at a single point in time. Defaults to now. Time and the combination of start, end, step are mutually exclusive.").DataType("string").Required(false)). + Metadata(restfulspec.KeyOpenAPITags, []string{constants.CustomMetricsTag}). + Writes(monitoring.Metric{}). + Returns(http.StatusOK, respOK, monitoring.Metric{})). + Produces(restful.MIME_JSON) + c.Add(ws) return nil } diff --git a/pkg/models/monitoring/monitoring.go b/pkg/models/monitoring/monitoring.go index b945a6c15..5fc49bea0 100644 --- a/pkg/models/monitoring/monitoring.go +++ b/pkg/models/monitoring/monitoring.go @@ -62,25 +62,31 @@ func NewMonitoringOperator(client monitoring.Interface, k8s kubernetes.Interface } func (mo monitoringOperator) GetMetric(expr, namespace string, time time.Time) (monitoring.Metric, error) { - // Different monitoring backend implementations have different ways to enforce namespace isolation. - // Each implementation should register itself to `ReplaceNamespaceFns` during init(). - // We hard code "prometheus" here because we only support this datasource so far. - // In the future, maybe the value should be returned from a method like `mo.c.GetMonitoringServiceName()`. - expr, err := expressions.ReplaceNamespaceFns["prometheus"](expr, namespace) - if err != nil { - return monitoring.Metric{}, err + if namespace != "" { + // Different monitoring backend implementations have different ways to enforce namespace isolation. + // Each implementation should register itself to `ReplaceNamespaceFns` during init(). + // We hard code "prometheus" here because we only support this datasource so far. + // In the future, maybe the value should be returned from a method like `mo.c.GetMonitoringServiceName()`. + var err error + expr, err = expressions.ReplaceNamespaceFns["prometheus"](expr, namespace) + if err != nil { + return monitoring.Metric{}, err + } } return mo.c.GetMetric(expr, time), nil } func (mo monitoringOperator) GetMetricOverTime(expr, namespace string, start, end time.Time, step time.Duration) (monitoring.Metric, error) { - // Different monitoring backend implementations have different ways to enforce namespace isolation. - // Each implementation should register itself to `ReplaceNamespaceFns` during init(). - // We hard code "prometheus" here because we only support this datasource so far. - // In the future, maybe the value should be returned from a method like `mo.c.GetMonitoringServiceName()`. - expr, err := expressions.ReplaceNamespaceFns["prometheus"](expr, namespace) - if err != nil { - return monitoring.Metric{}, err + if namespace != "" { + // Different monitoring backend implementations have different ways to enforce namespace isolation. + // Each implementation should register itself to `ReplaceNamespaceFns` during init(). + // We hard code "prometheus" here because we only support this datasource so far. + // In the future, maybe the value should be returned from a method like `mo.c.GetMonitoringServiceName()`. + var err error + expr, err = expressions.ReplaceNamespaceFns["prometheus"](expr, namespace) + if err != nil { + return monitoring.Metric{}, err + } } return mo.c.GetMetricOverTime(expr, start, end, step), nil } @@ -101,14 +107,18 @@ func (mo monitoringOperator) GetMetadata(namespace string) Metadata { } func (mo monitoringOperator) GetMetricLabelSet(metric, namespace string, start, end time.Time) MetricLabelSet { - // Different monitoring backend implementations have different ways to enforce namespace isolation. - // Each implementation should register itself to `ReplaceNamespaceFns` during init(). - // We hard code "prometheus" here because we only support this datasource so far. - // In the future, maybe the value should be returned from a method like `mo.c.GetMonitoringServiceName()`. - expr, err := expressions.ReplaceNamespaceFns["prometheus"](metric, namespace) - if err != nil { - klog.Error(err) - return MetricLabelSet{} + var expr = metric + var err error + if namespace != "" { + // Different monitoring backend implementations have different ways to enforce namespace isolation. + // Each implementation should register itself to `ReplaceNamespaceFns` during init(). + // We hard code "prometheus" here because we only support this datasource so far. + // In the future, maybe the value should be returned from a method like `mo.c.GetMonitoringServiceName()`. + expr, err = expressions.ReplaceNamespaceFns["prometheus"](metric, namespace) + if err != nil { + klog.Error(err) + return MetricLabelSet{} + } } data := mo.c.GetMetricLabelSet(expr, start, end) return MetricLabelSet{Data: data} diff --git a/pkg/simple/client/monitoring/prometheus/prometheus.go b/pkg/simple/client/monitoring/prometheus/prometheus.go index ccdfe11c3..f03e69647 100644 --- a/pkg/simple/client/monitoring/prometheus/prometheus.go +++ b/pkg/simple/client/monitoring/prometheus/prometheus.go @@ -147,9 +147,12 @@ func (p prometheus) GetNamedMetricsOverTime(metrics []string, start, end time.Ti func (p prometheus) GetMetadata(namespace string) []monitoring.Metadata { var meta []monitoring.Metadata + var matchTarget string - // Filter metrics available to members of this namespace - matchTarget := fmt.Sprintf("{namespace=\"%s\"}", namespace) + if namespace != "" { + // Filter metrics available to members of this namespace + matchTarget = fmt.Sprintf("{namespace=\"%s\"}", namespace) + } items, err := p.client.TargetsMetadata(context.Background(), matchTarget, "", "") if err != nil { klog.Error(err)