k8s.io/kubernetes@v1.29.3/test/integration/logs/benchmark/load_test.go (about) 1 /* 2 Copyright 2021 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 benchmark 18 19 import ( 20 "bytes" 21 "errors" 22 "strings" 23 "testing" 24 25 "github.com/stretchr/testify/assert" 26 27 logsapi "k8s.io/component-base/logs/api/v1" 28 _ "k8s.io/component-base/logs/json/register" 29 runtimev1 "k8s.io/cri-api/pkg/apis/runtime/v1" 30 "k8s.io/klog/v2" 31 ) 32 33 func TestData(t *testing.T) { 34 versionResponse := &runtimev1.VersionResponse{ 35 Version: "0.1.0", 36 RuntimeName: "containerd", 37 RuntimeVersion: "v1.6.18", 38 RuntimeApiVersion: "v1", 39 } 40 41 testcases := map[string]struct { 42 messages []logMessage 43 // These are subsets of the full output and may be empty. 44 // Prefix and variable stack traces therefore aren't compared. 45 printf, structured, json string 46 stats logStats 47 }{ 48 "data/simple.log": { 49 messages: []logMessage{ 50 { 51 msg: "Pod status updated", 52 }, 53 }, 54 printf: `Pod status updated: []`, 55 structured: `"Pod status updated"`, 56 json: `"msg":"Pod status updated","v":0`, 57 stats: logStats{ 58 TotalLines: 1, 59 JsonLines: 1, 60 ArgCounts: map[string]int{}, 61 }, 62 }, 63 "data/split.log": { 64 messages: []logMessage{ 65 { 66 msg: "Pod status updated", 67 }, 68 { 69 msg: "Pod status updated again", 70 }, 71 }, 72 stats: logStats{ 73 TotalLines: 3, 74 SplitLines: 1, 75 JsonLines: 2, 76 ArgCounts: map[string]int{}, 77 }, 78 }, 79 "data/error.log": { 80 messages: []logMessage{ 81 { 82 msg: "Pod status update", 83 err: errors.New("failed"), 84 isError: true, 85 }, 86 }, 87 printf: `Pod status update: failed []`, 88 structured: `"Pod status update" err="failed"`, 89 json: `"msg":"Pod status update","err":"failed"`, 90 stats: logStats{ 91 TotalLines: 1, 92 JsonLines: 1, 93 ErrorMessages: 1, 94 ArgCounts: map[string]int{ 95 stringArg: 1, 96 totalArg: 1, 97 }, 98 }, 99 }, 100 "data/error-value.log": { 101 messages: []logMessage{ 102 { 103 msg: "Pod status update", 104 kvs: []interface{}{"err", errors.New("failed")}, 105 }, 106 }, 107 printf: `Pod status update: [err failed]`, 108 structured: `"Pod status update" err="failed"`, 109 json: `"msg":"Pod status update","v":0,"err":"failed"`, 110 stats: logStats{ 111 TotalLines: 1, 112 JsonLines: 1, 113 ArgCounts: map[string]int{ 114 stringArg: 1, 115 totalArg: 1, 116 }, 117 }, 118 }, 119 "data/values.log": { 120 messages: []logMessage{ 121 { 122 msg: "Example", 123 kvs: []interface{}{ 124 "pod", klog.KRef("system", "kube-scheduler"), 125 "pv", klog.KRef("", "volume"), 126 "someString", "hello world", 127 "someValue", 1.0, 128 }, 129 }, 130 }, 131 printf: `Example: [pod system/kube-scheduler pv volume someString hello world someValue 1]`, 132 structured: `"Example" pod="system/kube-scheduler" pv="volume" someString="hello world" someValue=1`, 133 json: `"msg":"Example","v":0,"pod":{"name":"kube-scheduler","namespace":"system"},"pv":{"name":"volume"},"someString":"hello world","someValue":1`, 134 stats: logStats{ 135 TotalLines: 1, 136 JsonLines: 1, 137 ArgCounts: map[string]int{ 138 stringArg: 1, 139 krefArg: 2, 140 numberArg: 1, 141 totalArg: 4, 142 }, 143 }, 144 }, 145 "data/versionresponse.log": { 146 messages: []logMessage{ 147 { 148 msg: "[RemoteRuntimeService] Version Response", 149 verbosity: 10, 150 kvs: []interface{}{ 151 "apiVersion", versionResponse, 152 }, 153 }, 154 }, 155 printf: `[RemoteRuntimeService] Version Response: [apiVersion &VersionResponse{Version:0.1.0,RuntimeName:containerd,RuntimeVersion:v1.6.18,RuntimeApiVersion:v1,}]`, 156 structured: `"[RemoteRuntimeService] Version Response" apiVersion="&VersionResponse{Version:0.1.0,RuntimeName:containerd,RuntimeVersion:v1.6.18,RuntimeApiVersion:v1,}"`, 157 // Because of 158 // https://github.com/kubernetes/kubernetes/issues/106652 159 // we get the string instead of a JSON struct. 160 json: `"msg":"[RemoteRuntimeService] Version Response","v":0,"apiVersion":"&VersionResponse{Version:0.1.0,RuntimeName:containerd,RuntimeVersion:v1.6.18,RuntimeApiVersion:v1,}"`, 161 stats: logStats{ 162 TotalLines: 1, 163 JsonLines: 1, 164 ArgCounts: map[string]int{ 165 totalArg: 1, 166 otherArg: 1, 167 }, 168 OtherArgs: []interface{}{ 169 versionResponse, 170 }, 171 }, 172 }, 173 } 174 175 for filePath, expected := range testcases { 176 t.Run(filePath, func(t *testing.T) { 177 messages, stats, err := loadLog(filePath) 178 if err != nil { 179 t.Fatalf("unexpected load error: %v", err) 180 } 181 assert.Equal(t, expected.messages, messages) 182 assert.Equal(t, expected.stats, stats) 183 printAll := func(format func(item logMessage)) { 184 for _, item := range expected.messages { 185 format(item) 186 } 187 } 188 testBuffered := func(t *testing.T, expected string, format string, print func(item logMessage)) { 189 var buffer bytes.Buffer 190 c := logsapi.NewLoggingConfiguration() 191 c.Format = format 192 o := logsapi.LoggingOptions{ 193 ErrorStream: &buffer, 194 InfoStream: &buffer, 195 } 196 klog.SetOutput(&buffer) 197 defer func() { 198 if err := logsapi.ResetForTest(nil); err != nil { 199 t.Errorf("Unexpected error resetting the logging configuration: %v", err) 200 } 201 }() 202 if err := logsapi.ValidateAndApplyWithOptions(c, &o, nil); err != nil { 203 t.Fatalf("Unexpected error configuring logging: %v", err) 204 } 205 206 printAll(print) 207 klog.Flush() 208 209 if !strings.Contains(buffer.String(), expected) { 210 t.Errorf("Expected log output to contain:\n%s\nActual log output:\n%s\n", expected, buffer.String()) 211 } 212 } 213 214 t.Run("printf", func(t *testing.T) { 215 testBuffered(t, expected.printf, "text", printf) 216 }) 217 t.Run("structured", func(t *testing.T) { 218 testBuffered(t, expected.structured, "text", printLogger) 219 }) 220 t.Run("json", func(t *testing.T) { 221 testBuffered(t, expected.json, "json", printLogger) 222 }) 223 }) 224 } 225 }