Skip to content

Commit

Permalink
Implement factory and config for sampling processor (head-based) (#186)
Browse files Browse the repository at this point in the history
* Implement factory and config for sampling processor (head-based)

* Change Config name
  • Loading branch information
MohamedElqdusy authored and Paulo Janotti committed Jul 26, 2019
1 parent b907e01 commit 11a0a2a
Show file tree
Hide file tree
Showing 8 changed files with 264 additions and 30 deletions.
29 changes: 29 additions & 0 deletions processor/tracesamplerprocessor/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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
//
// https://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 tracesamplerprocessor

import "github.com/open-telemetry/opentelemetry-service/config/configmodels"

// Config has the configuration guiding the trace sampler processor.
type Config struct {
configmodels.ProcessorSettings `mapstructure:",squash"`
// SamplingPercentage is the percentage rate at which traces are going to be sampled. Defaults to zero, i.e.: no sample.
// Values greater or equal 100 are treated as "sample all traces".
SamplingPercentage float32 `mapstructure:"sampling-percentage"`
// HashSeed allows one to configure the hashing seed. This is important in scenarios where multiple layers of collectors
// have different sampling rates: if they use the same seed all passing one layer may pass the other even if they have
// different sampling rates, configuring different seeds avoids that.
HashSeed uint32 `mapstructure:"hash-seed"`
}
73 changes: 73 additions & 0 deletions processor/tracesamplerprocessor/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// 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
//
// https://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 tracesamplerprocessor

import (
"path"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/open-telemetry/opentelemetry-service/config"
"github.com/open-telemetry/opentelemetry-service/config/configmodels"
"github.com/open-telemetry/opentelemetry-service/processor"
)

func TestLoadConfig(t *testing.T) {
receivers, processors, exporters, err := config.ExampleComponents()
assert.Nil(t, err)

factory := &Factory{}
processors[typeStr] = factory
cfg, err := config.LoadConfigFile(
t, path.Join(".", "testdata", "config.yaml"), receivers, processors, exporters,
)

require.Nil(t, err)
require.NotNil(t, cfg)

p0 := cfg.Processors["trace-sampler"]
assert.Equal(t, p0,
&Config{
ProcessorSettings: configmodels.ProcessorSettings{
TypeVal: "trace-sampler",
NameVal: "trace-sampler",
},
SamplingPercentage: 15.3,
HashSeed: 22,
})

}

func TestLoadConfigEmpty(t *testing.T) {
receivers, _, exporters, err := config.ExampleComponents()
processors, err := processor.Build(&Factory{})
require.NotNil(t, processors)
require.NoError(t, err)

config, err := config.LoadConfigFile(
t,
path.Join(".", "testdata", "empty.yaml"),
receivers,
processors,
exporters)

require.Nil(t, err)
require.NotNil(t, config)
p0 := config.Processors["trace-sampler"]
factory := &Factory{}
assert.Equal(t, p0, factory.CreateDefaultConfig())
}
67 changes: 67 additions & 0 deletions processor/tracesamplerprocessor/factory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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
//
// https://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 tracesamplerprocessor

import (
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-service/config/configerror"
"github.com/open-telemetry/opentelemetry-service/config/configmodels"
"github.com/open-telemetry/opentelemetry-service/consumer"
"github.com/open-telemetry/opentelemetry-service/processor"
)

const (
// The value of "type" trace-samplers in configuration.
typeStr = "trace-sampler"
)

// Factory is the factory for trace-sample processor.
type Factory struct {
}

// Type gets the type of the config created by this factory.
func (f *Factory) Type() string {
return typeStr
}

// CreateDefaultConfig creates the default configuration for processor.
func (f *Factory) CreateDefaultConfig() configmodels.Processor {
return &Config{
ProcessorSettings: configmodels.ProcessorSettings{
TypeVal: typeStr,
NameVal: typeStr,
},
}
}

// CreateTraceProcessor creates a trace processor based on this config.
func (f *Factory) CreateTraceProcessor(
logger *zap.Logger,
nextConsumer consumer.TraceConsumer,
cfg configmodels.Processor,
) (processor.TraceProcessor, error) {
oCfg := cfg.(*Config)
return NewTraceProcessor(nextConsumer, *oCfg)
}

// CreateMetricsProcessor creates a metrics processor based on this config.
func (f *Factory) CreateMetricsProcessor(
logger *zap.Logger,
nextConsumer consumer.MetricsConsumer,
cfg configmodels.Processor,
) (processor.MetricsProcessor, error) {
return nil, configerror.ErrDataTypeIsNotSupported
}
45 changes: 45 additions & 0 deletions processor/tracesamplerprocessor/factory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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
//
// https://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 tracesamplerprocessor

import (
"testing"

"github.com/stretchr/testify/assert"
"go.uber.org/zap"

"github.com/open-telemetry/opentelemetry-service/exporter/exportertest"
)

func TestCreateDefaultConfig(t *testing.T) {
factory := &Factory{}

cfg := factory.CreateDefaultConfig()
assert.NotNil(t, cfg, "failed to create default config")
}

func TestCreateProcessor(t *testing.T) {
factory := &Factory{}

cfg := factory.CreateDefaultConfig()

tp, err := factory.CreateTraceProcessor(zap.NewNop(), exportertest.NewNopTraceExporter(), cfg)
assert.NotNil(t, tp)
assert.NoError(t, err, "cannot create trace processor")

mp, err := factory.CreateMetricsProcessor(zap.NewNop(), nil, cfg)
assert.Nil(t, mp)
assert.Error(t, err, "should not be able to create metric processor")
}
16 changes: 16 additions & 0 deletions processor/tracesamplerprocessor/testdata/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
receivers:
examplereceiver:

processors:
trace-sampler:
sampling-percentage: 15.3
hash-seed: 22

exporters:
exampleexporter:

pipelines:
traces:
receivers: [examplereceiver]
processors: [trace-sampler]
exporters: [exampleexporter]
15 changes: 15 additions & 0 deletions processor/tracesamplerprocessor/testdata/empty.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
receivers:
examplereceiver:

processors:
trace-sampler:


exporters:
exampleexporter:

pipelines:
traces:
receivers: [examplereceiver]
processors: [trace-sampler]
exporters: [exampleexporter]
17 changes: 3 additions & 14 deletions processor/tracesamplerprocessor/tracesamplerprocessor.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,8 @@ const (
percentageScaleFactor = numHashBuckets / 100.0
)

// TraceSamplerCfg has the configuration guiding the trace sampler processor.
type TraceSamplerCfg struct {
// SamplingPercentage is the percentage rate at which traces are going to be sampled. Defaults to zero, i.e.: no sample.
// Values greater or equal 100 are treated as "sample all traces".
SamplingPercentage float32
// HashSeed allows one to configure the hashing seed. This is important in scenarios where multiple layers of collectors
// have different sampling rates: if they use the same seed all passing one layer may pass the other even if they have
// different sampling rates, configuring different seeds avoids that.
HashSeed uint32
}

// InitFromViper updates TraceSamplerCfg according to the viper configuration.
func (tsc *TraceSamplerCfg) InitFromViper(v *viper.Viper) (*TraceSamplerCfg, error) {
// InitFromViper updates TraceSampler config according to the viper configuration.
func (tsc *Config) InitFromViper(v *viper.Viper) (*Config, error) {
if v == nil {
return nil, errors.New("v is nil")
}
Expand All @@ -73,7 +62,7 @@ var _ processor.TraceProcessor = (*tracesamplerprocessor)(nil)

// NewTraceProcessor returns a processor.TraceProcessor that will perform head sampling according to the given
// configuration.
func NewTraceProcessor(nextConsumer consumer.TraceConsumer, cfg TraceSamplerCfg) (processor.TraceProcessor, error) {
func NewTraceProcessor(nextConsumer consumer.TraceConsumer, cfg Config) (processor.TraceProcessor, error) {
if nextConsumer == nil {
return nil, errors.New("nextConsumer is nil")
}
Expand Down
Loading

0 comments on commit 11a0a2a

Please sign in to comment.