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  }