func (r *CentralizedRule) snapshot() *xraySvc.SamplingStatisticsDocument {
	r.mu.Lock()
	name := &r.ruleName
	requests, sampled, borrows := r.requests, r.sampled, r.borrows
	r.requests, r.sampled, r.borrows = 0, 0, 0
	r.mu.Unlock()
	now := r.clock.Now()
	s := &xraySvc.SamplingStatisticsDocument{
		RequestCount: &requests,
		SampledCount: &sampled,
		BorrowCount:  &borrows,
		RuleName:     name,
		Timestamp:    &now,
	}
	return s
}
snapshot takes a snapshot of the sampling statistics counters, returning
xraySvc.SamplingStatistics. It also resets statistics counters.
package sampling
import (
	"sync"
	"github.com/aws/aws-xray-sdk-go/internal/logger"
	"github.com/aws/aws-xray-sdk-go/pattern"
	"github.com/aws/aws-xray-sdk-go/utils"
	xraySvc "github.com/aws/aws-sdk-go/service/xray"
)
type Properties struct {
	ServiceName string  `json:"service_name"`
	Host        string  `json:"host"`
	HTTPMethod  string  `json:"http_method"`
	URLPath     string  `json:"url_path"`
	FixedTarget int64   `json:"fixed_target"`
	Rate        float64 `json:"rate"`
}
func (p *Properties) AppliesTo(host, path, method string) bool {
	return (host == "" || pattern.WildcardMatchCaseInsensitive(p.Host, host)) &&
		(path == "" || pattern.WildcardMatchCaseInsensitive(p.URLPath, path)) &&
		(method == "" || pattern.WildcardMatchCaseInsensitive(p.HTTPMethod, method))
}
func (r *CentralizedRule) AppliesTo(request *Request) bool {
	return (request.Host == "" || pattern.WildcardMatchCaseInsensitive(r.Host, request.Host)) &&
		(request.URL == "" || pattern.WildcardMatchCaseInsensitive(r.URLPath, request.URL)) &&
		(request.Method == "" || pattern.WildcardMatchCaseInsensitive(r.HTTPMethod, request.Method)) &&
		(request.ServiceName == "" || pattern.WildcardMatchCaseInsensitive(r.ServiceName, request.ServiceName)) &&
		(request.ServiceType == "" || pattern.WildcardMatchCaseInsensitive(r.serviceType, request.ServiceType))
}
type CentralizedRule struct {
	reservoir *CentralizedReservoir
	ruleName string
	priority int64
	requests int64
	sampled int64
	borrows int64
	usedAt int64
	*Properties
	serviceType string
	resourceARN string
	attributes map[string]*string
	clock utils.Clock
	rand utils.Rand
	mu sync.RWMutex
}
func (r *CentralizedRule) stale(now int64) bool {
	r.mu.RLock()
	defer r.mu.RUnlock()
	return r.requests != 0 && now >= r.reservoir.refreshedAt+r.reservoir.interval
}
func (r *CentralizedRule) Sample() *Decision {
	now := r.clock.Now().Unix()
	sd := &Decision{
		Rule: &r.ruleName,
	}
	r.mu.Lock()
	defer r.mu.Unlock()
	r.requests++
	if r.reservoir.expired(now) {
		if r.reservoir.borrow(now) {
			logger.Debugf(
				"Sampling target has expired for rule %s. Borrowing a request.",
				r.ruleName,
			)
			sd.Sample = true
			r.borrows++
			return sd
		}
		logger.Debugf(
			"Sampling target has expired for rule %s. Using fixed rate.",
			r.ruleName,
		)
		sd.Sample = r.bernoulliSample()
		return sd
	}
	if r.reservoir.Take(now) {
		r.sampled++
		sd.Sample = true
		return sd
	}
	logger.Debugf(
		"Sampling target has been exhausted for rule %s. Using fixed rate.",
		r.ruleName,
	)
	sd.Sample = r.bernoulliSample()
	return sd
}
func (r *CentralizedRule) bernoulliSample() bool {
	if r.rand.Float64() < r.Rate {
		r.sampled++
		return true
	}
	return false
}