k8s.io/apiserver@v0.31.1/pkg/storage/value/encrypt/envelope/metrics/metrics_test.go (about) 1 /* 2 Copyright 2023 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package metrics 18 19 import ( 20 "fmt" 21 "strings" 22 "sync" 23 "testing" 24 "time" 25 26 "google.golang.org/grpc/codes" 27 "google.golang.org/grpc/status" 28 29 "k8s.io/apimachinery/pkg/util/rand" 30 "k8s.io/component-base/metrics/legacyregistry" 31 "k8s.io/component-base/metrics/testutil" 32 ) 33 34 const ( 35 testKeyHash1 = "sha256:6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" 36 testKeyHash2 = "sha256:d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" 37 testKeyHash3 = "sha256:4e07408562bedb8b60ce05c1decfe3ad16b72230967de01f640b7e4729b49fce" 38 testProviderNameForMetric = "providerName" 39 testAPIServerID = "testAPIServerID" 40 testAPIServerIDHash = "sha256:14f9d63e669337ac6bfda2e2162915ee6a6067743eddd4e5c374b572f951ff37" 41 ) 42 43 var ( 44 errCode = "empty" 45 ) 46 47 func TestRecordKMSOperationLatency(t *testing.T) { 48 testCases := []struct { 49 name string 50 methodName string 51 duration time.Duration 52 operationErr error 53 want string 54 }{ 55 { 56 name: "operation success", 57 methodName: "/v2alpha1.KeyManagementService/Encrypt", 58 duration: 1 * time.Second, 59 operationErr: nil, 60 want: ` 61 # HELP apiserver_envelope_encryption_kms_operations_latency_seconds [ALPHA] KMS operation duration with gRPC error code status total. 62 # TYPE apiserver_envelope_encryption_kms_operations_latency_seconds histogram 63 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0001"} 0 64 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0002"} 0 65 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0004"} 0 66 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0008"} 0 67 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0016"} 0 68 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0032"} 0 69 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0064"} 0 70 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0128"} 0 71 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0256"} 0 72 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0512"} 0 73 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.1024"} 0 74 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.2048"} 0 75 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.4096"} 0 76 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.8192"} 0 77 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="1.6384"} 1 78 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="3.2768"} 1 79 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="6.5536"} 1 80 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="13.1072"} 1 81 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="26.2144"} 1 82 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="52.4288"} 1 83 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="+Inf"} 1 84 apiserver_envelope_encryption_kms_operations_latency_seconds_sum{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 85 apiserver_envelope_encryption_kms_operations_latency_seconds_count{grpc_status_code="OK",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 86 `, 87 }, 88 { 89 name: "operation error", 90 methodName: "/v2alpha1.KeyManagementService/Encrypt", 91 duration: 1 * time.Second, 92 operationErr: status.Error(codes.Internal, "some error"), 93 want: ` 94 # HELP apiserver_envelope_encryption_kms_operations_latency_seconds [ALPHA] KMS operation duration with gRPC error code status total. 95 # TYPE apiserver_envelope_encryption_kms_operations_latency_seconds histogram 96 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0001"} 0 97 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0002"} 0 98 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0004"} 0 99 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0008"} 0 100 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0016"} 0 101 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0032"} 0 102 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0064"} 0 103 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0128"} 0 104 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0256"} 0 105 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0512"} 0 106 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.1024"} 0 107 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.2048"} 0 108 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.4096"} 0 109 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.8192"} 0 110 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="1.6384"} 1 111 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="3.2768"} 1 112 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="6.5536"} 1 113 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="13.1072"} 1 114 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="26.2144"} 1 115 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="52.4288"} 1 116 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="+Inf"} 1 117 apiserver_envelope_encryption_kms_operations_latency_seconds_sum{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 118 apiserver_envelope_encryption_kms_operations_latency_seconds_count{grpc_status_code="Internal",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 119 `, 120 }, 121 { 122 name: "wrapped not found error", 123 methodName: "/v2alpha1.KeyManagementService/Encrypt", 124 duration: 1 * time.Second, 125 operationErr: fmt.Errorf("some low level thing failed: %w", status.Error(codes.NotFound, "some error")), 126 want: ` 127 # HELP apiserver_envelope_encryption_kms_operations_latency_seconds [ALPHA] KMS operation duration with gRPC error code status total. 128 # TYPE apiserver_envelope_encryption_kms_operations_latency_seconds histogram 129 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0001"} 0 130 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0002"} 0 131 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0004"} 0 132 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0008"} 0 133 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0016"} 0 134 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0032"} 0 135 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0064"} 0 136 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0128"} 0 137 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0256"} 0 138 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0512"} 0 139 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.1024"} 0 140 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.2048"} 0 141 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.4096"} 0 142 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.8192"} 0 143 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="1.6384"} 1 144 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="3.2768"} 1 145 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="6.5536"} 1 146 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="13.1072"} 1 147 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="26.2144"} 1 148 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="52.4288"} 1 149 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="+Inf"} 1 150 apiserver_envelope_encryption_kms_operations_latency_seconds_sum{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 151 apiserver_envelope_encryption_kms_operations_latency_seconds_count{grpc_status_code="NotFound",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 152 `, 153 }, 154 { 155 name: "non gRPC error", 156 methodName: "/v2alpha1.KeyManagementService/Encrypt", 157 duration: 1 * time.Second, 158 operationErr: fmt.Errorf("some bad thing happened"), 159 want: ` 160 # HELP apiserver_envelope_encryption_kms_operations_latency_seconds [ALPHA] KMS operation duration with gRPC error code status total. 161 # TYPE apiserver_envelope_encryption_kms_operations_latency_seconds histogram 162 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0001"} 0 163 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0002"} 0 164 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0004"} 0 165 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0008"} 0 166 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0016"} 0 167 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0032"} 0 168 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0064"} 0 169 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0128"} 0 170 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0256"} 0 171 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.0512"} 0 172 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.1024"} 0 173 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.2048"} 0 174 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.4096"} 0 175 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="0.8192"} 0 176 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="1.6384"} 1 177 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="3.2768"} 1 178 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="6.5536"} 1 179 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="13.1072"} 1 180 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="26.2144"} 1 181 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="52.4288"} 1 182 apiserver_envelope_encryption_kms_operations_latency_seconds_bucket{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName",le="+Inf"} 1 183 apiserver_envelope_encryption_kms_operations_latency_seconds_sum{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 184 apiserver_envelope_encryption_kms_operations_latency_seconds_count{grpc_status_code="unknown-non-grpc",method_name="/v2alpha1.KeyManagementService/Encrypt",provider_name="providerName"} 1 185 `, 186 }, 187 } 188 189 RegisterMetrics() 190 191 for _, tt := range testCases { 192 t.Run(tt.name, func(t *testing.T) { 193 RecordKMSOperationLatency("providerName", tt.methodName, tt.duration, tt.operationErr) 194 defer KMSOperationsLatencyMetric.Reset() 195 if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tt.want), "apiserver_envelope_encryption_kms_operations_latency_seconds"); err != nil { 196 t.Fatal(err) 197 } 198 }) 199 } 200 } 201 202 func TestRecordKeyID_Serial(t *testing.T) { 203 testCases := []struct { 204 desc string 205 keyID string 206 metrics []string 207 providerName string 208 transformationType string 209 apiServerID string 210 want string 211 }{ 212 { 213 desc: "keyIDHash total", 214 keyID: "1", 215 metrics: []string{ 216 "apiserver_envelope_encryption_key_id_hash_total", 217 }, 218 providerName: testProviderNameForMetric, 219 transformationType: FromStorageLabel, 220 apiServerID: testAPIServerID, 221 want: fmt.Sprintf(` 222 # HELP apiserver_envelope_encryption_key_id_hash_total [ALPHA] Number of times a keyID is used split by transformation type, provider, and apiserver identity. 223 # TYPE apiserver_envelope_encryption_key_id_hash_total counter 224 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 225 `, testAPIServerIDHash, testKeyHash1, testProviderNameForMetric, FromStorageLabel), 226 }, 227 { 228 desc: "keyIDHash total more labels", 229 keyID: "2", 230 metrics: []string{ 231 "apiserver_envelope_encryption_key_id_hash_total", 232 }, 233 providerName: testProviderNameForMetric, 234 transformationType: FromStorageLabel, 235 apiServerID: testAPIServerID, 236 want: fmt.Sprintf(` 237 # HELP apiserver_envelope_encryption_key_id_hash_total [ALPHA] Number of times a keyID is used split by transformation type, provider, and apiserver identity. 238 # TYPE apiserver_envelope_encryption_key_id_hash_total counter 239 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 240 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 241 `, testAPIServerIDHash, testKeyHash1, testProviderNameForMetric, FromStorageLabel, testAPIServerIDHash, testKeyHash2, testProviderNameForMetric, FromStorageLabel), 242 }, 243 { 244 desc: "keyIDHash total same labels", 245 keyID: "2", 246 metrics: []string{ 247 "apiserver_envelope_encryption_key_id_hash_total", 248 }, 249 providerName: testProviderNameForMetric, 250 transformationType: FromStorageLabel, 251 apiServerID: testAPIServerID, 252 want: fmt.Sprintf(` 253 # HELP apiserver_envelope_encryption_key_id_hash_total [ALPHA] Number of times a keyID is used split by transformation type, provider, and apiserver identity. 254 # TYPE apiserver_envelope_encryption_key_id_hash_total counter 255 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 256 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 2 257 `, testAPIServerIDHash, testKeyHash1, testProviderNameForMetric, FromStorageLabel, testAPIServerIDHash, testKeyHash2, testProviderNameForMetric, FromStorageLabel), 258 }, 259 { 260 desc: "keyIDHash total exceeds limit, remove first label, and empty keyID", 261 keyID: "", 262 metrics: []string{ 263 "apiserver_envelope_encryption_key_id_hash_total", 264 }, 265 providerName: testProviderNameForMetric, 266 transformationType: FromStorageLabel, 267 apiServerID: testAPIServerID, 268 want: fmt.Sprintf(` 269 # HELP apiserver_envelope_encryption_key_id_hash_total [ALPHA] Number of times a keyID is used split by transformation type, provider, and apiserver identity. 270 # TYPE apiserver_envelope_encryption_key_id_hash_total counter 271 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 2 272 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 273 `, testAPIServerIDHash, testKeyHash2, testProviderNameForMetric, FromStorageLabel, testAPIServerIDHash, "", testProviderNameForMetric, FromStorageLabel), 274 }, 275 { 276 desc: "keyIDHash total exceeds limit, remove first label, empty keyID, and empty testAPIServerID", 277 keyID: "", 278 metrics: []string{ 279 "apiserver_envelope_encryption_key_id_hash_total", 280 }, 281 providerName: testProviderNameForMetric, 282 transformationType: FromStorageLabel, 283 apiServerID: "", 284 want: fmt.Sprintf(` 285 # HELP apiserver_envelope_encryption_key_id_hash_total [ALPHA] Number of times a keyID is used split by transformation type, provider, and apiserver identity. 286 # TYPE apiserver_envelope_encryption_key_id_hash_total counter 287 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 288 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 289 `, testAPIServerIDHash, "", testProviderNameForMetric, FromStorageLabel, "", "", testProviderNameForMetric, FromStorageLabel), 290 }, 291 { 292 desc: "keyIDHash total exceeds limit 2, remove first label", 293 keyID: "1", 294 metrics: []string{ 295 "apiserver_envelope_encryption_key_id_hash_total", 296 }, 297 providerName: testProviderNameForMetric, 298 transformationType: FromStorageLabel, 299 apiServerID: "", 300 want: fmt.Sprintf(` 301 # HELP apiserver_envelope_encryption_key_id_hash_total [ALPHA] Number of times a keyID is used split by transformation type, provider, and apiserver identity. 302 # TYPE apiserver_envelope_encryption_key_id_hash_total counter 303 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 304 apiserver_envelope_encryption_key_id_hash_total{apiserver_id_hash="%s",key_id_hash="%s",provider_name="%s",transformation_type="%s"} 1 305 `, "", "", testProviderNameForMetric, FromStorageLabel, "", testKeyHash1, testProviderNameForMetric, FromStorageLabel), 306 }, 307 } 308 309 KeyIDHashTotal.Reset() 310 cacheSize = 2 311 RegisterMetrics() 312 registerLRUMetrics() 313 314 for _, tt := range testCases { 315 t.Run(tt.desc, func(t *testing.T) { 316 RecordKeyID(tt.transformationType, tt.providerName, tt.keyID, tt.apiServerID) 317 // We are not resetting the metric here as each test is not independent in order to validate the behavior 318 // when the metric labels exceed the limit to ensure the labels are not unbounded. 319 if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tt.want), tt.metrics...); err != nil { 320 t.Fatal(err) 321 } 322 }) 323 } 324 } 325 326 func TestRecordKeyIDLRUKey(t *testing.T) { 327 RegisterMetrics() 328 329 cacheSize = 3 330 registerLRUMetrics() 331 KeyIDHashTotal.Reset() 332 defer KeyIDHashTotal.Reset() 333 334 var wg sync.WaitGroup 335 for i := 1; i < 100; i++ { 336 wg.Add(1) 337 go func() { 338 defer wg.Done() 339 keyID := rand.String(32) 340 apiServerID := rand.String(32) 341 key := metricLabels{ 342 transformationType: rand.String(32), 343 providerName: rand.String(32), 344 keyIDHash: getHash(keyID), 345 apiServerIDHash: getHash(apiServerID), 346 } 347 RecordKeyID(key.transformationType, key.providerName, keyID, apiServerID) 348 }() 349 } 350 wg.Wait() 351 352 validMetrics := 0 353 metricFamilies, err := legacyregistry.DefaultGatherer.Gather() 354 if err != nil { 355 t.Fatal(err) 356 } 357 for _, family := range metricFamilies { 358 if family.GetName() != "apiserver_envelope_encryption_key_id_hash_total" { 359 continue 360 } 361 for _, metric := range family.GetMetric() { 362 if metric.Counter.GetValue() != 1 { 363 t.Errorf("invalid metric seen: %s", metric.String()) 364 } else { 365 validMetrics++ 366 } 367 } 368 } 369 if validMetrics != cacheSize { 370 t.Fatalf("expected total valid metrics to be the same as cacheSize %d, got %d", cacheSize, validMetrics) 371 } 372 } 373 374 func TestRecordKeyIDFromStatus(t *testing.T) { 375 RegisterMetrics() 376 377 cacheSize = 3 378 registerLRUMetrics() 379 KeyIDHashStatusLastTimestampSeconds.Reset() 380 defer KeyIDHashStatusLastTimestampSeconds.Reset() 381 382 var wg sync.WaitGroup 383 for i := 1; i < 100; i++ { 384 wg.Add(1) 385 go func() { 386 defer wg.Done() 387 keyID := rand.String(32) 388 apiServerID := rand.String(32) 389 key := metricLabels{ 390 providerName: rand.String(32), 391 keyIDHash: getHash(keyID), 392 apiServerIDHash: getHash(apiServerID), 393 } 394 RecordKeyIDFromStatus(key.providerName, keyID, apiServerID) 395 }() 396 } 397 wg.Wait() 398 399 validMetrics := 0 400 metricFamilies, err := legacyregistry.DefaultGatherer.Gather() 401 if err != nil { 402 t.Fatal(err) 403 } 404 for _, family := range metricFamilies { 405 if family.GetName() != "apiserver_envelope_encryption_key_id_hash_status_last_timestamp_seconds" { 406 continue 407 } 408 for _, metric := range family.GetMetric() { 409 if metric.Gauge.GetValue() == 0 { 410 t.Errorf("invalid metric seen: %s", metric.String()) 411 } else { 412 validMetrics++ 413 } 414 } 415 } 416 if validMetrics != cacheSize { 417 t.Fatalf("expected total valid metrics to be the same as cacheSize %d, got %d", cacheSize, validMetrics) 418 } 419 } 420 421 func TestRecordInvalidKeyIDFromStatus(t *testing.T) { 422 testCases := []struct { 423 desc string 424 count int 425 metrics []string 426 providerName string 427 want string 428 }{ 429 { 430 desc: "invalid KeyID From Status Total 3", 431 count: 3, 432 metrics: []string{ 433 "apiserver_envelope_encryption_invalid_key_id_from_status_total", 434 }, 435 providerName: testProviderNameForMetric, 436 want: fmt.Sprintf(` 437 # HELP apiserver_envelope_encryption_invalid_key_id_from_status_total [ALPHA] Number of times an invalid keyID is returned by the Status RPC call split by error. 438 # TYPE apiserver_envelope_encryption_invalid_key_id_from_status_total counter 439 apiserver_envelope_encryption_invalid_key_id_from_status_total{error="%s",provider_name="%s"} %d 440 `, errCode, testProviderNameForMetric, 3), 441 }, 442 { 443 desc: "invalid KeyID From Status Total 10", 444 count: 10, 445 metrics: []string{ 446 "apiserver_envelope_encryption_invalid_key_id_from_status_total", 447 }, 448 providerName: testProviderNameForMetric, 449 want: fmt.Sprintf(` 450 # HELP apiserver_envelope_encryption_invalid_key_id_from_status_total [ALPHA] Number of times an invalid keyID is returned by the Status RPC call split by error. 451 # TYPE apiserver_envelope_encryption_invalid_key_id_from_status_total counter 452 apiserver_envelope_encryption_invalid_key_id_from_status_total{error="%s",provider_name="%s"} %d 453 `, errCode, testProviderNameForMetric, 10), 454 }, 455 } 456 457 InvalidKeyIDFromStatusTotal.Reset() 458 RegisterMetrics() 459 460 for _, tt := range testCases { 461 t.Run(tt.desc, func(t *testing.T) { 462 defer InvalidKeyIDFromStatusTotal.Reset() 463 var wg sync.WaitGroup 464 for i := 0; i < tt.count; i++ { 465 wg.Add(1) 466 go func() { 467 defer wg.Done() 468 RecordInvalidKeyIDFromStatus(tt.providerName, errCode) 469 }() 470 } 471 wg.Wait() 472 473 if err := testutil.GatherAndCompare(legacyregistry.DefaultGatherer, strings.NewReader(tt.want), tt.metrics...); err != nil { 474 t.Fatal(err) 475 } 476 }) 477 } 478 }