1// Copyright 2017, OpenCensus 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
15package trace
16
17import (
18	"encoding/binary"
19)
20
21const defaultSamplingProbability = 1e-4
22
23// Sampler decides whether a trace should be sampled and exported.
24type Sampler func(SamplingParameters) SamplingDecision
25
26// SamplingParameters contains the values passed to a Sampler.
27type SamplingParameters struct {
28	ParentContext   SpanContext
29	TraceID         TraceID
30	SpanID          SpanID
31	Name            string
32	HasRemoteParent bool
33}
34
35// SamplingDecision is the value returned by a Sampler.
36type SamplingDecision struct {
37	Sample bool
38}
39
40// ProbabilitySampler returns a Sampler that samples a given fraction of traces.
41//
42// It also samples spans whose parents are sampled.
43func ProbabilitySampler(fraction float64) Sampler {
44	if !(fraction >= 0) {
45		fraction = 0
46	} else if fraction >= 1 {
47		return AlwaysSample()
48	}
49
50	traceIDUpperBound := uint64(fraction * (1 << 63))
51	return Sampler(func(p SamplingParameters) SamplingDecision {
52		if p.ParentContext.IsSampled() {
53			return SamplingDecision{Sample: true}
54		}
55		x := binary.BigEndian.Uint64(p.TraceID[0:8]) >> 1
56		return SamplingDecision{Sample: x < traceIDUpperBound}
57	})
58}
59
60// AlwaysSample returns a Sampler that samples every trace.
61// Be careful about using this sampler in a production application with
62// significant traffic: a new trace will be started and exported for every
63// request.
64func AlwaysSample() Sampler {
65	return func(p SamplingParameters) SamplingDecision {
66		return SamplingDecision{Sample: true}
67	}
68}
69
70// NeverSample returns a Sampler that samples no traces.
71func NeverSample() Sampler {
72	return func(p SamplingParameters) SamplingDecision {
73		return SamplingDecision{Sample: false}
74	}
75}
76