From a54a8a27c48675dcd98c5a5f1dc70e88d147d17e Mon Sep 17 00:00:00 2001 From: rghetia Date: Thu, 22 Aug 2019 09:57:27 -0700 Subject: [PATCH] Add Sampler API (#70) - also add implementation of AlwaysSampleSampler and NeverSampleSampler --- api/trace/always_sampler.go | 52 ++++++++++++++++++++++++++++++++ api/trace/always_sampler_test.go | 39 ++++++++++++++++++++++++ api/trace/never_sampler.go | 52 ++++++++++++++++++++++++++++++++ api/trace/never_sampler_test.go | 39 ++++++++++++++++++++++++ api/trace/sampler.go | 44 +++++++++++++++++++++++++++ 5 files changed, 226 insertions(+) create mode 100644 api/trace/always_sampler.go create mode 100644 api/trace/always_sampler_test.go create mode 100644 api/trace/never_sampler.go create mode 100644 api/trace/never_sampler_test.go create mode 100644 api/trace/sampler.go diff --git a/api/trace/always_sampler.go b/api/trace/always_sampler.go new file mode 100644 index 000000000000..f23c2adfb274 --- /dev/null +++ b/api/trace/always_sampler.go @@ -0,0 +1,52 @@ +// Copyright 2019, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace + +import ( + "go.opentelemetry.io/api/core" +) + +const ( + alwaysSamplerDescription = "AlwaysSampleSampler" +) + +var alwaysSampleDecision = Decision{Sampled: true} + +type alwaysSampleSampler struct{} + +// ShouldSample implements Sampler interface. +// It always returns a Decision with Sampled value set to true +// and with Attributes set to an empty slice. +func (as alwaysSampleSampler) ShouldSample( + _ core.SpanContext, + _ bool, + _ core.TraceID, + _ uint64, + _ string, +) Decision { + return alwaysSampleDecision +} + +// Description implements Sampler interface. +// It returns the description of this sampler. +func (as alwaysSampleSampler) Description() string { + return alwaysSamplerDescription +} + +var _ Sampler = alwaysSampleSampler{} + +func AlwaysSampleSampler() alwaysSampleSampler { + return alwaysSampleSampler{} +} diff --git a/api/trace/always_sampler_test.go b/api/trace/always_sampler_test.go new file mode 100644 index 000000000000..e9fc7ee27e5b --- /dev/null +++ b/api/trace/always_sampler_test.go @@ -0,0 +1,39 @@ +// Copyright 2019, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "go.opentelemetry.io/api/core" +) + +func TestShouldSample(t *testing.T) { + gotD := AlwaysSampleSampler().ShouldSample( + core.SpanContext{}, false, core.TraceID{}, 0, "span") + wantD := Decision{Sampled: true} + if diff := cmp.Diff(wantD, gotD); diff != "" { + t.Errorf("Decision: +got, -want%v", diff) + } +} + +func TestDescription(t *testing.T) { + gotDesc := AlwaysSampleSampler().Description() + wantDesc := alwaysSamplerDescription + if diff := cmp.Diff(wantDesc, gotDesc); diff != "" { + t.Errorf("Description: +got, -want%v", diff) + } +} diff --git a/api/trace/never_sampler.go b/api/trace/never_sampler.go new file mode 100644 index 000000000000..3cdce92e903c --- /dev/null +++ b/api/trace/never_sampler.go @@ -0,0 +1,52 @@ +// Copyright 2019, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace + +import ( + "go.opentelemetry.io/api/core" +) + +const ( + neverSamplerDescription = "NeverSampleSampler" +) + +var neverSampledecision = Decision{Sampled: false} + +type neverSampleSampler struct{} + +// ShouldSample implements Sampler interface. +// It always returns a Decision with Sampled value set to false +// and with Attributes set to an empty slice. +func (ns neverSampleSampler) ShouldSample( + _ core.SpanContext, + _ bool, + _ core.TraceID, + _ uint64, + _ string, +) Decision { + return neverSampledecision +} + +// Description implements Sampler interface. +// It returns the description of this sampler. +func (ns neverSampleSampler) Description() string { + return neverSamplerDescription +} + +var _ Sampler = neverSampleSampler{} + +func NeverSampleSampler() neverSampleSampler { + return neverSampleSampler{} +} diff --git a/api/trace/never_sampler_test.go b/api/trace/never_sampler_test.go new file mode 100644 index 000000000000..3f1e7598f7b7 --- /dev/null +++ b/api/trace/never_sampler_test.go @@ -0,0 +1,39 @@ +// Copyright 2019, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "go.opentelemetry.io/api/core" +) + +func TestNeverSamperShouldSample(t *testing.T) { + gotD := NeverSampleSampler().ShouldSample( + core.SpanContext{}, false, core.TraceID{}, 0, "span") + wantD := Decision{Sampled: false} + if diff := cmp.Diff(wantD, gotD); diff != "" { + t.Errorf("Decision: +got, -want%v", diff) + } +} + +func TestNeverSamplerDescription(t *testing.T) { + gotDesc := NeverSampleSampler().Description() + wantDesc := neverSamplerDescription + if diff := cmp.Diff(wantDesc, gotDesc); diff != "" { + t.Errorf("Description: +got, -want%v", diff) + } +} diff --git a/api/trace/sampler.go b/api/trace/sampler.go new file mode 100644 index 000000000000..c0598305980b --- /dev/null +++ b/api/trace/sampler.go @@ -0,0 +1,44 @@ +// Copyright 2019, OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package trace + +import "go.opentelemetry.io/api/core" + +type Sampler interface { + // ShouldSample returns a Decision that contains a decision whether to sample + // or not sample the span to be created. Decision is based on a Sampler specific + // algorithm that takes into account one or more input parameters. + ShouldSample( + sc core.SpanContext, + remote bool, + traceID core.TraceID, + spanID uint64, + spanName string, + ) Decision + + // Description returns of the sampler. It contains its name or short description + // and its configured properties. + // For example 'ProbabilitySampler:{0.00001}' + Description() string +} + +type Decision struct { + // Sampled is set true if the span should be sampled. + Sampled bool + + // Attributes provides insight into Sample r's decision process. + // It could be empty slice or nil if no attributes are recorded by the sampler. + Attributes []core.KeyValue +}