Skip to content

Commit 535085e

Browse files
authored
Merge pull request #2154 from chrischdi/pr-custom-metrics-missing-header
fix: custommetrics: always extract the headers but only write it when we have metrics
2 parents 801f8bb + e57a28a commit 535085e

File tree

3 files changed

+39
-77
lines changed

3 files changed

+39
-77
lines changed

internal/store/builder.go

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ import (
3838
policyv1 "k8s.io/api/policy/v1"
3939
rbacv1 "k8s.io/api/rbac/v1"
4040
storagev1 "k8s.io/api/storage/v1"
41-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
42-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
43-
"k8s.io/apimachinery/pkg/runtime/schema"
44-
"k8s.io/client-go/discovery"
4541
clientset "k8s.io/client-go/kubernetes"
4642
"k8s.io/client-go/tools/cache"
4743
"k8s.io/klog/v2"
@@ -544,10 +540,7 @@ func (b *Builder) buildCustomResourceStores(resourceName string,
544540
metricFamilies = generator.FilterFamilyGenerators(b.familyGeneratorFilter, metricFamilies)
545541
composedMetricGenFuncs := generator.ComposeMetricGenFuncs(metricFamilies)
546542

547-
var familyHeaders []string
548-
if b.hasResources(resourceName, expectedType) {
549-
familyHeaders = generator.ExtractMetricFamilyHeaders(metricFamilies)
550-
}
543+
familyHeaders := generator.ExtractMetricFamilyHeaders(metricFamilies)
551544

552545
gvr := util.GVRFromType(resourceName, expectedType)
553546
var gvrString string
@@ -590,65 +583,6 @@ func (b *Builder) buildCustomResourceStores(resourceName string,
590583
return stores
591584
}
592585

593-
func (b *Builder) hasResources(resourceName string, expectedType interface{}) bool {
594-
gvr := util.GVRFromType(resourceName, expectedType)
595-
if gvr == nil {
596-
return true
597-
}
598-
discoveryClient, err := util.CreateDiscoveryClient(b.utilOptions.Apiserver, b.utilOptions.Kubeconfig)
599-
if err != nil {
600-
klog.ErrorS(err, "Failed to create discovery client")
601-
return false
602-
}
603-
g := gvr.Group
604-
v := gvr.Version
605-
r := gvr.Resource
606-
isCRDInstalled, err := discovery.IsResourceEnabled(discoveryClient, schema.GroupVersionResource{
607-
Group: g,
608-
Version: v,
609-
Resource: r,
610-
})
611-
if err != nil {
612-
klog.ErrorS(err, "Failed to check if CRD is enabled", "group", g, "version", v, "resource", r)
613-
return false
614-
}
615-
if !isCRDInstalled {
616-
klog.InfoS("CRD is not installed", "group", g, "version", v, "resource", r)
617-
return false
618-
}
619-
// Wait for the resource to come up.
620-
timer := time.NewTimer(ResourceDiscoveryTimeout)
621-
ticker := time.NewTicker(ResourceDiscoveryInterval)
622-
dynamicClient, err := util.CreateDynamicClient(b.utilOptions.Apiserver, b.utilOptions.Kubeconfig)
623-
if err != nil {
624-
klog.ErrorS(err, "Failed to create dynamic client")
625-
return false
626-
}
627-
var list *unstructured.UnstructuredList
628-
for range ticker.C {
629-
select {
630-
case <-timer.C:
631-
klog.InfoS("No CRs found for GVR", "group", g, "version", v, "resource", r)
632-
return false
633-
default:
634-
list, err = dynamicClient.Resource(schema.GroupVersionResource{
635-
Group: g,
636-
Version: v,
637-
Resource: r,
638-
}).List(b.ctx, metav1.ListOptions{})
639-
if err != nil {
640-
klog.ErrorS(err, "Failed to list objects", "group", g, "version", v, "resource", r)
641-
return false
642-
}
643-
}
644-
if len(list.Items) > 0 {
645-
break
646-
}
647-
}
648-
649-
return true
650-
}
651-
652586
// startReflector starts a Kubernetes client-go reflector with the given
653587
// listWatcher and registers it with the given store.
654588
func (b *Builder) startReflector(

pkg/metrics_store/metrics_writer.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,20 +58,16 @@ func (m MetricsWriter) WriteAll(w io.Writer) error {
5858
}(s)
5959
}
6060

61-
// If the first store has no headers, but has metrics, we need to write out
62-
// an empty header to ensure that the metrics are written out correctly.
63-
if m.stores[0].headers == nil && m.stores[0].metrics != nil {
64-
m.stores[0].headers = []string{""}
65-
}
6661
for i, help := range m.stores[0].headers {
6762
if help != "" && help != "\n" {
6863
help += "\n"
6964
}
70-
// TODO: This writes out the help text for each metric family, before checking if the metrics for it exist,
71-
// TODO: which is not ideal, and furthermore, diverges from the OpenMetrics standard.
72-
_, err := w.Write([]byte(help))
73-
if err != nil {
74-
return fmt.Errorf("failed to write help text: %v", err)
65+
66+
if len(m.stores[0].metrics) > 0 {
67+
_, err := w.Write([]byte(help))
68+
if err != nil {
69+
return fmt.Errorf("failed to write help text: %v", err)
70+
}
7571
}
7672

7773
for _, s := range m.stores {

pkg/metrics_store/metrics_writer_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package metricsstore_test
1818

1919
import (
20+
"fmt"
2021
"strings"
2122
"testing"
2223

@@ -231,3 +232,34 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
231232
}
232233
}
233234
}
235+
236+
// TestWriteAllWithEmptyStores checks that nothing is printed if no metrics exist for metric families.
237+
func TestWriteAllWithEmptyStores(t *testing.T) {
238+
genFunc := func(obj interface{}) []metric.FamilyInterface {
239+
mf1 := metric.Family{
240+
Name: "kube_service_info_1",
241+
Metrics: []*metric.Metric{},
242+
}
243+
244+
mf2 := metric.Family{
245+
Name: "kube_service_info_2",
246+
Metrics: []*metric.Metric{},
247+
}
248+
249+
return []metric.FamilyInterface{&mf1, &mf2}
250+
}
251+
store := metricsstore.NewMetricsStore([]string{"Info 1 about services", "Info 2 about services"}, genFunc)
252+
253+
multiNsWriter := metricsstore.NewMetricsWriter(store)
254+
w := strings.Builder{}
255+
err := multiNsWriter.WriteAll(&w)
256+
if err != nil {
257+
t.Fatalf("failed to write metrics: %v", err)
258+
}
259+
result := w.String()
260+
fmt.Println(result)
261+
262+
if result != "" {
263+
t.Fatalf("Unexpected output, got %q, want %q", result, "")
264+
}
265+
}

0 commit comments

Comments
 (0)