gitlab.com/gitlab-org/labkit@v1.21.0/monitoring/start_options_test.go (about)

     1  package monitoring
     2  
     3  import (
     4  	"net"
     5  	"net/http"
     6  	"runtime/debug"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/prometheus/client_golang/prometheus"
    11  	dto "github.com/prometheus/client_model/go"
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  type customGatherer struct {
    17  }
    18  
    19  func (c customGatherer) Gather() ([]*dto.MetricFamily, error) {
    20  	return nil, nil
    21  }
    22  
    23  type customRegisterer struct {
    24  }
    25  
    26  func (c customRegisterer) Register(collector prometheus.Collector) error {
    27  	return nil
    28  }
    29  
    30  func (c customRegisterer) MustRegister(collector ...prometheus.Collector) {
    31  }
    32  
    33  func (c customRegisterer) Unregister(collector prometheus.Collector) bool {
    34  	return false
    35  }
    36  
    37  func checkDefaultGatherer(t *testing.T, g prometheus.Gatherer) {
    38  	t.Helper()
    39  
    40  	assert.Equal(t, prometheus.DefaultGatherer, g)
    41  }
    42  
    43  func checkCustomGatherer(t *testing.T, g prometheus.Gatherer) {
    44  	t.Helper()
    45  
    46  	assert.Equal(t, customGatherer{}, g)
    47  }
    48  
    49  func checkDefaultRegisterer(t *testing.T, g prometheus.Registerer) {
    50  	t.Helper()
    51  
    52  	assert.Equal(t, prometheus.DefaultRegisterer, g)
    53  }
    54  
    55  func checkCustomRegisterer(t *testing.T, g prometheus.Registerer) {
    56  	t.Helper()
    57  
    58  	assert.Equal(t, customRegisterer{}, g)
    59  }
    60  func checkDefaultListener(t *testing.T, f listenerFactory) {
    61  	t.Helper()
    62  
    63  	gotListener, err := f()
    64  	require.Exactly(t, nil, gotListener)
    65  	require.NoError(t, err)
    66  }
    67  
    68  func isTCPListener(t *testing.T, f listenerFactory) {
    69  	t.Helper()
    70  
    71  	gotListener, err := f()
    72  	require.NoError(t, err)
    73  	require.IsType(t, &net.TCPListener{}, gotListener)
    74  }
    75  
    76  func Test_applyOptions(t *testing.T) {
    77  	testListener, err := net.Listen("tcp", ":0")
    78  	require.NoError(t, err)
    79  	defer testListener.Close()
    80  
    81  	isTestListener := func(t *testing.T, f listenerFactory) {
    82  		t.Helper()
    83  
    84  		gotListener, err := f()
    85  		require.NoError(t, err)
    86  		require.Exactly(t, testListener, gotListener)
    87  	}
    88  
    89  	testMux := http.NewServeMux()
    90  	testMux.HandleFunc("/debug/foo", func(writer http.ResponseWriter, r *http.Request) {})
    91  
    92  	testServer := &http.Server{
    93  		ReadTimeout: 1 * time.Second,
    94  	}
    95  
    96  	tests := []struct {
    97  		name                            string
    98  		opts                            []Option
    99  		wantListenerCheck               func(t *testing.T, f listenerFactory)
   100  		wantGathererCheck               func(t *testing.T, g prometheus.Gatherer)
   101  		wantRegistererCheck             func(t *testing.T, g prometheus.Registerer)
   102  		wantbuildInfoGaugeLabels        prometheus.Labels
   103  		wantVersion                     string
   104  		wantContinuousProfilingDisabled bool
   105  		wantMetricsDisabled             bool
   106  		wantPprofDisabled               bool
   107  		wantMetricsHandlerPattern       string
   108  		wantProfilerCredentialsFile     string
   109  		wantServeMux                    *http.ServeMux
   110  		wantServer                      *http.Server
   111  	}{
   112  		{
   113  			name:                      "empty",
   114  			opts:                      nil,
   115  			wantListenerCheck:         checkDefaultListener,
   116  			wantGathererCheck:         checkDefaultGatherer,
   117  			wantRegistererCheck:       checkDefaultRegisterer,
   118  			wantMetricsHandlerPattern: "/metrics",
   119  			wantServeMux:              http.NewServeMux(),
   120  			wantServer:                &http.Server{},
   121  		},
   122  		{
   123  			name:                      "with_server",
   124  			opts:                      []Option{WithServer(testServer)},
   125  			wantListenerCheck:         checkDefaultListener,
   126  			wantGathererCheck:         checkDefaultGatherer,
   127  			wantRegistererCheck:       checkDefaultRegisterer,
   128  			wantMetricsHandlerPattern: "/metrics",
   129  			wantServeMux:              http.NewServeMux(),
   130  			wantServer:                testServer,
   131  		},
   132  		{
   133  			name:                      "with_listener",
   134  			opts:                      []Option{WithListener(testListener)},
   135  			wantListenerCheck:         isTestListener,
   136  			wantGathererCheck:         checkDefaultGatherer,
   137  			wantRegistererCheck:       checkDefaultRegisterer,
   138  			wantMetricsHandlerPattern: "/metrics",
   139  			wantServeMux:              http.NewServeMux(),
   140  			wantServer:                &http.Server{},
   141  		},
   142  		{
   143  			name:                      "with_listen_address",
   144  			opts:                      []Option{WithListenerAddress(":0")},
   145  			wantListenerCheck:         isTCPListener,
   146  			wantGathererCheck:         checkDefaultGatherer,
   147  			wantRegistererCheck:       checkDefaultRegisterer,
   148  			wantMetricsHandlerPattern: "/metrics",
   149  			wantServeMux:              http.NewServeMux(),
   150  			wantServer:                &http.Server{},
   151  		},
   152  		{
   153  			name:                      "with_build_information",
   154  			opts:                      []Option{WithBuildInformation("1.0.0", "2018-01-02T00:00:00Z")},
   155  			wantListenerCheck:         checkDefaultListener,
   156  			wantGathererCheck:         checkDefaultGatherer,
   157  			wantRegistererCheck:       checkDefaultRegisterer,
   158  			wantbuildInfoGaugeLabels:  prometheus.Labels{"built": "2018-01-02T00:00:00Z", "version": "1.0.0"},
   159  			wantVersion:               "1.0.0",
   160  			wantMetricsHandlerPattern: "/metrics",
   161  			wantServeMux:              http.NewServeMux(),
   162  			wantServer:                &http.Server{},
   163  		},
   164  		{
   165  			name:                      "with_build_extra_labels",
   166  			opts:                      []Option{WithBuildExtraLabels(map[string]string{"git_version": "2.0.0"})},
   167  			wantListenerCheck:         checkDefaultListener,
   168  			wantGathererCheck:         checkDefaultGatherer,
   169  			wantRegistererCheck:       checkDefaultRegisterer,
   170  			wantbuildInfoGaugeLabels:  prometheus.Labels{"git_version": "2.0.0"},
   171  			wantMetricsHandlerPattern: "/metrics",
   172  			wantServeMux:              http.NewServeMux(),
   173  			wantServer:                &http.Server{},
   174  		},
   175  		{
   176  			name: "with_build_information_and_extra_labels",
   177  			opts: []Option{
   178  				WithBuildInformation("1.0.0", "2018-01-02T00:00:00Z"),
   179  				WithBuildExtraLabels(map[string]string{"git_version": "2.0.0"}),
   180  			},
   181  			wantListenerCheck:   checkDefaultListener,
   182  			wantGathererCheck:   checkDefaultGatherer,
   183  			wantRegistererCheck: checkDefaultRegisterer,
   184  			wantbuildInfoGaugeLabels: prometheus.Labels{
   185  				"built":       "2018-01-02T00:00:00Z",
   186  				"version":     "1.0.0",
   187  				"git_version": "2.0.0",
   188  			},
   189  			wantVersion:               "1.0.0",
   190  			wantMetricsHandlerPattern: "/metrics",
   191  			wantServeMux:              http.NewServeMux(),
   192  			wantServer:                &http.Server{},
   193  		},
   194  		{
   195  			name: "Go build information",
   196  			opts: []Option{
   197  				WithGoBuildInformation(&debug.BuildInfo{
   198  					GoVersion: "1.18",
   199  					Path:      "gitlab.com/gitlab-org/labkit",
   200  					Main: debug.Module{
   201  						Version: "1.0.0",
   202  					},
   203  					Settings: []debug.BuildSetting{
   204  						{Key: "vcs.revision", Value: "61b68cb5bb5c906a89bf3009e5f229caaccb6317"},
   205  						{Key: "vcs.modified", Value: "false"},
   206  						{Key: "vcs.time", Value: "2018-01-02T00:00:00Z"},
   207  					},
   208  				}),
   209  			},
   210  			wantListenerCheck:   checkDefaultListener,
   211  			wantGathererCheck:   checkDefaultGatherer,
   212  			wantRegistererCheck: checkDefaultRegisterer,
   213  			wantbuildInfoGaugeLabels: prometheus.Labels{
   214  				"committed":      "2018-01-02T00:00:00Z",
   215  				"go_version":     "1.18",
   216  				"module_path":    "gitlab.com/gitlab-org/labkit",
   217  				"module_version": "1.0.0",
   218  				"modified":       "false",
   219  				"version":        "61b68cb5bb5c906a89bf3009e5f229caaccb6317",
   220  			},
   221  			wantVersion:               "61b68cb5bb5c906a89bf3009e5f229caaccb6317",
   222  			wantMetricsHandlerPattern: "/metrics",
   223  			wantServeMux:              http.NewServeMux(),
   224  			wantServer:                &http.Server{},
   225  		},
   226  		{
   227  			name: "combined",
   228  			opts: []Option{
   229  				WithListenerAddress(":0"),
   230  				WithBuildInformation("1.0.0", "2018-01-02T00:00:00Z"),
   231  				WithBuildExtraLabels(map[string]string{"git_version": "2.0.0"}),
   232  			},
   233  			wantListenerCheck:   isTCPListener,
   234  			wantGathererCheck:   checkDefaultGatherer,
   235  			wantRegistererCheck: checkDefaultRegisterer,
   236  			wantbuildInfoGaugeLabels: prometheus.Labels{
   237  				"built":       "2018-01-02T00:00:00Z",
   238  				"version":     "1.0.0",
   239  				"git_version": "2.0.0",
   240  			},
   241  			wantVersion:               "1.0.0",
   242  			wantMetricsHandlerPattern: "/metrics",
   243  			wantServeMux:              http.NewServeMux(),
   244  			wantServer:                &http.Server{},
   245  		},
   246  		{
   247  			name:                            "without continuous profiling",
   248  			opts:                            []Option{WithoutContinuousProfiling()},
   249  			wantListenerCheck:               checkDefaultListener,
   250  			wantGathererCheck:               checkDefaultGatherer,
   251  			wantRegistererCheck:             checkDefaultRegisterer,
   252  			wantContinuousProfilingDisabled: true,
   253  			wantMetricsHandlerPattern:       "/metrics",
   254  			wantServeMux:                    http.NewServeMux(),
   255  			wantServer:                      &http.Server{},
   256  		},
   257  		{
   258  			name:                      "without metrics",
   259  			opts:                      []Option{WithoutMetrics()},
   260  			wantListenerCheck:         checkDefaultListener,
   261  			wantGathererCheck:         checkDefaultGatherer,
   262  			wantRegistererCheck:       checkDefaultRegisterer,
   263  			wantMetricsDisabled:       true,
   264  			wantMetricsHandlerPattern: "/metrics",
   265  			wantServeMux:              http.NewServeMux(),
   266  			wantServer:                &http.Server{},
   267  		},
   268  		{
   269  			name:                      "without pprof",
   270  			opts:                      []Option{WithoutPprof()},
   271  			wantListenerCheck:         checkDefaultListener,
   272  			wantGathererCheck:         checkDefaultGatherer,
   273  			wantRegistererCheck:       checkDefaultRegisterer,
   274  			wantPprofDisabled:         true,
   275  			wantMetricsHandlerPattern: "/metrics",
   276  			wantServeMux:              http.NewServeMux(),
   277  			wantServer:                &http.Server{},
   278  		},
   279  		{
   280  			name:                      "with custom metrics handler pattern",
   281  			opts:                      []Option{WithMetricsHandlerPattern("/foo")},
   282  			wantListenerCheck:         checkDefaultListener,
   283  			wantGathererCheck:         checkDefaultGatherer,
   284  			wantRegistererCheck:       checkDefaultRegisterer,
   285  			wantMetricsHandlerPattern: "/foo",
   286  			wantServeMux:              http.NewServeMux(),
   287  			wantServer:                &http.Server{},
   288  		},
   289  		{
   290  			name:                        "with profiler credentials file",
   291  			opts:                        []Option{WithProfilerCredentialsFile("/path/to/credentials.json")},
   292  			wantListenerCheck:           checkDefaultListener,
   293  			wantGathererCheck:           checkDefaultGatherer,
   294  			wantRegistererCheck:         checkDefaultRegisterer,
   295  			wantMetricsHandlerPattern:   "/metrics",
   296  			wantProfilerCredentialsFile: "/path/to/credentials.json",
   297  			wantServeMux:                http.NewServeMux(),
   298  			wantServer:                  &http.Server{},
   299  		},
   300  		{
   301  			name:                      "with custom gatherer",
   302  			opts:                      []Option{WithPrometheusGatherer(customGatherer{})},
   303  			wantListenerCheck:         checkDefaultListener,
   304  			wantGathererCheck:         checkCustomGatherer,
   305  			wantRegistererCheck:       checkDefaultRegisterer,
   306  			wantMetricsHandlerPattern: "/metrics",
   307  			wantServeMux:              http.NewServeMux(),
   308  			wantServer:                &http.Server{},
   309  		},
   310  		{
   311  			name:                      "with custom registerer",
   312  			opts:                      []Option{WithPrometheusRegisterer(customRegisterer{})},
   313  			wantListenerCheck:         checkDefaultListener,
   314  			wantGathererCheck:         checkDefaultGatherer,
   315  			wantRegistererCheck:       checkCustomRegisterer,
   316  			wantMetricsHandlerPattern: "/metrics",
   317  			wantServeMux:              http.NewServeMux(),
   318  			wantServer:                &http.Server{},
   319  		},
   320  		{
   321  			name:                      "with custom mux",
   322  			opts:                      []Option{WithServeMux(testMux)},
   323  			wantListenerCheck:         checkDefaultListener,
   324  			wantGathererCheck:         checkDefaultGatherer,
   325  			wantRegistererCheck:       checkDefaultRegisterer,
   326  			wantMetricsHandlerPattern: "/metrics",
   327  			wantServeMux:              testMux,
   328  			wantServer:                &http.Server{},
   329  		},
   330  		{
   331  			name:                      "with custom mux and server",
   332  			opts:                      []Option{WithServeMux(testMux), WithServer(testServer)},
   333  			wantListenerCheck:         checkDefaultListener,
   334  			wantGathererCheck:         checkDefaultGatherer,
   335  			wantRegistererCheck:       checkDefaultRegisterer,
   336  			wantMetricsHandlerPattern: "/metrics",
   337  			wantServeMux:              testMux,
   338  			wantServer:                testServer,
   339  		},
   340  	}
   341  	for _, tt := range tests {
   342  		t.Run(tt.name, func(t *testing.T) {
   343  			got := applyOptions(tt.opts)
   344  			tt.wantListenerCheck(t, got.listenerFactory)
   345  			tt.wantGathererCheck(t, got.gatherer)
   346  			tt.wantRegistererCheck(t, got.registerer)
   347  			require.Equal(t, tt.wantVersion, got.version)
   348  			require.Equal(t, tt.wantContinuousProfilingDisabled, got.continuousProfilingDisabled)
   349  			require.Equal(t, tt.wantMetricsDisabled, got.metricsDisabled)
   350  			require.Equal(t, tt.wantPprofDisabled, got.pprofDisabled)
   351  			require.Equal(t, tt.wantMetricsHandlerPattern, got.metricsHandlerPattern)
   352  			require.Equal(t, tt.wantProfilerCredentialsFile, got.profilerCredentialsFile)
   353  			require.Equal(t, tt.wantServeMux, got.serveMux)
   354  			require.Equal(t, tt.wantServer, got.server)
   355  
   356  			if tt.wantbuildInfoGaugeLabels == nil {
   357  				require.Equal(t, prometheus.Labels{}, got.buildInfoGaugeLabels)
   358  			} else {
   359  				require.Equal(t, tt.wantbuildInfoGaugeLabels, got.buildInfoGaugeLabels)
   360  			}
   361  		})
   362  	}
   363  }