Skip to content
This repository was archived by the owner on Jun 14, 2023. It is now read-only.

Commit 5ff73ea

Browse files
author
xbkaishui
authored
Add tracer sampler (#73)
1 parent fdae247 commit 5ff73ea

7 files changed

+170
-5
lines changed

README.md

+8
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@ if err != nil {
3232
}
3333
defer r.Close()
3434
tracer, err := go2sky.NewTracer("example", go2sky.WithReporter(r))
35+
// create with sampler
36+
// tracer, err := go2sky.NewTracer("example", go2sky.WithReporter(r), go2sky.WithSampler(0.5))
37+
```
38+
39+
You can also create tracer with sampling rate.
40+
```go
41+
....
42+
tracer, err := go2sky.NewTracer("example", go2sky.WithReporter(r), go2sky.WithSampler(0.5))
3543
```
3644

3745
## Create span

sampler.go

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Licensed to SkyAPM org under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. SkyAPM org 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 go2sky
19+
20+
import (
21+
"math/rand"
22+
"time"
23+
)
24+
25+
type Sampler interface {
26+
IsSampled(operation string) (sampled bool)
27+
}
28+
29+
type ConstSampler struct {
30+
decision bool
31+
}
32+
33+
// NewConstSampler creates a ConstSampler.
34+
func NewConstSampler(sample bool) *ConstSampler {
35+
s := &ConstSampler{
36+
decision: sample,
37+
}
38+
return s
39+
}
40+
41+
// IsSampled implements IsSampled() of Sampler.
42+
func (s *ConstSampler) IsSampled(operation string) bool {
43+
return s.decision
44+
}
45+
46+
type RandomSampler struct {
47+
samplingRate float64
48+
rand *rand.Rand
49+
threshold int
50+
}
51+
52+
// IsSampled implements IsSampled() of Sampler.
53+
func (s *RandomSampler) IsSampled(operation string) bool {
54+
return s.threshold >= s.rand.Intn(100)
55+
}
56+
57+
func (s *RandomSampler) init() {
58+
s.rand = rand.New(rand.NewSource(time.Now().Unix()))
59+
s.threshold = int(s.samplingRate * 100)
60+
}
61+
62+
func NewRandomSampler(samplingRate float64) *RandomSampler {
63+
s := &RandomSampler{
64+
samplingRate: samplingRate,
65+
}
66+
s.init()
67+
return s
68+
}

sampler_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Licensed to SkyAPM org under one or more contributor
2+
// license agreements. See the NOTICE file distributed with
3+
// this work for additional information regarding copyright
4+
// ownership. SkyAPM org 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 go2sky
19+
20+
import (
21+
"testing"
22+
)
23+
24+
func TestConstSampler_IsSampled(t *testing.T) {
25+
sampler := NewConstSampler(true)
26+
operationName := "op"
27+
sampled := sampler.IsSampled(operationName)
28+
if sampled != true {
29+
t.Errorf("const sampler should be sampled")
30+
}
31+
samplerNegative := NewConstSampler(false)
32+
sampledNegative := samplerNegative.IsSampled(operationName)
33+
if sampledNegative != false {
34+
t.Errorf("const sampler should not be sampled")
35+
}
36+
}
37+
38+
func TestRandomSampler_IsSampled(t *testing.T) {
39+
randomSampler := NewRandomSampler(0.5)
40+
//just for test case
41+
randomSampler.threshold = 100
42+
operationName := "op"
43+
sampled := randomSampler.IsSampled(operationName)
44+
if sampled != true {
45+
t.Errorf("const sampler should be sampled")
46+
}
47+
}

span_opts.go

+7
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@ func WithSpanType(spanType SpanType) SpanOption {
3535
s.SpanType = spanType
3636
}
3737
}
38+
39+
// WithOperationName setup span OperationName of a span
40+
func WithOperationName(operationName string) SpanOption {
41+
return func(s *defaultSpan) {
42+
s.OperationName = operationName
43+
}
44+
}

trace.go

+23-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type Tracer struct {
4040
reporter Reporter
4141
// 0 not init 1 init
4242
initFlag int32
43+
sampler Sampler
4344
}
4445

4546
// TracerOption allows for functional options to adjust behaviour
@@ -70,6 +71,10 @@ func NewTracer(service string, opts ...TracerOption) (tracer *Tracer, err error)
7071
t.reporter.Boot(t.service, t.instance)
7172
t.initFlag = 1
7273
}
74+
75+
if t.sampler == nil {
76+
t.sampler = NewConstSampler(true)
77+
}
7378
return t, nil
7479
}
7580

@@ -93,11 +98,10 @@ func (t *Tracer) CreateEntrySpan(ctx context.Context, operationName string, extr
9398
return
9499
}
95100
}
96-
s, nCtx, err = t.CreateLocalSpan(ctx, WithContext(refSc), WithSpanType(SpanTypeEntry))
101+
s, nCtx, err = t.CreateLocalSpan(ctx, WithContext(refSc), WithSpanType(SpanTypeEntry), WithOperationName(operationName))
97102
if err != nil {
98103
return
99104
}
100-
s.SetOperationName(operationName)
101105
return
102106
}
103107

@@ -117,6 +121,17 @@ func (t *Tracer) CreateLocalSpan(ctx context.Context, opts ...SpanOption) (s Spa
117121
if !ok {
118122
parentSpan = nil
119123
}
124+
isForceSample := len(ds.Refs) > 0
125+
// Try to sample when it is not force sample
126+
if parentSpan == nil && !isForceSample {
127+
// Force sample
128+
sampled := t.sampler.IsSampled(ds.OperationName)
129+
if !sampled {
130+
// Filter by sample just return noop span
131+
s = &NoopSpan{}
132+
return s, context.WithValue(ctx, ctxKeyInstance, s), nil
133+
}
134+
}
120135
s, err = newSegmentSpan(ds, parentSpan)
121136
if err != nil {
122137
return nil, nil, err
@@ -132,11 +147,15 @@ func (t *Tracer) CreateExitSpan(ctx context.Context, operationName string, peer
132147
if s, _ := t.createNoop(ctx); s != nil {
133148
return s, nil
134149
}
135-
s, _, err := t.CreateLocalSpan(ctx, WithSpanType(SpanTypeExit))
150+
s, _, err := t.CreateLocalSpan(ctx, WithSpanType(SpanTypeExit), WithOperationName(operationName))
136151
if err != nil {
137152
return nil, err
138153
}
139-
s.SetOperationName(operationName)
154+
noopSpan, ok := interface{}(s).(NoopSpan)
155+
if ok {
156+
// Ignored, there is no need to inject SW8 in the request header
157+
return &noopSpan, nil
158+
}
140159
s.SetPeer(peer)
141160
spanContext := &propagation.SpanContext{}
142161
span, ok := s.(ReportedSpan)

trace_opts.go

+16
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,19 @@ func WithInstance(instance string) TracerOption {
3030
t.instance = instance
3131
}
3232
}
33+
34+
// WithSampler setup sampler
35+
func WithSampler(samplingRate float64) TracerOption {
36+
return func(t *Tracer) {
37+
var sampler Sampler
38+
//check const sampler
39+
if samplingRate <= 0 {
40+
sampler = NewConstSampler(false)
41+
} else if samplingRate >= 1.0 {
42+
sampler = NewConstSampler(true)
43+
} else {
44+
sampler = NewRandomSampler(samplingRate)
45+
}
46+
t.sampler = sampler
47+
}
48+
}

trace_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ func TestNewTracer(t *testing.T) {
181181
service string
182182
opts []TracerOption
183183
}{service: "test", opts: nil},
184-
&Tracer{service: "test"},
184+
&Tracer{service: "test", sampler: NewConstSampler(true)},
185185
false,
186186
},
187187
}

0 commit comments

Comments
 (0)