1// Copyright The OpenTelemetry Authors 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// +build windows 16 17package loadscraper 18 19import ( 20 "context" 21 "testing" 22 "time" 23 24 "github.com/stretchr/testify/assert" 25 "github.com/stretchr/testify/require" 26 "go.uber.org/zap" 27 28 "go.opentelemetry.io/collector/receiver/hostmetricsreceiver/internal/perfcounters" 29) 30 31func TestStartSampling(t *testing.T) { 32 // override sampling frequency to 2ms 33 samplingFrequency = 2 * time.Millisecond 34 35 // startSampling should set up perf counter and start sampling 36 startSampling(context.Background(), zap.NewNop()) 37 assertSamplingUnderway(t) 38 39 // override the processor queue length perf counter with a mock 40 // that will ensure a positive value is returned 41 assert.IsType(t, &perfcounters.PerfLibScraper{}, samplerInstance.perfCounterScraper) 42 samplerInstance.perfCounterScraper = perfcounters.NewMockPerfCounterScraper(map[string]map[string][]int64{ 43 system: {processorQueueLength: {100}}, 44 }) 45 46 // second call to startSampling should succeed, but not do anything 47 startSampling(context.Background(), zap.NewNop()) 48 assertSamplingUnderway(t) 49 assert.IsType(t, &perfcounters.MockPerfCounterScraper{}, samplerInstance.perfCounterScraper) 50 51 // ensure that a positive load avg is returned by a call to 52 // "getSampledLoadAverages" which validates the value from the 53 // mock perf counter was used 54 require.Eventually(t, func() bool { 55 avgLoadValues, err := getSampledLoadAverages() 56 assert.NoError(t, err) 57 return avgLoadValues.Load1 > 0 && avgLoadValues.Load5 > 0 && avgLoadValues.Load15 > 0 58 }, time.Second, time.Millisecond, "Load Avg was not set after 1s") 59 60 // sampling should continue after first call to stopSampling since 61 // startSampling was called twice 62 stopSampling(context.Background()) 63 assertSamplingUnderway(t) 64 65 // second call to stopSampling should close perf counter, stop 66 // sampling, and clean up the sampler 67 stopSampling(context.Background()) 68 assertSamplingStopped(t) 69} 70 71func assertSamplingUnderway(t *testing.T) { 72 assert.NotNil(t, samplerInstance) 73 assert.NotNil(t, samplerInstance.perfCounterScraper) 74 75 select { 76 case <-samplerInstance.done: 77 assert.Fail(t, "Load scraper sampling done channel unexpectedly closed") 78 default: 79 } 80} 81 82func assertSamplingStopped(t *testing.T) { 83 select { 84 case <-samplerInstance.done: 85 default: 86 assert.Fail(t, "Load scraper sampling done channel not closed") 87 } 88} 89 90func TestSampleLoad(t *testing.T) { 91 counterReturnValues := []int64{10, 20, 30, 40, 50} 92 mockPerfCounterScraper := perfcounters.NewMockPerfCounterScraper(map[string]map[string][]int64{ 93 system: {processorQueueLength: counterReturnValues}, 94 }) 95 96 samplerInstance = &sampler{perfCounterScraper: mockPerfCounterScraper} 97 98 for i := 0; i < len(counterReturnValues); i++ { 99 samplerInstance.sampleLoad() 100 } 101 102 assert.Equal(t, calcExpectedLoad(counterReturnValues, loadAvgFactor1m), samplerInstance.loadAvg1m) 103 assert.Equal(t, calcExpectedLoad(counterReturnValues, loadAvgFactor5m), samplerInstance.loadAvg5m) 104 assert.Equal(t, calcExpectedLoad(counterReturnValues, loadAvgFactor15m), samplerInstance.loadAvg15m) 105} 106 107func calcExpectedLoad(scrapedValues []int64, loadAvgFactor float64) float64 { 108 // replicate the calculations that should be performed to determine the exponentially 109 // weighted moving averages based on the specified scraped values 110 var expectedLoad float64 111 for i := 0; i < len(scrapedValues); i++ { 112 expectedLoad = expectedLoad*loadAvgFactor + float64(scrapedValues[i])*(1-loadAvgFactor) 113 } 114 return expectedLoad 115} 116 117func Benchmark_SampleLoad(b *testing.B) { 118 s, _ := newSampler(zap.NewNop()) 119 120 b.ResetTimer() 121 for n := 0; n < b.N; n++ { 122 s.sampleLoad() 123 } 124} 125