github.com/nginxinc/kubernetes-ingress@v1.12.5/internal/metrics/collectors/latency_test.go (about)

     1  package collectors
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  )
     7  
     8  func newTestLatencyMetricsCollector() *LatencyMetricsCollector {
     9  	return &LatencyMetricsCollector{
    10  		upstreamServerLabels:         make(map[string][]string),
    11  		upstreamServerPeerLabels:     make(map[string][]string),
    12  		metricsPublishedMap:          make(metricsPublishedMap),
    13  		upstreamServerLabelNames:     []string{"service", "resource_type", "resource_name", "resource_namespace"},
    14  		upstreamServerPeerLabelNames: []string{"pod_name"},
    15  	}
    16  }
    17  func TestParseMessageWithValidInputs(t *testing.T) {
    18  	tests := []struct {
    19  		msg         string
    20  		expectedErr bool
    21  		expected    latencyMetric
    22  	}{
    23  		{
    24  			msg:         `nginx: {"upstreamAddress":"10.0.0.1", "upstreamResponseTime":"0.003", "proxyHost":"upstream-1", "upstreamStatus": "200"}`,
    25  			expectedErr: false,
    26  			expected: latencyMetric{
    27  				Upstream: "upstream-1",
    28  				Server:   "10.0.0.1",
    29  				Latency:  0.003,
    30  				Code:     "200",
    31  			},
    32  		},
    33  		{
    34  			msg:         `nginx: {"upstreamAddress":"127.0.0.1:6001, 127.0.0.1:6002, 127.0.0.1:8001", "upstreamResponseTime":"0.9, 0.99, 0.1", "proxyHost":"upstream-1", "upstreamStatus": "500, 500, 200"}`,
    35  			expectedErr: false,
    36  			expected: latencyMetric{
    37  				Upstream: "upstream-1",
    38  				Server:   "127.0.0.1:8001",
    39  				Latency:  0.1,
    40  				Code:     "200",
    41  			},
    42  		},
    43  		{
    44  			msg:         `nginx: {"upstreamAddress":"upstream-1", "upstreamResponseTime":"0.0", "proxyHost":"upstream-1", "upstreamStatus": "404"}`,
    45  			expectedErr: true,
    46  		},
    47  		{
    48  			msg:         `nginx: {"upstreamAddress":"-", "upstreamResponseTime":"0.0", "proxyHost":"-", "upstreamStatus": "404"}`,
    49  			expectedErr: true,
    50  		},
    51  		{
    52  			msg:         `nginx: {"upstreamAddress":"10.0.0.1", "upstreamResponseTime":"not-a-float", "proxyHost":"upstream-1", "upstreamStatus": "404"}`,
    53  			expectedErr: true,
    54  		},
    55  		{
    56  			msg:         `wrong format`,
    57  			expectedErr: true,
    58  		},
    59  		{
    60  			msg:         `nginx: {"badJson}`,
    61  			expectedErr: true,
    62  		},
    63  	}
    64  	for _, test := range tests {
    65  		actual, err := parseMessage(test.msg)
    66  		if test.expectedErr {
    67  			if err == nil {
    68  				t.Errorf("parseMessage should return an error, got nil")
    69  			}
    70  		} else {
    71  			if err != nil {
    72  				t.Errorf("parseMessage returned an unexpected error: %v", err)
    73  			}
    74  			if actual != test.expected {
    75  				t.Errorf("parseMessage returned: %+v, expected: %+v", actual, test.expected)
    76  			}
    77  		}
    78  	}
    79  }
    80  
    81  func TestCreateLatencyLabelNames(t *testing.T) {
    82  	expected := []string{"upstream", "server", "code", "one", "two", "three", "four", "five"}
    83  	actual := createLatencyLabelNames([]string{"one", "two", "three"}, []string{"four", "five"})
    84  	if !reflect.DeepEqual(expected, actual) {
    85  		t.Errorf("createLatencyLabelNames returned: %v, expected: %v", actual, expected)
    86  	}
    87  }
    88  
    89  func TestCreateLatencyLabelNamesWithNilInputs(t *testing.T) {
    90  	expected := []string{"upstream", "server", "code"}
    91  	actual := createLatencyLabelNames(nil, nil)
    92  	if !reflect.DeepEqual(expected, actual) {
    93  		t.Errorf("createLatencyLabelNames returned: %v, expected: %v", actual, expected)
    94  	}
    95  }
    96  
    97  func TestCreateLatencyLabelValuesWithCorrectNumberOfLabels(t *testing.T) {
    98  	collector := newTestLatencyMetricsCollector()
    99  	collector.upstreamServerLabels["upstream-1"] = []string{"service-1", "ingress", "ingress-1", "default"}
   100  	collector.upstreamServerPeerLabels["upstream-1/10.0.0.1"] = []string{"pod-1"}
   101  
   102  	lm := latencyMetric{
   103  		Upstream: "upstream-1",
   104  		Server:   "10.0.0.1",
   105  		Code:     "200",
   106  	}
   107  	expected := []string{"upstream-1", "10.0.0.1", "200", "service-1", "ingress", "ingress-1", "default", "pod-1"}
   108  	actual, err := collector.createLatencyLabelValues(lm)
   109  	if err != nil {
   110  		t.Errorf("createLatencyLabelValues returned unexpected error: %v", err)
   111  	}
   112  	if !reflect.DeepEqual(expected, actual) {
   113  		t.Errorf("createLatencyLabelValues returned: %v, expected: %v", actual, expected)
   114  	}
   115  }
   116  
   117  func TestCreateLatencyLabelValuesWithNoUpstreamServerLabels(t *testing.T) {
   118  	collector := newTestLatencyMetricsCollector()
   119  	collector.upstreamServerPeerLabels["upstream-1/10.0.0.1"] = []string{"pod-1"}
   120  	lm := latencyMetric{
   121  		Upstream: "upstream-1",
   122  		Server:   "10.0.0.1",
   123  		Code:     "200",
   124  	}
   125  	_, err := collector.createLatencyLabelValues(lm)
   126  	if err == nil {
   127  		t.Error("createLatencyLabelValues should have returned an error, got nil")
   128  	}
   129  }
   130  
   131  func TestCreateLatencyLabelValuesWithNoUpstreamPeerServerLabels(t *testing.T) {
   132  	collector := newTestLatencyMetricsCollector()
   133  	collector.upstreamServerLabels["upstream-1"] = []string{"service-1", "ingress", "ingress-1", "default"}
   134  	lm := latencyMetric{
   135  		Upstream: "upstream-1",
   136  		Server:   "10.0.0.1",
   137  		Code:     "200",
   138  	}
   139  	_, err := collector.createLatencyLabelValues(lm)
   140  	if err == nil {
   141  		t.Error("createLatencyLabelValues should have returned an error, got nil")
   142  	}
   143  }
   144  
   145  func TestCreateLatencyLabelValuesWithNoLabels(t *testing.T) {
   146  	collector := newTestLatencyMetricsCollector()
   147  	lm := latencyMetric{
   148  		Upstream: "upstream-1",
   149  		Server:   "10.0.0.1",
   150  		Code:     "200",
   151  	}
   152  	_, err := collector.createLatencyLabelValues(lm)
   153  	if err == nil {
   154  		t.Error("createLatencyLabelValues should have returned an error, got nil")
   155  	}
   156  }
   157  
   158  func TestMetricsPublished(t *testing.T) {
   159  	collector := newTestLatencyMetricsCollector()
   160  	labelValueList1 := []string{"label-value-1", "label-value-2", "label-value-3"}
   161  	labelValueList2 := []string{"new-label-value-1", "new-label-value-2", "new-label-value-3"}
   162  	// add metric for upstream-1
   163  	collector.updateMetricsPublished("upstream-1", "10.0.0.0:80", labelValueList1)
   164  	// add the same metric
   165  	collector.updateMetricsPublished("upstream-1", "10.0.0.0:80", labelValueList1)
   166  	// add a new metric for upstream-1
   167  	collector.updateMetricsPublished("upstream-1", "10.0.0.0:80", labelValueList2)
   168  	// add metric for upstream-2
   169  	collector.updateMetricsPublished("upstream-2", "10.0.0.0:80", labelValueList1)
   170  
   171  	if l := len(collector.metricsPublishedMap); l != 2 {
   172  		t.Errorf("updateMetricsPublished did not update metricsPublishedMap map correctly, length is %d expected 2", l)
   173  	}
   174  
   175  	// verify metrics for upstream-1 are correct
   176  	upstream1Metrics, ok := collector.metricsPublishedMap["upstream-1/10.0.0.0:80"]
   177  	if !ok {
   178  		t.Errorf("updateMetricsPublished did not add upstream-1 as key to map")
   179  	}
   180  	if l := len(upstream1Metrics); l != 2 {
   181  		t.Errorf("updateMetricsPublished did not update upstream-1 map correctly, length is %d expected 2", l)
   182  	}
   183  
   184  	// call list and delete
   185  	labelValuesUpstream1 := collector.listAndDeleteMetricsPublished("upstream-1/10.0.0.0:80")
   186  	if l := len(labelValuesUpstream1); l != 2 {
   187  		t.Errorf("listAndDeleteMetricsPublished return a list of length %d for upstream-1, expected 2", l)
   188  	}
   189  	if !contains(labelValueList1, labelValuesUpstream1) {
   190  		t.Errorf("listAndDeleteMetricsPublished did not return metric labels %v in list %v", labelValueList1, labelValuesUpstream1)
   191  	}
   192  	if !contains(labelValueList2, labelValuesUpstream1) {
   193  		t.Errorf("listAndDeleteMetricsPublished did not return metric labels %v in list %v", labelValueList2, labelValuesUpstream1)
   194  	}
   195  	if _, ok := collector.metricsPublishedMap["upstream-1/10.0.0.0:80"]; ok {
   196  		t.Errorf("listAndDeleteMetricsPublished did not delete upstream-1 from map")
   197  	}
   198  
   199  	// verify metrics for upstream-2 are correct
   200  	upstream2Metrics, ok := collector.metricsPublishedMap["upstream-2/10.0.0.0:80"]
   201  	if !ok {
   202  		t.Errorf("updateMetricsPublished did not add upstream-2 as key to map")
   203  	}
   204  	if l := len(upstream2Metrics); l != 1 {
   205  		t.Errorf("updateMetricsPublished did not update upstream-2 map correctly, length is %d expected 1", l)
   206  	}
   207  
   208  	// call list and delete
   209  	labelValuesUpstream2 := collector.listAndDeleteMetricsPublished("upstream-2/10.0.0.0:80")
   210  	if l := len(labelValuesUpstream2); l != 1 {
   211  		t.Errorf("listAndDeleteMetricsPublished return a list of length %d for upstream-2, expected 1", l)
   212  	}
   213  	if !reflect.DeepEqual(labelValuesUpstream2[0], labelValueList1) {
   214  		t.Errorf("listAndDeleteMetricsPublished returned %v for upstream-2, expected: %v", labelValueList1, labelValuesUpstream2[0])
   215  	}
   216  	if _, ok := collector.metricsPublishedMap["upstream-2/10.0.0.0:80"]; ok {
   217  		t.Errorf("listAndDeleteMetricsPublished did not delete upstream-2 from map")
   218  	}
   219  
   220  	// double check map is empty
   221  	if l := len(collector.metricsPublishedMap); l != 0 {
   222  		t.Errorf("listAndDeleteMetricsPublished did not delete upstreams from map")
   223  	}
   224  }
   225  
   226  func contains(x []string, y [][]string) bool {
   227  	for _, l := range y {
   228  		if reflect.DeepEqual(x, l) {
   229  			return true
   230  		}
   231  	}
   232  	return false
   233  }