github.com/Axway/agent-sdk@v1.1.101/pkg/traceability/sampling/sample.go (about) 1 package sampling 2 3 import ( 4 "fmt" 5 "sync" 6 7 "github.com/elastic/beats/v7/libbeat/publisher" 8 ) 9 10 // sample - private struct that is used to keep track of the samples being taken 11 type sample struct { 12 config Sampling 13 currentCounts map[string]int 14 counterLock sync.Mutex 15 } 16 17 // ShouldSampleTransaction - receives the transaction details and returns true to sample it false to not 18 func (s *sample) ShouldSampleTransaction(details TransactionDetails) bool { 19 hasFailedStatus := details.Status == "Failure" 20 // sample only failed transaction if OnlyErrors is set to `true` and the transaction summary's status is an error 21 if !hasFailedStatus && s.config.OnlyErrors { 22 return false 23 } 24 25 sampleGlobal := s.shouldSampleWithCounter(globalCounter) 26 perAPIEnabled := s.config.PerAPI && details.APIID != "" 27 28 if s.config.PerSub && details.SubID != "" { 29 apiSamp := false 30 if perAPIEnabled { 31 apiSamp = s.shouldSampleWithCounter(details.APIID) 32 } 33 return s.shouldSampleWithCounter(fmt.Sprintf("%s-%s", details.APIID, details.SubID)) || apiSamp 34 } 35 36 if perAPIEnabled { 37 return s.shouldSampleWithCounter(details.APIID) 38 } 39 40 return sampleGlobal 41 } 42 43 func (s *sample) shouldSampleWithCounter(counterName string) bool { 44 s.counterLock.Lock() 45 defer s.counterLock.Unlock() 46 // check if counter needs initiated 47 if _, found := s.currentCounts[counterName]; !found { 48 s.currentCounts[counterName] = 0 49 } 50 51 // Only sampling on percentage, not currently looking at the details 52 shouldSample := false 53 if s.currentCounts[counterName] < s.config.shouldSampleMax { 54 shouldSample = true 55 } 56 s.currentCounts[counterName]++ 57 58 // reset the count once we hit 100 * 10^(nb_decimals) messages 59 if s.currentCounts[counterName] == s.config.countMax { 60 s.currentCounts[counterName] = 0 61 } 62 63 // return if we should sample this transaction 64 return shouldSample 65 } 66 67 // FilterEvents - returns an array of events that are part of the sample 68 func (s *sample) FilterEvents(events []publisher.Event) []publisher.Event { 69 if s.config.Percentage == countMax { 70 return events // all events are sampled by default 71 } 72 73 sampledEvents := make([]publisher.Event, 0) 74 for _, event := range events { 75 if _, sampled := event.Content.Meta[SampleKey]; sampled { 76 sampledEvents = append(sampledEvents, event) 77 } 78 } 79 80 return sampledEvents 81 }