github.com/google/cadvisor@v0.49.1/collector/prometheus_collector_test.go (about)

     1  // Copyright 2015 Google Inc. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package collector
    16  
    17  import (
    18  	"fmt"
    19  	"net/http"
    20  	"net/http/httptest"
    21  	"os"
    22  	"testing"
    23  
    24  	"github.com/stretchr/testify/assert"
    25  	"github.com/stretchr/testify/require"
    26  
    27  	containertest "github.com/google/cadvisor/container/testing"
    28  	v1 "github.com/google/cadvisor/info/v1"
    29  )
    30  
    31  func TestPrometheus(t *testing.T) {
    32  	assert := assert.New(t)
    33  
    34  	// Create a prometheus collector using the config file 'sample_config_prometheus.json'
    35  	configFile, err := os.ReadFile("config/sample_config_prometheus.json")
    36  	assert.NoError(err)
    37  	containerHandler := containertest.NewMockContainerHandler("mockContainer")
    38  	collector, err := NewPrometheusCollector("Prometheus", configFile, 100, containerHandler, http.DefaultClient)
    39  	assert.NoError(err)
    40  	assert.Equal("Prometheus", collector.name)
    41  	assert.Equal("http://localhost:8080/metrics", collector.configFile.Endpoint.URL)
    42  
    43  	tempServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    44  
    45  		text := `# HELP go_gc_duration_seconds A summary of the GC invocation durations.
    46  # TYPE go_gc_duration_seconds summary
    47  go_gc_duration_seconds{quantile="0"} 5.8348000000000004e-05
    48  go_gc_duration_seconds{quantile="1"} 0.000499764
    49  go_gc_duration_seconds_sum 1.7560473e+07
    50  go_gc_duration_seconds_count 2693
    51  # HELP go_goroutines Number of goroutines that currently exist.
    52  # TYPE go_goroutines gauge
    53  go_goroutines 16
    54  # HELP empty_metric A metric without any values
    55  # TYPE empty_metric counter
    56  # HELP metric_with_spaces_in_label A metric with spaces in a label.
    57  # TYPE metric_with_spaces_in_label gauge
    58  metric_with_spaces_in_label{name="Network Agent"} 72
    59  # HELP metric_with_multiple_labels A metric with multiple labels.
    60  # TYPE metric_with_multiple_labels gauge
    61  metric_with_multiple_labels{label1="One", label2="Two", label3="Three"} 81
    62  `
    63  		fmt.Fprintln(w, text)
    64  	}))
    65  
    66  	defer tempServer.Close()
    67  
    68  	collector.configFile.Endpoint.URL = tempServer.URL
    69  
    70  	var spec []v1.MetricSpec
    71  	require.NotPanics(t, func() { spec = collector.GetSpec() })
    72  	assert.Len(spec, 4)
    73  	specNames := make(map[string]struct{}, 3)
    74  	for _, s := range spec {
    75  		specNames[s.Name] = struct{}{}
    76  	}
    77  	expectedSpecNames := map[string]struct{}{
    78  		"go_gc_duration_seconds":      {},
    79  		"go_goroutines":               {},
    80  		"metric_with_spaces_in_label": {},
    81  		"metric_with_multiple_labels": {},
    82  	}
    83  	assert.Equal(expectedSpecNames, specNames)
    84  
    85  	metrics := map[string][]v1.MetricVal{}
    86  	_, metrics, errMetric := collector.Collect(metrics)
    87  
    88  	assert.NoError(errMetric)
    89  
    90  	gcDuration := metrics["go_gc_duration_seconds"]
    91  	assert.Equal(5.8348000000000004e-05, gcDuration[0].FloatValue)
    92  	assert.Equal("__name__=go_gc_duration_seconds\xffquantile=0", gcDuration[0].Label)
    93  	assert.Equal(0.000499764, gcDuration[1].FloatValue)
    94  	assert.Equal("__name__=go_gc_duration_seconds\xffquantile=1", gcDuration[1].Label)
    95  	gcDurationSum := metrics["go_gc_duration_seconds_sum"]
    96  	assert.Equal(1.7560473e+07, gcDurationSum[0].FloatValue)
    97  	assert.Equal("__name__=go_gc_duration_seconds_sum", gcDurationSum[0].Label)
    98  	gcDurationCount := metrics["go_gc_duration_seconds_count"]
    99  	assert.Equal(float64(2693), gcDurationCount[0].FloatValue)
   100  	assert.Equal("__name__=go_gc_duration_seconds_count", gcDurationCount[0].Label)
   101  
   102  	goRoutines := metrics["go_goroutines"]
   103  	assert.Equal(float64(16), goRoutines[0].FloatValue)
   104  	assert.Equal("__name__=go_goroutines", goRoutines[0].Label)
   105  
   106  	metricWithSpaces := metrics["metric_with_spaces_in_label"]
   107  	assert.Equal(float64(72), metricWithSpaces[0].FloatValue)
   108  	assert.Equal("__name__=metric_with_spaces_in_label\xffname=Network Agent", metricWithSpaces[0].Label)
   109  
   110  	metricWithMultipleLabels := metrics["metric_with_multiple_labels"]
   111  	assert.Equal(float64(81), metricWithMultipleLabels[0].FloatValue)
   112  	assert.Equal("__name__=metric_with_multiple_labels\xfflabel1=One\xfflabel2=Two\xfflabel3=Three", metricWithMultipleLabels[0].Label)
   113  }
   114  
   115  func TestPrometheusEndpointConfig(t *testing.T) {
   116  	assert := assert.New(t)
   117  
   118  	//Create a prometheus collector using the config file 'sample_config_prometheus.json'
   119  	configFile, err := os.ReadFile("config/sample_config_prometheus_endpoint_config.json")
   120  	assert.NoError(err)
   121  	containerHandler := containertest.NewMockContainerHandler("mockContainer")
   122  	containerHandler.On("GetContainerIPAddress").Return(
   123  		"222.222.222.222",
   124  	)
   125  
   126  	collector, err := NewPrometheusCollector("Prometheus", configFile, 100, containerHandler, http.DefaultClient)
   127  	assert.NoError(err)
   128  	assert.Equal(collector.name, "Prometheus")
   129  	assert.Equal(collector.configFile.Endpoint.URL, "http://222.222.222.222:8081/METRICS")
   130  }
   131  
   132  func TestPrometheusShortResponse(t *testing.T) {
   133  	assert := assert.New(t)
   134  
   135  	// Create a prometheus collector using the config file 'sample_config_prometheus.json'
   136  	configFile, err := os.ReadFile("config/sample_config_prometheus.json")
   137  	assert.NoError(err)
   138  	containerHandler := containertest.NewMockContainerHandler("mockContainer")
   139  	collector, err := NewPrometheusCollector("Prometheus", configFile, 100, containerHandler, http.DefaultClient)
   140  	assert.NoError(err)
   141  	assert.Equal(collector.name, "Prometheus")
   142  	assert.Equal(collector.configFile.Endpoint.URL, "http://localhost:8080/metrics")
   143  
   144  	tempServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   145  		text := "# HELP empty_metric A metric without any values"
   146  		fmt.Fprint(w, text)
   147  	}))
   148  
   149  	defer tempServer.Close()
   150  
   151  	collector.configFile.Endpoint.URL = tempServer.URL
   152  
   153  	assert.NotPanics(func() { collector.GetSpec() })
   154  }
   155  
   156  func TestPrometheusMetricCountLimit(t *testing.T) {
   157  	assert := assert.New(t)
   158  
   159  	// Create a prometheus collector using the config file 'sample_config_prometheus.json'
   160  	configFile, err := os.ReadFile("config/sample_config_prometheus.json")
   161  	assert.NoError(err)
   162  	containerHandler := containertest.NewMockContainerHandler("mockContainer")
   163  	collector, err := NewPrometheusCollector("Prometheus", configFile, 10, containerHandler, http.DefaultClient)
   164  	assert.NoError(err)
   165  	assert.Equal(collector.name, "Prometheus")
   166  	assert.Equal(collector.configFile.Endpoint.URL, "http://localhost:8080/metrics")
   167  
   168  	tempServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   169  		for i := 0; i < 30; i++ {
   170  			fmt.Fprintf(w, "# HELP m%d Number of goroutines that currently exist.\n", i)
   171  			fmt.Fprintf(w, "# TYPE m%d gauge\n", i)
   172  			fmt.Fprintf(w, "m%d %d", i, i)
   173  		}
   174  	}))
   175  	defer tempServer.Close()
   176  
   177  	collector.configFile.Endpoint.URL = tempServer.URL
   178  	metrics := map[string][]v1.MetricVal{}
   179  	_, result, errMetric := collector.Collect(metrics)
   180  
   181  	assert.Error(errMetric)
   182  	assert.Equal(len(metrics), 0)
   183  	assert.Nil(result)
   184  }
   185  
   186  func TestPrometheusFiltersMetrics(t *testing.T) {
   187  	assert := assert.New(t)
   188  
   189  	// Create a prometheus collector using the config file 'sample_config_prometheus_filtered.json'
   190  	configFile, err := os.ReadFile("config/sample_config_prometheus_filtered.json")
   191  	assert.NoError(err)
   192  	containerHandler := containertest.NewMockContainerHandler("mockContainer")
   193  	collector, err := NewPrometheusCollector("Prometheus", configFile, 100, containerHandler, http.DefaultClient)
   194  	assert.NoError(err)
   195  	assert.Equal(collector.name, "Prometheus")
   196  	assert.Equal(collector.configFile.Endpoint.URL, "http://localhost:8080/metrics")
   197  
   198  	tempServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   199  
   200  		text := `# HELP go_gc_duration_seconds A summary of the GC invocation durations.
   201  # TYPE go_gc_duration_seconds summary
   202  go_gc_duration_seconds{quantile="0"} 5.8348000000000004e-05
   203  go_gc_duration_seconds{quantile="1"} 0.000499764
   204  go_gc_duration_seconds_sum 1.7560473e+07
   205  go_gc_duration_seconds_count 2693
   206  # HELP go_goroutines Number of goroutines that currently exist.
   207  # TYPE go_goroutines gauge
   208  go_goroutines 16
   209  `
   210  		fmt.Fprintln(w, text)
   211  	}))
   212  
   213  	defer tempServer.Close()
   214  
   215  	collector.configFile.Endpoint.URL = tempServer.URL
   216  	metrics := map[string][]v1.MetricVal{}
   217  	_, metrics, errMetric := collector.Collect(metrics)
   218  
   219  	assert.NoError(errMetric)
   220  	assert.Len(metrics, 1)
   221  
   222  	goRoutines := metrics["go_goroutines"]
   223  	assert.Equal(goRoutines[0].FloatValue, float64(16))
   224  }
   225  
   226  func TestPrometheusFiltersMetricsCountLimit(t *testing.T) {
   227  	assert := assert.New(t)
   228  
   229  	// Create a prometheus collector using the config file 'sample_config_prometheus_filtered.json'
   230  	configFile, err := os.ReadFile("config/sample_config_prometheus_filtered.json")
   231  	assert.NoError(err)
   232  	containerHandler := containertest.NewMockContainerHandler("mockContainer")
   233  	_, err = NewPrometheusCollector("Prometheus", configFile, 1, containerHandler, http.DefaultClient)
   234  	assert.Error(err)
   235  }