Skip to content

Commit 4e30f4e

Browse files
authored
Merge pull request #1921 from dgrisonnet/simplify-metricswriter
Remove duplicated MetricsWriter implementation
2 parents 18d87c2 + fa89bc9 commit 4e30f4e

File tree

9 files changed

+55
-52
lines changed

9 files changed

+55
-52
lines changed

internal/store/builder.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -234,24 +234,20 @@ func (b *Builder) WithAllowLabels(labels map[string][]string) error {
234234
// Build initializes and registers all enabled stores.
235235
// It returns metrics writers which can be used to write out
236236
// metrics from the stores.
237-
func (b *Builder) Build() []metricsstore.MetricsWriter {
237+
func (b *Builder) Build() metricsstore.MetricsWriterList {
238238
if b.familyGeneratorFilter == nil {
239239
panic("familyGeneratorFilter should not be nil")
240240
}
241241

242-
var metricsWriters []metricsstore.MetricsWriter
242+
var metricsWriters metricsstore.MetricsWriterList
243243
var activeStoreNames []string
244244

245245
for _, c := range b.enabledResources {
246246
constructor, ok := availableStores[c]
247247
if ok {
248248
stores := cacheStoresToMetricStores(constructor(b))
249249
activeStoreNames = append(activeStoreNames, c)
250-
if len(stores) == 1 {
251-
metricsWriters = append(metricsWriters, stores[0])
252-
} else {
253-
metricsWriters = append(metricsWriters, metricsstore.NewMultiStoreMetricsWriter(stores))
254-
}
250+
metricsWriters = append(metricsWriters, metricsstore.NewMetricsWriter(stores...))
255251
}
256252
}
257253

pkg/builder/builder.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ package builder
1919
import (
2020
"context"
2121

22-
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
23-
2422
"github.com/prometheus/client_golang/prometheus"
2523
vpaclientset "k8s.io/autoscaler/vertical-pod-autoscaler/pkg/client/clientset/versioned"
2624
clientset "k8s.io/client-go/kubernetes"
@@ -29,6 +27,7 @@ import (
2927
internalstore "k8s.io/kube-state-metrics/v2/internal/store"
3028
ksmtypes "k8s.io/kube-state-metrics/v2/pkg/builder/types"
3129
"k8s.io/kube-state-metrics/v2/pkg/customresource"
30+
generator "k8s.io/kube-state-metrics/v2/pkg/metric_generator"
3231
metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store"
3332
"k8s.io/kube-state-metrics/v2/pkg/options"
3433
)
@@ -135,7 +134,7 @@ func (b *Builder) WithCustomResourceStoreFactories(fs ...customresource.Registry
135134

136135
// Build initializes and registers all enabled stores.
137136
// Returns metric writers.
138-
func (b *Builder) Build() []metricsstore.MetricsWriter {
137+
func (b *Builder) Build() metricsstore.MetricsWriterList {
139138
return b.internal.Build()
140139
}
141140

pkg/builder/types/interfaces.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type BuilderInterface interface {
5151
DefaultGenerateStoresFunc() BuildStoresFunc
5252
DefaultGenerateCustomResourceStoresFunc() BuildCustomResourceStoresFunc
5353
WithCustomResourceStoreFactories(fs ...customresource.RegistryFactory)
54-
Build() []metricsstore.MetricsWriter
54+
Build() metricsstore.MetricsWriterList
5555
BuildStores() [][]cache.Store
5656
}
5757

pkg/metrics_store/metrics_store.go

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

1919
import (
20-
"io"
2120
"sync"
2221

2322
"k8s.io/apimachinery/pkg/api/meta"
@@ -144,18 +143,3 @@ func (s *MetricsStore) Replace(list []interface{}, _ string) error {
144143
func (s *MetricsStore) Resync() error {
145144
return nil
146145
}
147-
148-
// WriteAll writes all metrics of the store into the given writer, zipped with the
149-
// help text of each metric family.
150-
func (s *MetricsStore) WriteAll(w io.Writer) {
151-
s.mutex.RLock()
152-
defer s.mutex.RUnlock()
153-
154-
for i, help := range s.headers {
155-
w.Write([]byte(help))
156-
w.Write([]byte{'\n'})
157-
for _, metricFamilies := range s.metrics {
158-
w.Write(metricFamilies[i])
159-
}
160-
}
161-
}

pkg/metrics_store/metrics_store_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ func TestObjectsSameNameDifferentNamespaces(t *testing.T) {
8181
}
8282

8383
w := strings.Builder{}
84-
ms.WriteAll(&w)
84+
mw := NewMetricsWriter(ms)
85+
err := mw.WriteAll(&w)
86+
if err != nil {
87+
t.Fatalf("failed to write metrics: %v", err)
88+
}
8589
m := w.String()
8690

8791
for _, id := range serviceIDS {

pkg/metrics_store/metrics_writer.go

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,28 @@ limitations under the License.
1616

1717
package metricsstore
1818

19-
import "io"
19+
import (
20+
"fmt"
21+
"io"
22+
)
2023

21-
// MetricsWriter is the interface that wraps the WriteAll method.
22-
// WriteAll writes out bytes to the underlying writer.
23-
type MetricsWriter interface {
24-
WriteAll(w io.Writer)
25-
}
24+
// MetricsWriterList represent a list of MetricsWriter
25+
type MetricsWriterList []*MetricsWriter
2626

27-
// MultiStoreMetricsWriter is a struct that holds multiple MetricsStore(s) and
27+
// MetricsWriter is a struct that holds multiple MetricsStore(s) and
2828
// implements the MetricsWriter interface.
2929
// It should be used with stores which have the same metric headers.
3030
//
31-
// MultiStoreMetricsWriter writes out metrics from the underlying stores so that
31+
// MetricsWriter writes out metrics from the underlying stores so that
3232
// metrics with the same name coming from different stores end up grouped together.
3333
// It also ensures that the metric headers are only written out once.
34-
type MultiStoreMetricsWriter struct {
34+
type MetricsWriter struct {
3535
stores []*MetricsStore
3636
}
3737

38-
// NewMultiStoreMetricsWriter creates a new MultiStoreMetricsWriter.
39-
func NewMultiStoreMetricsWriter(stores []*MetricsStore) MetricsWriter {
40-
return &MultiStoreMetricsWriter{
38+
// NewMetricsWriter creates a new MetricsWriter.
39+
func NewMetricsWriter(stores ...*MetricsStore) *MetricsWriter {
40+
return &MetricsWriter{
4141
stores: stores,
4242
}
4343
}
@@ -46,9 +46,9 @@ func NewMultiStoreMetricsWriter(stores []*MetricsStore) MetricsWriter {
4646
//
4747
// WriteAll writes metrics so that the ones with the same name
4848
// are grouped together when written out.
49-
func (m MultiStoreMetricsWriter) WriteAll(w io.Writer) {
49+
func (m MetricsWriter) WriteAll(w io.Writer) error {
5050
if len(m.stores) == 0 {
51-
return
51+
return nil
5252
}
5353

5454
for _, s := range m.stores {
@@ -59,12 +59,19 @@ func (m MultiStoreMetricsWriter) WriteAll(w io.Writer) {
5959
}
6060

6161
for i, help := range m.stores[0].headers {
62-
w.Write([]byte(help))
63-
w.Write([]byte{'\n'})
62+
_, err := w.Write([]byte(help + "\n"))
63+
if err != nil {
64+
return fmt.Errorf("failed to write help text: %v", err)
65+
}
66+
6467
for _, s := range m.stores {
6568
for _, metricFamilies := range s.metrics {
66-
w.Write(metricFamilies[i])
69+
_, err := w.Write(metricFamilies[i])
70+
if err != nil {
71+
return fmt.Errorf("failed to write metrics family: %v", err)
72+
}
6773
}
6874
}
6975
}
76+
return nil
7077
}

pkg/metrics_store/metrics_writer_test.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,12 @@ func TestWriteAllWithSingleStore(t *testing.T) {
8383
}
8484
}
8585

86-
multiNsWriter := metricsstore.NewMultiStoreMetricsWriter([]*metricsstore.MetricsStore{store})
86+
multiNsWriter := metricsstore.NewMetricsWriter(store)
8787
w := strings.Builder{}
88-
multiNsWriter.WriteAll(&w)
88+
err := multiNsWriter.WriteAll(&w)
89+
if err != nil {
90+
t.Fatalf("failed to write metrics: %v", err)
91+
}
8992
result := w.String()
9093

9194
resultLines := strings.Split(strings.TrimRight(result, "\n"), "\n")
@@ -192,9 +195,12 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
192195
}
193196
}
194197

195-
multiNsWriter := metricsstore.NewMultiStoreMetricsWriter([]*metricsstore.MetricsStore{s1, s2})
198+
multiNsWriter := metricsstore.NewMetricsWriter(s1, s2)
196199
w := strings.Builder{}
197-
multiNsWriter.WriteAll(&w)
200+
err := multiNsWriter.WriteAll(&w)
201+
if err != nil {
202+
t.Fatalf("failed to write metrics: %v", err)
203+
}
198204
result := w.String()
199205

200206
resultLines := strings.Split(strings.TrimRight(result, "\n"), "\n")

pkg/metricshandler/metrics_handler.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ type MetricsHandler struct {
5151

5252
// mtx protects metricsWriters, curShard, and curTotalShards
5353
mtx *sync.RWMutex
54-
metricsWriters []metricsstore.MetricsWriter
54+
metricsWriters metricsstore.MetricsWriterList
5555
curShard int32
5656
curTotalShards int
5757
}
@@ -200,7 +200,10 @@ func (m *MetricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
200200
}
201201

202202
for _, w := range m.metricsWriters {
203-
w.WriteAll(writer)
203+
err := w.WriteAll(writer)
204+
if err != nil {
205+
klog.ErrorS(err, "Failed to write metrics")
206+
}
204207
}
205208

206209
// In case we gzipped the response, we have to close the writer.

tests/lib/lib_test.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ func TestAsLibrary(t *testing.T) {
5555
time.Sleep(time.Second)
5656

5757
w := strings.Builder{}
58-
c.WriteAll(&w)
58+
mw := metricsstore.NewMetricsWriter(c)
59+
err = mw.WriteAll(&w)
60+
if err != nil {
61+
t.Fatalf("failed to write metrics: %v", err)
62+
}
5963
m := w.String()
6064

6165
if !strings.Contains(m, service.ObjectMeta.Name) {

0 commit comments

Comments
 (0)