@@ -14,21 +14,21 @@ See the License for the specific language governing permissions and
14
14
limitations under the License.
15
15
*/
16
16
17
- package metricsstore_test
17
+ package metricsstore
18
18
19
19
import (
20
20
"fmt"
21
+ "github.com/google/go-cmp/cmp"
22
+ "github.com/prometheus/common/expfmt"
23
+ "reflect"
21
24
"strings"
22
25
"testing"
23
26
24
- "github.com/prometheus/common/expfmt"
25
-
26
27
v1 "k8s.io/api/core/v1"
27
28
"k8s.io/apimachinery/pkg/api/meta"
28
29
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
30
30
31
"k8s.io/kube-state-metrics/v2/pkg/metric"
31
- metricsstore "k8s.io/kube-state-metrics/v2/pkg/metrics_store"
32
32
)
33
33
34
34
func TestWriteAllWithSingleStore (t * testing.T ) {
@@ -62,7 +62,7 @@ func TestWriteAllWithSingleStore(t *testing.T) {
62
62
63
63
return []metric.FamilyInterface {& mf1 , & mf2 }
64
64
}
65
- store := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
65
+ store := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
66
66
svcs := []v1.Service {
67
67
{
68
68
ObjectMeta : metav1.ObjectMeta {
@@ -86,7 +86,7 @@ func TestWriteAllWithSingleStore(t *testing.T) {
86
86
}
87
87
}
88
88
89
- multiNsWriter := metricsstore . NewMetricsWriter (store )
89
+ multiNsWriter := NewMetricsWriter (store )
90
90
w := strings.Builder {}
91
91
err := multiNsWriter .WriteAll (& w )
92
92
if err != nil {
@@ -150,7 +150,7 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
150
150
151
151
return []metric.FamilyInterface {& mf1 , & mf2 }
152
152
}
153
- s1 := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
153
+ s1 := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
154
154
svcs1 := []v1.Service {
155
155
{
156
156
ObjectMeta : metav1.ObjectMeta {
@@ -190,15 +190,15 @@ func TestWriteAllWithMultipleStores(t *testing.T) {
190
190
},
191
191
},
192
192
}
193
- s2 := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
193
+ s2 := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
194
194
for _ , s := range svcs2 {
195
195
svc := s
196
196
if err := s2 .Add (& svc ); err != nil {
197
197
t .Fatal (err )
198
198
}
199
199
}
200
200
201
- multiNsWriter := metricsstore . NewMetricsWriter (s1 , s2 )
201
+ multiNsWriter := NewMetricsWriter (s1 , s2 )
202
202
w := strings.Builder {}
203
203
err := multiNsWriter .WriteAll (& w )
204
204
if err != nil {
@@ -250,9 +250,9 @@ func TestWriteAllWithEmptyStores(t *testing.T) {
250
250
251
251
return []metric.FamilyInterface {& mf1 , & mf2 }
252
252
}
253
- store := metricsstore . NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
253
+ store := NewMetricsStore ([]string {"Info 1 about services" , "Info 2 about services" }, genFunc )
254
254
255
- multiNsWriter := metricsstore . NewMetricsWriter (store )
255
+ multiNsWriter := NewMetricsWriter (store )
256
256
w := strings.Builder {}
257
257
err := multiNsWriter .WriteAll (& w )
258
258
if err != nil {
@@ -266,6 +266,103 @@ func TestWriteAllWithEmptyStores(t *testing.T) {
266
266
}
267
267
}
268
268
269
+ // TODO: AFAIR empty headers are ignored by Prometheus? If not, we should remove them.
270
+ func TestSanitizeHeaders (t * testing.T ) {
271
+ boilerplateHeaders := []string {
272
+ "" ,
273
+ "" ,
274
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
275
+ "# HELP foo foo_help\n # TYPE foo info" ,
276
+ "# HELP foo foo_help\n # TYPE foo stateset" ,
277
+ "# HELP foo foo_help\n # TYPE foo counter" ,
278
+ }
279
+ duplicatedBoilerplateHeaders := []string {
280
+ "" ,
281
+ "" ,
282
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
283
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
284
+ "# HELP foo foo_help\n # TYPE foo info" ,
285
+ "# HELP foo foo_help\n # TYPE foo info" ,
286
+ "# HELP foo foo_help\n # TYPE foo stateset" ,
287
+ "# HELP foo foo_help\n # TYPE foo stateset" ,
288
+ "# HELP foo foo_help\n # TYPE foo counter" ,
289
+ "# HELP foo foo_help\n # TYPE foo counter" ,
290
+ }
291
+ dedepedBoilerplateHeaders := []string {
292
+ "" ,
293
+ "" ,
294
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
295
+ "" ,
296
+ "# HELP foo foo_help\n # TYPE foo info" ,
297
+ "" ,
298
+ "# HELP foo foo_help\n # TYPE foo stateset" ,
299
+ "" ,
300
+ "# HELP foo foo_help\n # TYPE foo counter" ,
301
+ "" ,
302
+ }
303
+ protoIngestibleHeaders := []string {
304
+ "" ,
305
+ "" ,
306
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
307
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
308
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
309
+ "# HELP foo foo_help\n # TYPE foo counter" ,
310
+ }
311
+ dedepedProtoIngestibleHeaders := []string {
312
+ "" ,
313
+ "" ,
314
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
315
+ "" ,
316
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
317
+ "" ,
318
+ "# HELP foo foo_help\n # TYPE foo gauge" ,
319
+ "" ,
320
+ "# HELP foo foo_help\n # TYPE foo counter" ,
321
+ "" ,
322
+ }
323
+ testcases := []struct {
324
+ name string
325
+ contentType expfmt.Format
326
+ headers []string
327
+ expectedHeaders []string
328
+ }{
329
+ {
330
+ name : "text-format unique headers" ,
331
+ contentType : expfmt .FmtText ,
332
+ headers : boilerplateHeaders ,
333
+ expectedHeaders : boilerplateHeaders ,
334
+ },
335
+ {
336
+ name : "text-format consecutive duplicate headers" ,
337
+ contentType : expfmt .FmtText ,
338
+ headers : duplicatedBoilerplateHeaders ,
339
+ expectedHeaders : dedepedBoilerplateHeaders ,
340
+ },
341
+ {
342
+ name : "proto-format unique headers" ,
343
+ contentType : expfmt .ProtoFmt , // Prometheus ProtoFmt is the only proto-based format we check for.
344
+ headers : boilerplateHeaders ,
345
+ expectedHeaders : protoIngestibleHeaders ,
346
+ },
347
+ {
348
+ name : "proto-format consecutive duplicate headers" ,
349
+ contentType : expfmt .ProtoFmt , // Prometheus ProtoFmt is the only proto-based format we check for.
350
+ headers : duplicatedBoilerplateHeaders ,
351
+ expectedHeaders : dedepedProtoIngestibleHeaders ,
352
+ },
353
+ }
354
+
355
+ for _ , testcase := range testcases {
356
+ writer := NewMetricsWriter (NewMetricsStore (testcase .headers , nil ))
357
+ t .Run (testcase .name , func (t * testing.T ) {
358
+ SanitizeHeaders (string (testcase .contentType ), MetricsWriterList {writer })
359
+ if ! reflect .DeepEqual (testcase .expectedHeaders , writer .stores [0 ].headers ) {
360
+ t .Fatalf ("(-want, +got):\n %s" , cmp .Diff (testcase .expectedHeaders , writer .stores [0 ].headers ))
361
+ }
362
+ })
363
+ }
364
+ }
365
+
269
366
func BenchmarkSanitizeHeaders (b * testing.B ) {
270
367
benchmarks := []struct {
271
368
name string
@@ -303,10 +400,10 @@ func BenchmarkSanitizeHeaders(b *testing.B) {
303
400
headers = append (headers , fmt .Sprintf ("# HELP foo_%d foo_help\n # TYPE foo_%d info" , j , j ))
304
401
}
305
402
}
306
- writer := metricsstore . NewMetricsWriter (metricsstore . NewMetricsStore (headers , nil ))
403
+ writer := NewMetricsWriter (NewMetricsStore (headers , nil ))
307
404
b .Run (benchmark .name , func (b * testing.B ) {
308
405
for i := 0 ; i < b .N ; i ++ {
309
- metricsstore . SanitizeHeaders (string (benchmark .contentType ), metricsstore. MetricsWriterList {writer })
406
+ SanitizeHeaders (string (benchmark .contentType ), MetricsWriterList {writer })
310
407
}
311
408
})
312
409
}
0 commit comments