forked from jaegertracing/jaeger
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[jaeger-v2] Add
remotesampling
extension (jaegertracing#5389)
## Description of the changes - Part of jaegertracing#5531 - adds static sampling support for otel-based jaeger-v2. - supports hot reload - added unit tests ## How was this change tested? - `go run -tags=ui ./cmd/jaeger --config ./cmd/jaeger/config-badger.yaml` - `make test` ## Checklist - [x] I have read https://github.com/jaegertracing/jaeger/blob/master/CONTRIBUTING_GUIDELINES.md - [x] I have signed all commits - [x] I have added unit tests for the new functionality - [ ] I have run lint and test steps successfully - for `jaeger`: `make lint test` - for `jaeger-ui`: `yarn lint` and `yarn test` --------- Signed-off-by: pushkarm029 <pushkarmishra029@gmail.com> Signed-off-by: Yuri Shkuro <github@ysh.us> Signed-off-by: Pushkar Mishra <pushkarmishra029@gmail.com> Co-authored-by: Yuri Shkuro <yurishkuro@users.noreply.github.com> Co-authored-by: Yuri Shkuro <github@ysh.us>
- Loading branch information
1 parent
ed90e30
commit cd5c1f7
Showing
25 changed files
with
1,506 additions
and
63 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
// Copyright (c) 2024 The Jaeger Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package remotesampling | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/asaskevich/govalidator" | ||
"go.opentelemetry.io/collector/component" | ||
"go.opentelemetry.io/collector/config/configgrpc" | ||
"go.opentelemetry.io/collector/config/confighttp" | ||
"go.opentelemetry.io/collector/confmap" | ||
|
||
"github.com/jaegertracing/jaeger/plugin/sampling/strategyprovider/adaptive" | ||
) | ||
|
||
var ( | ||
errNoProvider = errors.New("no sampling strategy provider specified, expecting 'adaptive' or 'file'") | ||
errMultipleProviders = errors.New("only one sampling strategy provider can be specified, 'adaptive' or 'file'") | ||
) | ||
|
||
var ( | ||
_ component.Config = (*Config)(nil) | ||
_ component.ConfigValidator = (*Config)(nil) | ||
_ confmap.Unmarshaler = (*Config)(nil) | ||
) | ||
|
||
type Config struct { | ||
File *FileConfig `mapstructure:"file"` | ||
Adaptive *AdaptiveConfig `mapstructure:"adaptive"` | ||
HTTP *confighttp.ServerConfig `mapstructure:"http"` | ||
GRPC *configgrpc.ServerConfig `mapstructure:"grpc"` | ||
} | ||
|
||
type FileConfig struct { | ||
// File specifies a local file as the source of sampling strategies. | ||
Path string `valid:"required" mapstructure:"path"` | ||
} | ||
|
||
type AdaptiveConfig struct { | ||
// SamplingStore is the name of the storage defined in the jaegerstorage extension. | ||
SamplingStore string `valid:"required" mapstructure:"sampling_store"` | ||
|
||
adaptive.Options `mapstructure:",squash"` | ||
} | ||
|
||
// Unmarshal is a custom unmarshaler that allows the factory to provide default values | ||
// for nested configs (like GRPC endpoint) yes still reset the pointers to nil if the | ||
// config did not contain the corresponding sections. | ||
// This is a workaround for the lack of opional fields support in OTEL confmap. | ||
// Issue: https://github.com/open-telemetry/opentelemetry-collector/issues/10266 | ||
func (cfg *Config) Unmarshal(conf *confmap.Conf) error { | ||
// first load the config normally | ||
err := conf.Unmarshal(cfg) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// use string names of fields to see if they are set in the confmap | ||
if !conf.IsSet("file") { | ||
cfg.File = nil | ||
} | ||
|
||
if !conf.IsSet("adaptive") { | ||
cfg.Adaptive = nil | ||
} | ||
|
||
if !conf.IsSet("grpc") { | ||
cfg.GRPC = nil | ||
} | ||
|
||
if !conf.IsSet("http") { | ||
cfg.HTTP = nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (cfg *Config) Validate() error { | ||
if cfg.File == nil && cfg.Adaptive == nil { | ||
return errNoProvider | ||
} | ||
|
||
if cfg.File != nil && cfg.Adaptive != nil { | ||
return errMultipleProviders | ||
} | ||
|
||
_, err := govalidator.ValidateStruct(cfg) | ||
return err | ||
} |
134 changes: 134 additions & 0 deletions
134
cmd/jaeger/internal/extension/remotesampling/config_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// Copyright (c) 2024 The Jaeger Authors. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package remotesampling | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
"go.opentelemetry.io/collector/confmap" | ||
) | ||
|
||
func Test_Validate(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
config *Config | ||
expectedErr string | ||
}{ | ||
{ | ||
name: "No provider specified", | ||
config: &Config{}, | ||
expectedErr: "no sampling strategy provider specified, expecting 'adaptive' or 'file'", | ||
}, | ||
{ | ||
name: "Both providers specified", | ||
config: &Config{ | ||
File: &FileConfig{Path: "test-path"}, | ||
Adaptive: &AdaptiveConfig{SamplingStore: "test-store"}, | ||
}, | ||
expectedErr: "only one sampling strategy provider can be specified, 'adaptive' or 'file'", | ||
}, | ||
{ | ||
name: "Only File provider specified", | ||
config: &Config{ | ||
File: &FileConfig{Path: "test-path"}, | ||
}, | ||
expectedErr: "", | ||
}, | ||
{ | ||
name: "Only Adaptive provider specified", | ||
config: &Config{ | ||
Adaptive: &AdaptiveConfig{SamplingStore: "test-store"}, | ||
}, | ||
expectedErr: "", | ||
}, | ||
{ | ||
name: "Invalid File provider", | ||
config: &Config{ | ||
File: &FileConfig{Path: ""}, | ||
}, | ||
expectedErr: "File.Path: non zero value required", | ||
}, | ||
{ | ||
name: "Invalid Adaptive provider", | ||
config: &Config{ | ||
Adaptive: &AdaptiveConfig{SamplingStore: ""}, | ||
}, | ||
expectedErr: "Adaptive.SamplingStore: non zero value required", | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
err := tt.config.Validate() | ||
if tt.expectedErr == "" { | ||
require.NoError(t, err) | ||
} else { | ||
assert.Equal(t, tt.expectedErr, err.Error()) | ||
} | ||
}) | ||
} | ||
} | ||
|
||
func Test_Unmarshal(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
input map[string]any | ||
expectedCfg *Config | ||
expectedErr string | ||
}{ | ||
{ | ||
name: "Valid config with File", | ||
input: map[string]any{ | ||
"file": map[string]any{ | ||
"path": "test-path", | ||
}, | ||
}, | ||
expectedCfg: &Config{ | ||
File: &FileConfig{Path: "test-path"}, | ||
}, | ||
expectedErr: "", | ||
}, | ||
{ | ||
name: "Valid config with Adaptive", | ||
input: map[string]any{ | ||
"adaptive": map[string]any{ | ||
"sampling_store": "test-store", | ||
}, | ||
}, | ||
expectedCfg: &Config{ | ||
Adaptive: &AdaptiveConfig{SamplingStore: "test-store"}, | ||
}, | ||
expectedErr: "", | ||
}, | ||
{ | ||
name: "Empty config", | ||
input: map[string]any{}, | ||
expectedCfg: &Config{}, | ||
expectedErr: "", | ||
}, | ||
{ | ||
name: "Invalid config", | ||
input: map[string]any{ | ||
"foo": "bar", | ||
}, | ||
expectedErr: "invalid keys: foo", // sensitive to lib implementation | ||
}, | ||
} | ||
|
||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
conf := confmap.NewFromStringMap(tt.input) | ||
var cfg Config | ||
err := cfg.Unmarshal(conf) | ||
if tt.expectedErr == "" { | ||
require.NoError(t, err) | ||
assert.Equal(t, tt.expectedCfg, &cfg) | ||
} else { | ||
assert.ErrorContains(t, err, tt.expectedErr) | ||
} | ||
}) | ||
} | ||
} |
Oops, something went wrong.