github.com/waldiirawan/apm-agent-go/v2@v2.2.2/sampler_test.go (about)

     1  // Licensed to Elasticsearch B.V. under one or more contributor
     2  // license agreements. See the NOTICE file distributed with
     3  // this work for additional information regarding copyright
     4  // ownership. Elasticsearch B.V. licenses this file to you under
     5  // the Apache License, Version 2.0 (the "License"); you may
     6  // not use this file except in compliance with the License.
     7  // You may obtain a copy of the License at
     8  //
     9  //     http://www.apache.org/licenses/LICENSE-2.0
    10  //
    11  // Unless required by applicable law or agreed to in writing,
    12  // software distributed under the License is distributed on an
    13  // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    14  // KIND, either express or implied.  See the License for the
    15  // specific language governing permissions and limitations
    16  // under the License.
    17  
    18  package apm_test
    19  
    20  import (
    21  	"encoding/binary"
    22  	"math/rand"
    23  	"sync"
    24  	"testing"
    25  
    26  	"github.com/stretchr/testify/assert"
    27  
    28  	"github.com/waldiirawan/apm-agent-go/v2"
    29  )
    30  
    31  func TestRatioSampler(t *testing.T) {
    32  	ratio := 0.75
    33  	s := apm.NewRatioSampler(ratio)
    34  
    35  	const (
    36  		numGoroutines = 100
    37  		numIterations = 1000
    38  	)
    39  
    40  	sampled := make([]int, numGoroutines)
    41  	var wg sync.WaitGroup
    42  	for i := 0; i < numGoroutines; i++ {
    43  		wg.Add(1)
    44  		go func(i int) {
    45  			defer wg.Done()
    46  
    47  			// fixed seed to avoid intermittent failures
    48  			rng := rand.New(rand.NewSource(int64(i)))
    49  			for j := 0; j < numIterations; j++ {
    50  				var traceContext apm.TraceContext
    51  				binary.LittleEndian.PutUint64(traceContext.Span[:], rng.Uint64())
    52  				result := s.Sample(apm.SampleParams{TraceContext: traceContext})
    53  				assert.Equal(t, ratio, result.SampleRate)
    54  				if result.Sampled {
    55  					sampled[i]++
    56  				}
    57  			}
    58  
    59  		}(i)
    60  	}
    61  	wg.Wait()
    62  
    63  	var total int
    64  	for i := 0; i < numGoroutines; i++ {
    65  		total += sampled[i]
    66  	}
    67  	assert.InDelta(t, ratio, float64(total)/(numGoroutines*numIterations), 0.1)
    68  }
    69  
    70  func TestRatioSamplerAlways(t *testing.T) {
    71  	s := apm.NewRatioSampler(1.0)
    72  	assert.False(t, s.Sample(apm.SampleParams{TraceContext: apm.TraceContext{}}).Sampled) // invalid span ID
    73  	assert.True(t, s.Sample(apm.SampleParams{TraceContext: apm.TraceContext{
    74  		Span: apm.SpanID{0, 0, 0, 0, 0, 0, 0, 1},
    75  	}}).Sampled)
    76  	assert.True(t, s.Sample(apm.SampleParams{TraceContext: apm.TraceContext{
    77  		Span: apm.SpanID{255, 255, 255, 255, 255, 255, 255, 255},
    78  	}}).Sampled)
    79  }
    80  
    81  func TestRatioSamplerNever(t *testing.T) {
    82  	s := apm.NewRatioSampler(0)
    83  	assert.False(t, s.Sample(apm.SampleParams{TraceContext: apm.TraceContext{}}).Sampled) // invalid span ID
    84  	assert.False(t, s.Sample(apm.SampleParams{TraceContext: apm.TraceContext{
    85  		Span: apm.SpanID{0, 0, 0, 0, 0, 0, 0, 1},
    86  	}}).Sampled)
    87  	assert.False(t, s.Sample(apm.SampleParams{TraceContext: apm.TraceContext{
    88  		Span: apm.SpanID{255, 255, 255, 255, 255, 255, 255, 255},
    89  	}}).Sampled)
    90  }
    91  
    92  func TestRatioSamplerPrecision(t *testing.T) {
    93  	ratios := map[float64]float64{
    94  		0.00001: 0.0001,
    95  		0.55554: 0.5555,
    96  		0.55555: 0.5556,
    97  		0.55556: 0.5556,
    98  	}
    99  	for r, want := range ratios {
   100  		s := apm.NewRatioSampler(r)
   101  		got := s.Sample(apm.SampleParams{}).SampleRate
   102  		assert.Equal(t, want, got)
   103  	}
   104  }